import { env } from "cloudflare:workers"; import { timingSafeEqualStrings } from "./crypto"; import { isLocalDev } from "./deployment"; export type BootstrapVars = { ADMIN_EMAIL?: string; BOOTSTRAP_TOKEN?: string; GITFOR_LOCAL?: string; PUBLIC_URL?: string; }; const MIN_BOOTSTRAP_TOKEN_LENGTH = 16; export function isAdminEmail(email: string, vars: BootstrapVars = env): boolean { const configured = (vars.ADMIN_EMAIL ?? "").trim().toLowerCase(); return configured !== "" && email.trim().toLowerCase() === configured; } /** A one-time BOOTSTRAP_TOKEN secret; too-short values are ignored so a placeholder can't be guessed. */ export function validBootstrapToken(presented: string | null | undefined, vars: BootstrapVars = env): boolean { const secret = vars.BOOTSTRAP_TOKEN ?? ""; if (secret.length < MIN_BOOTSTRAP_TOKEN_LENGTH || !presented) return false; return timingSafeEqualStrings(presented, secret); } /** * Who may become the instance's first admin at signup (DEPLOY-P3 / AUTH-P5): whoever presents the * BOOTSTRAP_TOKEN, or on loopback dev only, simply the first account. ADMIN_EMAIL is not trusted here because * the address is unverified at signup; `promoteAdminEmailOnVerify` grants it once the address is proven. */ export function mayBootstrapAdminAtSignup( bootstrapToken: string | null | undefined, vars: BootstrapVars = env, ): boolean { return validBootstrapToken(bootstrapToken, vars) || isLocalDev(vars); } /** * Which first signup may bypass SIGNUPS_ENABLED=false: only one that could become admin right away. ADMIN_EMAIL * does not qualify, since anyone can type it and would then hold the single bootstrap slot unverified. */ export function mayBypassClosedSignups(bootstrapToken: string | null | undefined, vars: BootstrapVars = env): boolean { return mayBootstrapAdminAtSignup(bootstrapToken, vars); }