export const DESTRUCTIVE_TEST_CONFIRMATION = 'SMOKE_SEED_LOCAL_OR_CI_ONLY'; const ALLOWED_ENVIRONMENTS = new Set(['local', 'test', 'ci']); const KNOWN_PRODUCTION_DATABASE_USERS = new Set(['tiku_api', 'tiku_worker']); function argumentValue(argv, name) { const directIndex = argv.indexOf(name); if (directIndex >= 0) return String(argv[directIndex + 1] || '').trim(); const prefix = `${name}=`; return String(argv.find(value => value.startsWith(prefix)) || '').slice(prefix.length).trim(); } export function resolveDestructiveTestConfirmation( env = process.env, argv = process.argv.slice(2), ) { return argumentValue(argv, '--confirm') || String(env.SMOKE_SEED_CONFIRM || '').trim(); } export function describeDatabaseTarget(databaseUrl) { if (!databaseUrl || typeof databaseUrl !== 'string') { throw new Error('DATABASE_URL is required'); } let parsed; try { parsed = new URL(databaseUrl); } catch { throw new Error('DATABASE_URL must be a valid PostgreSQL URL'); } if (!['postgres:', 'postgresql:'].includes(parsed.protocol)) { throw new Error('DATABASE_URL must use the postgres or postgresql protocol'); } if (!parsed.hostname || !parsed.pathname || parsed.pathname === '/') { throw new Error('DATABASE_URL must include a host and database name'); } return { host: parsed.hostname, port: parsed.port || '5432', database: decodeURIComponent(parsed.pathname.slice(1)), user: decodeURIComponent(parsed.username || ''), }; } function targetText(target, environment = 'unavailable') { const safe = value => String(value || '[missing]') .replace(/[\u0000-\u001f\u007f\s]+/g, '_') .slice(0, 160); return [ `host=${safe(target.host)}`, `port=${safe(target.port)}`, `database=${safe(target.database)}`, `user=${safe(target.user)}`, `databaseEnvironment=${safe(environment)}`, ].join(' '); } function refusal(operation, reason, target, environment) { return new Error( `Refusing ${operation}: ${reason}. Target: ${targetText(target, environment)}`, ); } function knownProductionReason(target) { const user = target.user.toLowerCase(); const host = target.host.toLowerCase(); if (KNOWN_PRODUCTION_DATABASE_USERS.has(user)) { return 'database user is reserved for production runtime'; } if (host === 'tjszsb.com' || host.endsWith('.tjszsb.com')) { return 'database host belongs to the production domain'; } return ''; } export async function assertDestructiveTestDatabase({ client, databaseUrl, confirmation = resolveDestructiveTestConfirmation(), operation = 'destructive database test', } = {}) { let target; try { target = describeDatabaseTarget(databaseUrl); } catch (error) { throw new Error(`Refusing ${operation}: ${error.message}`); } if (confirmation !== DESTRUCTIVE_TEST_CONFIRMATION) { throw refusal( operation, `explicit confirmation ${DESTRUCTIVE_TEST_CONFIRMATION} is required`, target, ); } const productionReason = knownProductionReason(target); if (productionReason) { throw refusal(operation, productionReason, target); } if (!client || typeof client.query !== 'function') { throw refusal(operation, 'a connected PostgreSQL client is required', target); } let result; try { result = await client.query( ` select environment, allow_destructive_tests as "allowDestructiveTests" from app_private.environment_safety where id = true limit 1 `, ); } catch { throw refusal( operation, 'database safety marker is unavailable or unreadable', target, ); } const marker = result?.rows?.[0]; const environment = String(marker?.environment || 'missing').toLowerCase(); if (!marker) { throw refusal(operation, 'database safety marker row is missing', target, environment); } if (!ALLOWED_ENVIRONMENTS.has(environment)) { throw refusal( operation, `database environment ${environment} is not approved for destructive tests`, target, environment, ); } if (marker.allowDestructiveTests !== true) { throw refusal( operation, 'database marker does not allow destructive tests', target, environment, ); } return { target, environment, allowDestructiveTests: true }; }