Skip to content

fix(cli): accept v0.0.13/v0.0.14 schema fingerprints as legacy v0 - #465

Open
alan-roe wants to merge 2 commits into
MapleTechLabs:mainfrom
alan-roe:fix/legacy-schema-fingerprints
Open

fix(cli): accept v0.0.13/v0.0.14 schema fingerprints as legacy v0#465
alan-roe wants to merge 2 commits into
MapleTechLabs:mainfrom
alan-roe:fix/legacy-schema-fingerprints

Conversation

@alan-roe

@alan-roe alan-roe commented Aug 14, 2026

Copy link
Copy Markdown

Problem

Stores created by v0.0.13 or v0.0.14 cannot enter the versioned local-store migration chain. Only the v0.0.12 schema fingerprint (428701854f9fd30e) is registered as legacy v0, so maple schema plan on a store born on a later pre-migration release fails with:

SchemaCommandError: the store fingerprint 06d3f9912027129b is not registered

Computed with the repo's own schemaFingerprint over each tag's local-schema.sql: v0.0.12 → 428701854f9fd30e, v0.0.13 → ea2d7ee4f385544e, v0.0.14 → 06d3f9912027129b.

Since maple start fails closed on a non-current identity (correctly), the only path such a deployment has is maple reset — full data loss, exactly what the migration system exists to avoid.

Why widening is safe

The v0.0.12→v0.0.14 DDL delta touches only derived state (alert_checks columns, service_map_db_*_hourly MV reworks, the new service_operations_minutely table+MV). The six authoritative raw tables are byte-identical across all three schemas, and legacy-to-current.ts replays only those raw tables (derived state is rebuilt; alert_checks/session tables stay with the retained rollback source). So the existing frozen v0→v1 edge is already correct for all three sources — they just weren't registered.

Changes

  • local-schema-history.ts: the v0 entry carries three frozen fingerprint/projectRevision variants
  • schema-identity.ts: LEGACY_SCHEMA_VARIANTS / LEGACY_SCHEMA_FINGERPRINTS / legacyLocalSchemaIdentity
  • local-store-migrations.ts: identityFromMarker and resolveMigrationChain classify any registered variant as legacy v0; unknown fingerprints still fail closed
  • journal validation: the chain's first step keeps the frozen module identity (canonical v0) while the journal's top-level source records the marker as found — assertJournalChainInvariants now accepts any registered v0 variant for that one comparison (sourceMatchesFirstStep); everything else stays strict
  • tests: marker classification + planMigration v0→v5 for every variant, unknown-fingerprint rejection

Verification

  • bun test test/local-store-migrations.test.ts — 18 pass; tsc --noEmit clean
  • End-to-end on a production v0.0.14 store (self-hosted deployment): schema plan resolves the full v0→v5 chain and schema migrate --yes promotes cleanly (all 5 steps verified), raw telemetry intact, stock v0.0.18 binary serves the migrated store

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Stores created by v0.0.13 or v0.0.14 carry schema fingerprints
(ea2d7ee4f385544e / 06d3f9912027129b) that were never registered in the
local-schema history, so 'maple schema plan' fails with 'the store
fingerprint ... is not registered' and those stores are locked out of
the v0->v5 migration chain entirely.

The v0.0.12->v0.0.14 DDL delta touches only derived tables/MVs (raw
tables are byte-identical), and the legacy->v1 migration replays only
the six raw tables, so the existing v0 edge is correct for all three
schemas.

- register the three fingerprint/projectRevision variants on the v0
  history entry
- classify any registered variant as legacy v0 in identityFromMarker
  and resolveMigrationChain (unknown fingerprints still fail closed)
- accept a registered variant as the journal's source identity when
  validating the chain's first step (the frozen legacy edge records
  the canonical v0 identity; the journal records the marker as found)

Verified end-to-end on a production v0.0.14 store: plan resolves
v0->v5 and migrate promotes cleanly.
…ntity history

The append-only gate (scripts/check-local-schema-manifest.ts) compares every
existing LOCAL_SCHEMA_HISTORY entry against the base branch byte-for-byte, so
adding a variants field inside the v0 entry tripped it. The variant list now
lives in schema-identity.ts as its own constant; the history array is
byte-identical to main.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant