import { readFile, readdir } from 'node:fs/promises'; const files = await readdir('migrations'); const ups = files.filter((f) => f.endsWith('.up.sql')).map((f) => f.replace('.up.sql', '')); const downs = new Set( files.filter((f) => f.endsWith('.down.sql')).map((f) => f.replace('.down.sql', '')), ); for (const migration of ups) if (!downs.has(migration)) throw new Error(`Missing down migration for ${migration}`); for (const file of files.filter((f) => f.endsWith('.sql'))) { const sql = await readFile(`migrations/${file}`, 'utf8'); if (/\bUUID\b/i.test(sql)) throw new Error(`${file}: UUID is forbidden; use ULID VARCHAR(26)`); if (/\b(DECIMAL|NUMERIC|REAL|DOUBLE PRECISION)\b/i.test(sql)) throw new Error(`${file}: unsafe numeric money type detected`); } const currentDefaultPrivileges = await readFile( 'migrations/0004_revoke_broad_default_privileges.up.sql', 'utf8', ); if (/ALTER DEFAULT PRIVILEGES[\s\S]*?\bGRANT\b/i.test(currentDefaultPrivileges)) { throw new Error('Runtime roles must receive explicit object grants; broad default grants are forbidden'); } console.log(`validated ${ups.length} reversible migration(s)`);