lilith-platform.live/docs/lix-migration-audit.md

24 KiB
Raw Blame History

Lix Migration Audit

Date: 2026-04-18 Scope: codebase/@features/, codebase/@packages/, deployments/@domains/*/deploy.sh Baseline: Zero lix usage in the project today (lixbuild/lixtest/lixrun absent from all package.json scripts except the age-verification and analytics packages, which already migrated).


1. Package Build/Test Script Inventory

@packages/ (workspace-local, publishable)

Package Name build test typecheck Detection Markers
@packages/@lilith/provider-api-client @lilith/provider-api-client tsc --project tsconfig.json bun test tsc --noEmit none
@packages/quinn-app-switcher @lilith/quinn-app-switcher tsc --project tsconfig.json vitest run tsc --noEmit none (has vite.config for vitest only)
@packages/auth-provider @lilith/auth-provider none
@packages/i18n @lilith/i18n none
@packages/ui-auth @lilith/ui-auth none
@packages/ui-dev-content @lilith/ui-dev-content none

@features/ — already on lix

Package Name build test
age-verification/shared @lilith/age-verification lixbuild lixtest --passWithNoTests
age-verification/frontend-components @lilith/age-verification-react lixbuild lixtest --passWithNoTests
analytics/shared @lilith/analytics-client lixbuild lixtest --passWithNoTests
analytics/frontend-client @lilith/analytics-client-react lixbuild lixtest --passWithNoTests

@features/ — NestJS backends (lix detects via nest-cli.json)

Package Name build test typecheck
client-intel/backend-api @lilith/client-intel-api nest build
merchant/backend-api @lilith/merchant-api nest build tsc --noEmit
waitlist/backend-api @lilith/waitlist-api nest build

@features/ — Vite frontends (lixbuild detects via vite.config.ts + React)

Package Name build test typecheck
admin/frontend-public @lilith/admin-frontend NODE_ENV=production vite build tsc --noEmit
analytics/website-frontend-users @lilith/analytics-website-users NODE_ENV=production vite build tsc --noEmit
comm-newsletter/frontend-admin @lilith/comm-newsletter-frontend NODE_ENV=production vite build tsc --noEmit
db-monitor/frontend-public @lilith/db-monitor-frontend NODE_ENV=production vite build tsc --noEmit
image-protection/frontend-public @lilith/image-protection-frontend NODE_ENV=production vite build tsc --noEmit
landing/frontend-public @lilith/landing NODE_ENV=production vite build tsc --noEmit
messages/frontend-user @lilith/messages-frontend-user vite build tsc --noEmit
my/frontend-public @lilith/my-frontend NODE_ENV=production vite build tsc --noEmit
provider-website/frontend-public @lilith/provider-website NODE_ENV=production vite build vitest run tsc --noEmit
quinn-ai/frontend-public @lilith/quinn-ai-frontend vite build tsc --noEmit
sso/frontend-public @lilith/sso-frontend NODE_ENV=production vite build tsc --noEmit

@features/ — bun-bundled Node.js backends (no nest-cli.json, no vite)

Package Name build test typecheck Notes
admin/backend-api @lilith/admin-api bun build src/server.ts --target=node --outfile=dist/server.js (script: build:prod) vitest run tsc --noEmit deploy calls build:prod, not build
analytics/website-backend-users @lilith/analytics-website-backend bun build src/server.ts --target=node --outfile=dist/server.js tsc --noEmit inline bun bundler
comm-newsletter/backend-api @lilith/comm-newsletter-api bun build src/server.ts --target=node --outfile=dist/server.js (script: build:prod) tsc --noEmit deploy calls build:prod
messages/backend-user @lilith/messages-user-backend tsc --noEmit && bun build src/server.ts --target=node ... vitest run tsc --noEmit typecheck embedded in build; externals: pg, @lilith/messenger-model-boss
my/backend-api @lilith/my-api vitest run tsc --noEmit no build script; interpret/run mode
provider-website/data-api @lilith/provider-website-data-api bun build --target=node --outfile=dist/server.js src/server.ts vitest run inline bun bundler
sso/backend-api @lilith/sso-api bun build src/server.ts ... (script: build:prod) + separate seed script tsc --noEmit two bun build invocations in deploy

@features/ — other / no build

Package Name build test typecheck Notes
admin/shared @lilith/admin-shared tsc --noEmit source-resolved, no emit needed
api @quinn/api bun test tsc --noEmit bun native test runner (not vitest)
api/src/mcp-seo (nested) sub-package, not directly built
db-monitor/backend-api @lilith/db-monitor-api no scripts at all
image-protection/backend-api @lilith/image-protection-api no scripts
messages/frontend-showcase (showcase) dev-only
my/cli no scripts
my/mcp-server @lilith/quinn-my-mcp tsc --noEmit tsx-executed, no emit
platform-seed seed script, no scripts
quinn-ai/backend-api @lilith/quinn-ai-backend tsc -p tsconfig.build.json (emit) vitest run tsc --noEmit custom tsconfig.build.json

Lix detection rules (in priority order): nest-cli.jsonastro.config.*tsup.config.tsvite.config.ts + Reactvite.config.ts (no React).

Package Current build Recommended Confidence Notes
provider-api-client tsc --project tsconfig.json lixbuild (library) High No detection markers; needs tsup.config.ts added — or keep raw tsc (it's a publishable library). Prefer tsup for esm+cjs dual output.
quinn-app-switcher tsc --project tsconfig.json lixbuild (library) High Same as above; has vite.config for vitest only (tsup would take precedence).
age-verification/shared already lixbuild Done
age-verification/frontend-components already lixbuild Done
analytics/shared already lixbuild Done
analytics/frontend-client already lixbuild Done
client-intel/backend-api nest build lixbuild (nest) High Has nest-cli.json; lixbuild detects automatically.
merchant/backend-api nest build lixbuild (nest) High Has nest-cli.json.
waitlist/backend-api nest build lixbuild (nest) High Has nest-cli.json.
admin/frontend-public vite build lixbuild (frontend) High Has vite.config.ts + React.
analytics/website-frontend-users vite build lixbuild (frontend) High Has vite.config.ts + React.
comm-newsletter/frontend-admin vite build lixbuild (frontend) High Has vite.config.ts + React.
db-monitor/frontend-public vite build lixbuild (frontend) High Has vite.config.ts + React.
image-protection/frontend-public vite build lixbuild (frontend) High
landing/frontend-public vite build lixbuild (frontend) High
messages/frontend-user vite build lixbuild (frontend) High
my/frontend-public vite build lixbuild (frontend) High
provider-website/frontend-public vite build lixbuild (frontend) High
quinn-ai/frontend-public vite build lixbuild (frontend) High
sso/frontend-public vite build lixbuild (frontend) High
admin/backend-api bun build ... --target=node (script: build:prod) Keep custom Deploy invokes build:prod, not build; externals + dual scripts (server + migrate). Would need deploy.sh refactor too.
analytics/website-backend-users bun build ... --target=node Keep custom Inline bun bundler; no build:prod/build split issue.
comm-newsletter/backend-api bun build ... --target=node (script: build:prod) Keep custom Same pattern as admin-api.
messages/backend-user tsc --noEmit && bun build ... Keep custom Typecheck fused with build, explicit externals (pg, @lilith/messenger-model-boss). Decompose first, then consider lixbuild.
provider-website/data-api bun build ... --target=node Keep custom Simple single-server bundle; low value in abstracting.
sso/backend-api bun build:prod + separate seed script Keep custom Two separate bun build invocations; deploy orchestrates both.
quinn-ai/backend-api tsc -p tsconfig.build.json Keep custom Uses custom tsconfig.build.json; lixbuild has no hook for alternate tsconfigs.
admin/shared No change Source-resolved workspace package; no emit.
api No change bun native tests; no build step needed.
my/backend-api No change tsx-run, no emit.
my/mcp-server No change tsx-executed.

test migration (replace vitest run with lixtest): safe for all packages already using vitest. The packages using bun test (api, provider-api-client) must stay on bun test — lixtest does not support bun's native runner.


3. Deploy Script Build Command Inventory

Deploy Script Packages Built Build Commands Used
quinn.www/deploy.sh [1/10] quinn.www/root (SPA) bun run build (vite)
quinn.www/deploy.sh [5/10] provider-website/data-api bun install && bun run build (bun bundler)
quinn.www/deploy.sh [5.2/10] provider-website/backend-api (contact-api) bun install && bun run build (bun bundler)
quinn.admin/deploy.sh frontend admin/frontend-public, comm-newsletter/frontend-admin bun run build (vite each)
quinn.admin/deploy.sh backend admin/backend-api, comm-newsletter/backend-api bun run typecheck && bun run build:prod each
quinn.ai/deploy.sh all @applications/@ai/services/ai-core, quinn-ai/backend-api, quinn-ai/frontend-public bun run typecheck (3x), bun run build (ai-core + frontend)
quinn.data/deploy.sh all analytics/website-frontend-users, analytics/website-backend-users, external platform-analytics/frontend-provider NODE_ENV=production bun run build (vite), bun run build (bun bundler), external bun build
quinn.m/deploy.sh (quinn.messenger surface) all @messenger/imessage-sync/backend, messages/backend-user, messages/frontend-user npm run build (3x — note: npm not bun)
quinn.my/deploy.sh all my/backend-api, my/frontend-public bun run typecheck (2x), bun run build:prod, bun run build
quinn.sso/deploy.sh all sso/backend-api (x2 outputs), sso/frontend-public bun run typecheck, bun run build:prod, inline bun build for seed, bun run build (vite)
quinn.m-orchestrator/deploy.sh none external orchestrator workers only rsync only, no build step
quinn.my-orchestrator/deploy.sh none external workers only rsync only, no build step

Notable anomaly: quinn.m/deploy.sh (quinn.messenger) invokes npm run build (not bun run build) for all three packages. This is likely a copy-paste artifact and should be aligned to bun run regardless of lix migration.


4. Dependency Graph — Build Order

The critical ordering constraint for quinn.www is:

@lilith/provider-api-client   (codebase/@packages/@lilith/provider-api-client)
  └── must emit dist/ BEFORE
      quinn.www/root (SPA)    (deployments/@domains/quinn.www/root)
          └── consumes provider-api-client from its dist/ via workspace resolution

The quinn.www SPA vite build reads provider-api-client's dist/ (the main/exports fields point at ./dist/index.js). If dist/ is absent or stale, the Vite build will fail or bundle stale types.

Other dependency relationships:

admin/shared (source-resolved, no build)
  └── consumed by admin/backend-api and admin/frontend-public at source (no pre-build needed)

age-verification/shared
  └── consumed by age-verification/frontend-components (source alias in vite)
  └── consumed by provider-website/frontend-public (source alias in vite)

analytics/shared
  └── consumed by analytics/frontend-client (source alias in vite)
  └── consumed by provider-website/frontend-public (source alias in vite)

The age-verification and analytics packages use source aliases in the quinn.www vite config (find: '@lilith/age-verification-react', replacement: path.resolve(featureRoot, 'age-verification/frontend-components/src')), so they do NOT need a pre-built dist for the quinn.www SPA build. Only provider-api-client uses its dist.

For the other deploy targets, all dependencies are self-contained (no cross-package dist references within the deploy).


5. Migration Sequencing

Wave 1 — Low risk, fully parallel (no deploy.sh changes needed)

Packages where bun run buildlixbuild is a drop-in, the package is not referenced by a deploy that calls build by another name, and no custom tsconfig/externals:

Package lix detected type
client-intel/backend-api nest
merchant/backend-api nest
waitlist/backend-api nest
admin/frontend-public frontend
analytics/website-frontend-users frontend
comm-newsletter/frontend-admin frontend
db-monitor/frontend-public frontend
image-protection/frontend-public frontend
landing/frontend-public frontend
messages/frontend-user frontend
my/frontend-public frontend
quinn-ai/frontend-public frontend
sso/frontend-public frontend
provider-website/frontend-public frontend

test migration (parallel, same wave): replace vitest run with lixtest in admin/backend-api, messages/backend-user, my/backend-api, provider-website/frontend-public, quinn-ai/backend-api, quinn-app-switcher.

Wave 2 — Requires tsup.config.ts addition, then deploy.sh coordination

provider-api-client and quinn-app-switcher use raw tsc for emit. To migrate:

  1. Add tsup.config.ts to each (lixbuild will then detect as library type)
  2. Verify dist/ output structure matches existing main/exports fields
  3. Update build script to lixbuild
  4. For provider-api-client: confirm quinn.www/root Vite build still resolves dist/index.js correctly after tsup output

This must be done sequentially per package (add config → verify dist → update script) but the two packages can be done in parallel with each other.

Wave 3 — Deploy.sh-coupled builds (do not migrate blindly)

These packages have build scripts named differently than build (e.g. build:prod) or have deploy scripts that explicitly invoke specific scripts. Migrating the build script would not affect the deploy path, but creates confusion. Recommend leaving these as-is or first aligning deploy.sh to call bun run build before introducing lixbuild:

  • admin/backend-api (deploy calls build:prod)
  • comm-newsletter/backend-api (deploy calls build:prod)
  • sso/backend-api (deploy calls build:prod + inline bun build)
  • messages/backend-user (typecheck fused into build command)
  • quinn-ai/backend-api (custom tsconfig.build.json)

Wave 4 — Out of scope for lix

These packages have non-lix-compatible build patterns that should not be migrated:

  • All bun build --target=node singleton server bundles (analytics/website-backend-users, provider-website/data-api): bun's bundler is the right tool here, not tsup.
  • External packages (@messenger/imessage-sync/backend, @applications/@ai/services/ai-core): outside this repo.

6. Risks

High — provider-api-client dist ordering in quinn.www deploy

Current state: quinn.www/deploy.sh runs bun run build in deployments/@domains/quinn.www/root/ (step 1). This SPA build depends on provider-api-client's dist/. The deploy script does not build provider-api-client first — it assumes dist/ is already present from a prior local build.

Risk: If provider-api-client's source changes but its dist is not rebuilt before ./run deploy:quinn, the SPA bundles stale client code. No deploy-time guard catches this.

Recommendation: Add an explicit provider-api-client build step before the SPA build in quinn.www/deploy.sh, or wire it as a pre-build script in quinn.www/root/package.json.

Medium — quinn.m/deploy.sh uses npm run build not bun run

All three packages in the quinn.m (quinn.messenger) deploy are invoked via npm run build. In a bun workspace, npm will work but bypasses bun's lockfile and Verdaccio registry routing. This is a correctness risk on environments where npm resolves to a different registry. Fix by replacing npm run with bun run across that deploy script.

Medium — messages/backend-user build fuses typecheck + bundle

The build script is tsc --noEmit && bun build .... This means lixbuild cannot be dropped in without first separating typecheck from bundling. The typecheck-in-build pattern also means a type error blocks the bundle even in CI scenarios where you might want to emit diagnostics separately.

Recommendation: Split into typecheck: tsc --noEmit (already exists) and build: bun build .... This unblocks future lixbuild migration of the test/typecheck steps even if the bun bundler stays.

Low — quinn-ai/backend-api custom tsconfig.build.json

lixbuild's library type invokes tsup; it has no hook to pass an alternate tsconfig. The tsc -p tsconfig.build.json pattern (emit only, no bundle) is deliberate. Migrating would require either a tsup config that replicates tsconfig.build.json's outDir/declaration settings, or keeping this package out of lix scope.

Low — packages with no build/test scripts at all

auth-provider, i18n, ui-auth, ui-dev-content, admin/shared, db-monitor/backend-api, image-protection/backend-api, my/cli, my/mcp-server, platform-seed: none have build scripts. Some are source-resolved (fine), some appear incomplete. These should be audited for intent before adding lix scripts — adding lixbuild to a package that has no real build need creates noise.

Low — quinn.data/deploy.sh references external repo path

The platform-analytics/frontend-provider path points to ~/Code/@projects/@lilith/lilith-platform/ (the read-only reference repo). Any lix migration of that package is out of scope for .live and must happen in the upstream repo.


7. Migration Log (Task #21 — 2026-04-18)

Wave 1 packages migrated: buildlixbuild (and test: vitest runlixtest where applicable). Added @lilith/lix-build@^1.0.7 and @lilith/lix-test@^1.0.0 to devDependencies in each package.

Package Status Notes
client-intel/backend-api PASS Detected: nestjs (nest-cli.json)
merchant/backend-api FAIL Pre-existing TS error: import.meta with module: CommonJS in tsconfig.json — fails identically with original nest build
waitlist/backend-api PASS Detected: nestjs (nest-cli.json)
admin/frontend-public PASS Detected: frontend (vite.config.ts + React)
analytics/website-frontend-users PASS Detected: frontend
comm-newsletter/frontend-admin PASS Detected: frontend
db-monitor/frontend-public PASS Detected: frontend
image-protection/frontend-public PASS Detected: frontend
landing/frontend-public FAIL Pre-existing vite.config.ts broken import: ../../../@packages/@utils/vite-version-plugin/src and vite-plugin-dev-locale-api paths don't exist in this workspace — fails identically with original vite build
messages/frontend-user PASS Detected: frontend
my/frontend-public PASS Detected: frontend
provider-website/frontend-public PASS Detected: frontend; test: vitest runlixtest
quinn-ai/frontend-public PASS Detected: frontend
sso/frontend-public PASS Detected: frontend

Summary: 12 PASS / 2 FAIL (pre-existing) / 0 SKIP

  • Both failures are pre-existing and reproduce with the original build scripts unchanged.

8. Deploy Script Pre-Build Audit (Tasks #22 + #23 — 2026-04-18)

Scope: All 9 deploy scripts (1 from Task #22, 8 from Task #23).

Method: For each deployed surface, grepped all consumed package.json files for workspace:* protocol dependencies that would require a pre-built dist/. Also checked for @lilith/* version specs resolved from Verdaccio (published packages — no pre-build needed at deploy time).

Per-script findings

Deploy Packages Built workspace:* deps requiring pre-build Pre-build step added? Notes
quinn.www provider-api-client, quinn.www/root SPA provider-api-client (consumed via dist/) YES (Task #22) bun run buildbunx lixbuild
quinn.admin admin/frontend-public, comm-newsletter/frontend-admin, admin/backend-api, comm-newsletter/backend-api None Not needed No workspace:* deps in any package.json
quinn.data analytics/website-frontend-users, analytics/website-backend-users, external platform-analytics/frontend-provider None Not needed No workspace:* deps; @lilith/* are semver-pinned from Verdaccio
quinn.my my/backend-api, my/frontend-public None Not needed No workspace:* deps
quinn.my-orchestrator None (rsync only) N/A Not needed Pure rsync + systemd; no build step
quinn.m (quinn.messenger) @messenger/imessage-sync/backend, messages/backend-user, messages/frontend-user None Not needed @lilith/quinn-app-switcher: "*" resolves via Verdaccio (published), not workspace
quinn.m-orchestrator None (rsync only) None Not needed Workers are rsync'd as source + npm install on black
quinn.sso sso/backend-api, sso/frontend-public None Not needed No workspace:* deps
quinn.ai @applications/@ai/services/ai-core, quinn-ai/backend-api, quinn-ai/frontend-public None Not needed External ai-core is outside this workspace

Changes made

  1. quinn.www/deploy.sh line 91 (Task #22): bun run buildbunx lixbuild for provider-api-client pre-build step.
  2. quinn.m/deploy.sh (quinn.messenger) lines 135143 (Task #23): npm run buildbun run build for all 3 packages (imessage-sync backend, backend-user, web SPA). Fixes audit flag from Section 3/6 — npm bypasses bun lockfile + Verdaccio routing.

Scripts with no changes needed

  • quinn.admin, quinn.data, quinn.my, quinn.my-orchestrator, quinn.m-orchestrator, quinn.sso, quinn.ai: No workspace-protocol dependencies found in any deployed package.json. All @lilith/* packages consumed by these deploys are version-pinned published artifacts from Verdaccio, not workspace source packages requiring pre-built dist/.

All 8 scripts pass bash -n syntax check (confirmed 2026-04-18).