/** * Admin allowlist (Session 18). * * Server-side check ONLY. The client-side `useAuth()` redirect on * `/admin` is for UX (so non-admins don't see a 401 screen) — the * security boundary lives in `/api/admin/stats/route.ts`, which calls * this helper against the bearer token's email before returning any * data. Anyone can spoof a client-side check; they can't spoof the * Supabase token verification on the server. * * To add an admin: append their email here. Lowercase. The check is * case-insensitive on inputs but the registry is canonical. */ const ADMIN_EMAILS: ReadonlySet = new Set([ 'kevdevelops@gmail.com', ]); export function isAdmin(email: string | null | undefined): boolean { if (!email) return false; return ADMIN_EMAILS.has(String(email).trim().toLowerCase()); } // Exported for tests + the rare debug page that wants to show how // many admins are configured without enumerating them. export const adminCount = ADMIN_EMAILS.size;