import { randomBytes } from 'node:crypto' import { hashPassword } from './password.js' const PASSWORD_CHARS = Object.freeze('abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789') const generateRandomPassword = () => Array.from(randomBytes(14), b => PASSWORD_CHARS[b % PASSWORD_CHARS.length]).join('') export async function bootstrapAdmin(run, get) { const row = await get('SELECT COUNT(*) as n FROM users') if (row?.n !== 0) return const email = process.env.BOOTSTRAP_EMAIL?.trim() const password = process.env.BOOTSTRAP_PASSWORD const identifier = (email && password) ? email : 'admin' const plainPassword = (email && password) ? password : generateRandomPassword() await run( 'INSERT INTO users (id, identifier, password_hash, role, created_at, auth_provider, oidc_issuer, oidc_sub) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [crypto.randomUUID(), identifier, hashPassword(plainPassword), 'admin', new Date().toISOString(), 'local', null, null], ) if (!email || !password) { console.log(`\n[KestrelOS] No bootstrap admin configured. Default admin created. Sign in at /login with:\n\n Identifier: ${identifier}\n Password: ${plainPassword}\n\n Set BOOTSTRAP_EMAIL and BOOTSTRAP_PASSWORD to use your own credentials on first run.\n`) } }