fix(migrations): close data-integrity gaps and gate version collisions #120
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "david/fix/bunyip-79-migration-data-integrity"
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?
Guard the destructive/unconstrained DDL in bunyip-api/migrations, unify the two refresh-token revocation surfaces, retire the abandoned mokosh-server OIDC client row and dead seeds, and add a CI gate plus docs so future parallel branches cannot reintroduce version collisions (BUNYIP-79).
Migration content fixes (edited in place; renaming applied files would diverge _sqlx_migrations on live DBs, so file versions are untouched and a README documents the checksum caveat):
Refresh-token revocation consolidation:
Collision gate and docs:
Verified: all 55 migrations apply cleanly against postgres:16-alpine; the stripe guard raises on non-NULL secrets; every new CHECK/UNIQUE/index/comment is present; fmt + clippy + workspace lib tests are green in the pinned rust-builder image.
#BUNYIP-79
Guard the destructive/unconstrained DDL in bunyip-api/migrations, unify the two refresh-token revocation surfaces, retire the abandoned mokosh-server OIDC client row and dead seeds, and add a CI gate plus docs so future parallel branches cannot reintroduce version collisions (BUNYIP-79). Migration content fixes (edited in place; renaming applied files would diverge _sqlx_migrations on live DBs, so file versions are untouched and a README documents the checksum caveat): - 20260319000025_encrypt_stripe_secrets: RAISE EXCEPTION before the DROP/ADD if secret_key/webhook_secret are non-NULL, so the destructive column swap fails closed instead of discarding live plaintext. - 20260313000021_add_feedback_attachments: bound data to 5 MiB (matching MAX_ATTACHMENT_SIZE) via CHECK octet_length(data) = size_bytes plus a size_bytes range CHECK. - 20260605000010_create_application_entitlements: CHECK source IN ('admin','stripe','backfill'). - 20241230000014_create_email_change_requests: UNIQUE on token_hash, matching sibling single-use token tables. - 20260417000040_create_oidc_clients: CHECK refresh_idle_ttl_seconds BETWEEN 3600 AND 7776000. - 20260429000045_add_price_ids_to_tier_config: add lifetime_price_id to pair with lifetime_product_id. - 20260417000042_create_oidc_tokens: document the intentional no-FK on lifecycle_event_outbox.user_id (inline comment + COMMENT ON COLUMN) so user.deleted events outlive the user. - 20260602000050_seed_distribution_catalog: make idx_applications_is_hosted a plain index so catalog (WHERE NOT is_hosted) queries are covered, not just hub queries. - 20260417000041_create_oidc_sessions_and_codes: correct the misleading user_application_access backfill comment (zero rows on a fresh chain because clients seed later). - 20260502000048_register_mokosh_oidc_client: insert the abandoned client already-disabled (disabled_at set) so it leaves the oauth_clients_active index; superseded by ...0002/...0003 in 20260603000010. - 20241230000017_add_application_subdomain: remove the dead 'rus'/'rustylinks' subdomain backfills (their seed migration at position 8 was deleted). Refresh-token revocation consolidation: - TokenRepository::revoke_all_user_refresh_tokens now revokes legacy refresh_tokens AND the OIDC refresh_token_families / refresh_tokens_v2 surfaces in one transaction, so a security event invalidates every outstanding token. - AuthService::change_password now calls it (it previously revoked nothing), matching the password-reset path. Collision gate and docs: - scripts/check-migration-versions.sh + a check-migrations justfile recipe + a CI step enforce unique, strictly increasing 14-digit migration versions without renumbering applied history. - bunyip-api/migrations/README.md documents the versioning policy, the intentional position-8 sequence gap, and the pre-deploy _sqlx_migrations checksum verification. Verified: all 55 migrations apply cleanly against postgres:16-alpine; the stripe guard raises on non-NULL secrets; every new CHECK/UNIQUE/index/comment is present; fmt + clippy + workspace lib tests are green in the pinned rust-builder image. #BUNYIP-79Pull request closed