v5.35.0 2 June 2026 Fix

Migration Index Reconciliation and Self-Registration Gate

Why This Matters

SpeyBooks treats the live database schema and the recorded migration history as two views of one truth that must always agree. They had quietly diverged: eight migrations had applied their changes to the database but never recorded themselves in the internal migration index, so the index claimed an older migration was the most recent. No financial data was affected and no invariant was at risk, but a migration index that disagrees with the schema undermines the ability to reason mechanically about what has and has not run. This release restores agreement and closes the gap that allowed it.


Fixes

Migration index reconciliation

  • Eight applied migrations recorded into the index Each of the eight migrations had its distinctive schema change verified as live in the database before any index record was written, so a record is only ever added for a change that is demonstrably present. The reconciliation makes no schema or financial change of its own; it is a pure governance correction.

  • Honest provenance for the recovered dates Exact original apply times are not recoverable. Each backfilled record carries a documented best-estimate timestamp that preserves the true apply order, with one timestamp adjusted to account for a file edited after a later migration had already run. The reasoning is recorded in the migration itself.

Self-registration gate

  • A migration can no longer apply without recording itself The deployment pipeline now runs a static gate that fails the deploy if any migration subject to enforcement omits its self-registration step. This is the durable backstop: the class of defect that produced this drift can no longer reach production unnoticed.

Operational Impact

  • The internal migration index and the live schema agree again, with no gaps in the recorded sequence.
  • Any future migration that applies changes without recording itself fails the deploy rather than drifting silently.
  • No user-facing behaviour changed; no financial data was touched.

Proof anchor: reconciliation by migration 089; enforcement by a deploy-time static gate (AX-MIG-003), fatal on omission. Class M at the CI layer.


Files Changed

Backend:

  • api/db/migrations/089-item32-schema-migrations-reconciliation.sql — reconciliation migration (with dry-run twin)
  • scripts/check-migration-registration.sh — deploy-time self-registration gate
  • api/deploy.sh — gate wired in as a pipeline phase
  • docs/kernel/axioms.yml — AX-MIG-003 registered (registry version bumped)

This restores a clean, mechanically verifiable migration history and hardens the path so it stays that way.