import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import Database from "better-sqlite3"; import { ensureDataLayout } from "./lib/data-dir.mjs"; import { runMigrations } from "./migrate.mjs"; const requiredTables = [ "user", "session", "account", "verification", "app_profiles", "app_setup_state", "portal_invitations", "auth_audit_events", ]; const requiredIndexes = [ "app_profiles_auth_user_id_unique", "app_profiles_client_id_unique", "portal_invitations_token_hash_unique", "session_user_id_idx", "account_user_id_idx", ]; async function main() { const paths = ensureDataLayout(); const packageJson = JSON.parse( readFileSync(new URL("../package.json", import.meta.url), "utf8"), ); assert.equal( packageJson.scripts?.predev, "node scripts/migrate.mjs", "pnpm dev must apply migrations before starting Next.js", ); assert.equal( packageJson.scripts?.prestart, "node scripts/migrate.mjs", "pnpm start must apply migrations before starting Next.js", ); runMigrations(paths.databasePath); const sqlite = new Database(paths.databasePath, { readonly: true }); try { const tables = sqlite .prepare("select name from sqlite_master where type = 'table'") .all() .map((row) => row.name); const indexes = sqlite .prepare("select name from sqlite_master where type = 'index'") .all() .map((row) => row.name); for (const table of requiredTables) { assert.ok(tables.includes(table), `Missing auth table: ${table}`); } for (const index of requiredIndexes) { assert.ok(indexes.includes(index), `Missing auth index: ${index}`); } const profileColumns = sqlite.prepare("pragma table_info(app_profiles)").all(); const roleColumn = profileColumns.find((column) => column.name === "role"); const disabledColumn = profileColumns.find((column) => column.name === "disabled"); const clientIdColumn = profileColumns.find((column) => column.name === "client_id"); assert.equal(roleColumn?.notnull, 1, "app_profiles.role must be required"); assert.equal(disabledColumn?.notnull, 1, "app_profiles.disabled must be required"); assert.ok(clientIdColumn, "app_profiles.client_id must bind invited client accounts"); console.log("Phase 2 auth smoke passed"); } finally { sqlite.close(); } } main().catch((error) => { console.error(error); process.exitCode = 1; });