feat(storage): mosaic storage migrate-tier with dry-run + idempotency (FED-M1-05)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful

Adds `mosaic storage migrate-tier --to federated` for one-way migration
from `local` (PGlite) or `standalone` (PG without pgvector) to
`federated` (PG + pgvector). Source is read via DrizzleMigrationSource
which queries the normalized schema (the same path the gateway writes
through), so the migration captures all real domain data — not just
the flat key/value collections.

Key behaviors:
- `--dry-run` prints per-table row counts without writes
- `--allow-non-empty` required to write into a populated target (default
  refuses to mix data sets)
- Per-table transactions; partial failure does not leave half-migrated
  tables
- Idempotent on re-run via INSERT ... ON CONFLICT DO UPDATE keyed on id
- Topological table order respects FK dependencies (verified against
  schema.references())
- Skips sessions, verifications, admin_tokens (TTL'd / one-time / env-bound)
- For sources without pgvector, insights.embedding is projected to NULL
  on read, then upserted as NULL (column is nullable)

32 unit tests cover ordering, dry-run, idempotency, empty-target
preconditions, table skipping, and embedding-null projection. Integration
test against real PG/PGlite is FED-M1-08.

Refs #460
This commit is contained in:
Jarvis
2026-04-19 19:30:33 -05:00
parent 4c2b177eab
commit 8d30a47286
9 changed files with 1486 additions and 17 deletions

View File

@@ -28,6 +28,7 @@ export default tseslint.config(
'apps/web/e2e/helpers/*.ts',
'apps/web/playwright.config.ts',
'apps/gateway/vitest.config.ts',
'packages/storage/vitest.config.ts',
'packages/mosaic/__tests__/*.ts',
],
},