Console
Privileged-actions surface for admin, moderator, and expert roles. Role model, audit log, and per-action runbooks.
If you don't see a Console pill in the header, this page doesn't apply to you yet — every privileged surface is gated by an explicit role grant.
# Who it's for
Admins
Manage user roles, review researcher credentials, watch sync failures and API quotas, and audit every privileged action.
Moderators
Triage flagged content, run the appeals queue, and apply soft-bans with audit trails.
Experts
Review the validation queue scoped to your taxa and watch your per-taxon expertise score.
# What's inside
The console lives at /console/ and bundles 36+ tabs grouped by role. The sidebar and role pills are projections of a single console-tabs.ts source — adding a new surface is one entry, not a hand-rolled route.
Admin tabs
Overview, Users, Roles, Credentials, Audit log, API quotas, Sync failures, Cron runs, Feature flags, Bans, Karma, Anomalies, Forensics, Errors, Health, Webhooks, Proposals, plus seven read-only entity browsers (Identifications, Notifications, Media, Follows, Watchlists, Projects, Taxon changes).
Moderator tabs
Overview, Flag queue, Comments triage, Appeals.
Expert tabs
Overview, Expertise score, Validation queue, Apply for an expert badge.
# How privileges work
Server-side dispatcher
Every privileged write goes through the supabase/functions/admin/ Edge Function. The dispatcher re-verifies the JWT, enforces the action's required role, runs the handler, and inserts an admin_audit row in the same transaction. Browsers never write directly to privileged tables.
RLS predicate: has_role(uid, role)
All privilege-gated rows use has_role(), not denormalised flags like users.is_expert. Roles can also be time-bounded (expires_at) and auto-revoked nightly.
Two-person rule
Irreversible actions can require a second admin's approval through admin_action_proposals. The dispatcher enforces the gate when the feature flag is on; pending proposals expire hourly.
# Observability & forensics
Anomalies
Hourly detect_admin_anomalies() cron flags off-hours actions (per-admin timezone), bulk grants, and unusual write patterns.
Health digest
Weekly compute_admin_health_digest() snapshot drives the hero card on /console/health/ with directional Δ pills and 12-week sparklines.
Function errors
A structured function_errors sink wired into the dispatcher. /console/errors/ offers severity-coloured pills, URL-driven filters, single + bulk acknowledge.
Webhooks
HMAC-SHA256 outbound signing, per-webhook deliveries drilldown, click-to-replay, and nonce-based replay protection.
# References
Module 24 — Admin Console — implementation reference
Runbook — Admin bootstrap — first admin / role grants
Runbook — Role model — admin / moderator / expert grants
Runbook — Audit log — querying admin_audit
Runbook — Per-action ops — what each tab does day-to-day
Runbook — Entity browsers — shared paginated template
Design doc — Admin console — rationale and history