migration-reversibility
Part of shipsafe — offline deploy-safety skills. Every script is stdlib-only Python 3.8+; nothing leaves the machine.
python3 scripts/check_migrations.py <migrations_dir_or_file> [--json]
Three finding categories:
DATA_LOSS — DROP TABLE/COLUMN without co-located backup, TRUNCATE, DELETE without WHERE, type narrowing to VARCHAR(n). Rolling back the deploy does not roll back these — the data is gone.
DEPLOY_BREAKER — operations that break the currently running app version during the deploy window: ADD COLUMN NOT NULL without DEFAULT, RENAMEs (old code queries the old name), CREATE INDEX without CONCURRENTLY (locks writes on Postgres).
SECURITY — Row Level Security audit. Explicit
DISABLE ROW LEVEL SECURITYis critical anywhere. For Supabase projects (detected via path or auth.uid()/anon-grant signals — non-Supabase databases are deliberately not flagged), tables CREATEd without a matchingENABLE ROW LEVEL SECURITYare flagged high: on Supabase the public anon key can query any table in the public schema, so a table without RLS is publicly readable and writable. This is the #1 documented cause of vibe-coded app data breaches; when it fires, walk the user through deny-by-default policies.
The governing rule, which is worth stating to the user verbatim: a migration is deploy-safe only if the previous version of the app still works after it runs. That's what makes rollback possible.
For flagged RENAMEs and DROPs, recommend the expand/contract pattern: add the new thing → dual-write → migrate readers → remove the old thing in a later release. SQL comments are stripped before analysis, and a backup statement in the same file downgrades DROP severity.
Exit codes: 0 clean, 1 findings.
All paths below are relative to this skill's directory (migration-reversibility/).