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

@@ -24,7 +24,8 @@
"@electric-sql/pglite": "^0.2.17",
"@mosaicstack/db": "workspace:^",
"@mosaicstack/types": "workspace:*",
"commander": "^13.0.0"
"commander": "^13.0.0",
"postgres": "^3.4.8"
},
"devDependencies": {
"typescript": "^5.8.0",