fix(migrations): backfill entitlement source-check before 20260802000010 #456
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/BUNYIP-457-entitlement-source-check-backfill"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Adds
migrate_reconcile::backfill_entitlement_source_check, a scoped startup backfill that delivers theapplication_entitlements_source_checkconstraint to databases that never received it, so migration20260802000010no longer aborts bunyip-api startup on them.Why
20260605000010'sCHECK (source IN ('admin', 'stripe', 'backfill'))onapplication_entitlements.sourcewas added by the9c082ebin-place edit (BUNYIP-79).migrate_reconcileheals the checksum on pre-edit databases but, per its own header andmigrations/README.md, never retro-applies the DDL. So a database that ran the pre-edit body hasapplication_entitlementswith noapplication_entitlements_source_checkconstraint.20260802000010(first in v0.11.0) then widens that constraint to allow'seed'with a bareALTER TABLE ... DROP CONSTRAINT application_entitlements_source_check(noIF EXISTS), which raisesconstraint ... does not existand aborts startup. Observed on nc-01; 0.11.0 was rolled back to 0.10.0.A forward-only migration cannot fix this:
20260802000010is itself the failing migration, so on an affected database the chain never reaches a later one.Change
bunyip-api/src/migrate_reconcile.rs: newbackfill_entitlement_source_check. Sequential guards (so no::regclasscast hits an absent relation): return if20260802000010is already applied; return ifapplication_entitlementsis absent; return if the constraint already exists; otherwiseADD CONSTRAINT application_entitlements_source_check CHECK (source IN ('admin', 'stripe', 'backfill')). The migrator then runs20260802000010'sDROP+ADD, ending at the four-value constraint incl'seed'.bunyip-api/src/main.rs: invoke it afterreconcile_legacy_migration_checksumsand beforeMigrator::run.bunyip-api/migrations/README.md+ the module header: document the backfill and why it ships via the hook rather than a forward migration.Idempotent and tightly scoped: a no-op once
20260802000010is applied (so it can never fight a future migration that deliberately alters the constraint), on fresh databases (the table is created in order by the migrator), and on every boot after it has run once.20260802000010andLEGACY_CHECKSUMSare left untouched, so already-applied databases (c-01/prod) need no checksum reconciliation.Verify
just check-container(fmt + clippy-D warnings+ workspace tests) passes.postgres:16: the nc-01 shape (table without the constraint, 802 unapplied) backfills, then20260802000010applies and the constraint ends asCHECK (source IN ('admin', 'stripe', 'backfill', 'seed')); the c-01 shape (802 applied) skips; the fresh shape (table absent) skips.Deploy
No version bump in this PR (bump to 0.11.1 via
just create-release hotfixwhen ready). On the next 0.11.1 deploy, nc-01 self-heals (backfill adds the constraint, then20260802000010applies); c-01/prod are unaffected (802 already applied, its checksum unchanged). No per-server manual SQL.Closes BUNYIP-457.
20260605000010's CHECK (source IN ('admin','stripe','backfill')) on application_entitlements.source was added by the9c082ebin-place edit (BUNYIP-79), so migrate_reconcile heals the checksum but never retro-applies the DDL. A database that ran the pre-edit body therefore has application_entitlements with no application_entitlements_source_check constraint. 20260802000010 then widens that constraint to allow 'seed' with a bare DROP CONSTRAINT (no IF EXISTS), which raises "constraint ... does not exist" and aborts startup (observed on nc-01; 0.11.0 was rolled back to 0.10.0). A forward-only migration cannot fix it: 20260802000010 is itself the failing migration, so the chain never reaches a later one on the affected database. Add migrate_reconcile::backfill_entitlement_source_check, run from main after the checksum reconcile and before the migrator: if 20260802000010 is not yet applied, application_entitlements exists, and the constraint is absent, add CHECK (source IN ('admin','stripe','backfill')) so the migrator's DROP + ADD then succeeds and widens it to include 'seed'. Tightly scoped and idempotent: a no-op once 802 is applied, on fresh databases, and on every later boot, and it cannot fight a future migration that deliberately alters the constraint. 20260802000010 and LEGACY_CHECKSUMS are left untouched, so already-applied databases (c-01/prod) need no checksum reconciliation. Verified against postgres:16 for the nc-01, c-01, and fresh shapes; documented in migrations/README.md and the module header. #BUNYIP-457 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: nrupard <natrsmith11@gmail.com>