Skip to main content

Manual batch rollback inventory

These files are manual incident artifacts under apps/database/rollbacks/, not forward migrations. They are never automatically applied by the migration gate. Take release-authority approval, stop affected writers/callers, retain the exact source and catalog receipt, and run one file at a time with psql -X -v ON_ERROR_STOP=1 -f FILE against the explicitly approved database. Do not change hosted migration ledgers to replay history. Recovery uses an approved forward repair; local rehearsal alone may use supabase migration repair --local. For a whole batch, use reverse apply order: Devbox rollback removes admission/lease protections. Drain and stop all claim, enqueue and control callers, deploy a compatible caller before resuming, and do not run #6457’s rollback while #6460 still depends on S4. The historical function bodies are pinned in the files; compare them with the intended pre-migration version before use. There is no CASCADE fallback for unexpected dependencies. Every transactional file bounds locks to five seconds and statements to thirty seconds; a busy database aborts the transaction for diagnosis and a fresh retry. The index file sets session timeouts (five-second locks, five-minute statement) and uses DROP INDEX CONCURRENTLY. Run it alone in autocommit: never use BEGIN, psql -1/--single-transaction, or a runner that wraps/batches the file. Long transactions can delay a concurrent drop. On timeout/cancellation, inspect pg_stat_activity, pg_stat_progress_create_index and the exact index catalog before retrying; do not start another build/drop blindly. Close the dedicated session or reset both timeouts if execution stopped before the file’s resets.

Cross-app token containment is forward-only

The 20261026173000 migration bounds both minting overloads and marks overlong unused tokens revoked. It leaves their expiry and other evidence intact, but stores neither the previous revocation bit nor migration-specific provenance. Never un-revoke rows or restore the vulnerable generator bodies. Rolling back an application deployment does not restore these handoff credentials: users must start a new bounded handoff after recovery.
  1. Stop cross-app handoff routes and privileged minting callers. Keep server-side lifetime/audience validation in place.
  2. Run the containment file. It revokes client EXECUTE for both minting overloads and marks at most 1,000 unused, unrevoked rows per invocation. It never changes used tokens, expiry fields or other audit data. Existing service/admin privileges remain; those callers must stay stopped separately.
  3. Read revoked_now and remaining. Repeat bounded invocations after writers stop until remaining = 0; locked rows skipped by SKIP LOCKED still count as remaining. A nonzero count is incomplete containment. Stop and diagnose timeout/contention rather than retrying indefinitely.
  4. Review a forward repair, prove both overloads’ bounds and denial tests, then explicitly restore authenticated execution on the two signatures listed in the file. Do not broadly grant privileges. The original forward migration restates those grants; replay it only in a disposable rehearsal, not by changing a hosted ledger. Existing revocations remain permanent.
The disposable proof applies the complete batch with the real Supabase CLI, compares Devbox function bodies/owners/ACLs, columns, indexes, triggers and constraints with snapshots taken before each step, rolls back in reverse order, and re-applies. Containment is checked separately for bounded progress, idempotency, preserved expiry/used rows, denied client minting and permanent revocation after re-apply. It intentionally cannot reproduce #6840’s old catalog or credential validity; no reversible rollback is claimed for that security fix.