/** Seeds the two accounts requested for this first slice: `admin` (role * admin, unlocks /admin) and `demo` (role user, the "logged-in doctor" * persona). Idempotent (ON CONFLICT DO NOTHING) — safe to run on every * deploy alongside migrate.ts. * * SECURITY: both passwords are "1", set explicitly for local/dev use. Do * not run this against a deployment `/admin` is actually reachable from * without rotating them first — see docs/operations.md and the plan this * was built from. */ import * as bcrypt from "bcrypt"; import { createPool } from "./db"; import { loadSettings } from "./config"; const SEED_USERS: Array<{ username: string; password: string; role: "user" | "admin" }> = [ { username: "admin", password: "1", role: "admin" }, { username: "demo", password: "1", role: "user" }, ]; async function main() { const settings = loadSettings(); const pool = createPool(settings.postgresDsn); for (const seed of SEED_USERS) { const passwordHash = await bcrypt.hash(seed.password, 12); await pool.query( `INSERT INTO auth_user (username, password_hash, role) VALUES ($1, $2, $3) ON CONFLICT (username) DO NOTHING`, [seed.username, passwordHash, seed.role] ); console.log(`Seeded ${seed.username} (${seed.role})`); } await pool.end(); } main().catch((error) => { console.error(error); process.exit(1); });