Runbook — Superadmin access governance (ADR-0134 D2 / ADR-0136)
users.is_superadmin = 1 grants the staff console (/admin/**): payment
activation, FinOps margins, incidents, and cross-tenant data (any tenant’s
health, private conversations on the audited paths). It is the most powerful
flag in the system. There is no self-serve UI to set it — by design.
The audit trail and the live holder list are at /admin/access.
Granting
Section titled “Granting”Who approves: a current superadmin + the requester’s manager. Grant the
minimum needed (today that’s full superadmin; a scoped billing_ops role is
a follow-up — see ADR-0134).
Steps:
- Confirm the person has MFA enrolled (the console requires fresh MFA; an unenrolled superadmin is blocked anyway).
- Run the sanctioned script (from
platform/) — it flips the flag and writes the audit event in one go (ADR-0136):Terminal window node scripts/superadmin-access.mjs \--env prod --email <email> --action grant \--by <your-email> --reason "<approval + who signed off>" - Verify at
/admin/access: the new holder appears with grant logged (notout-of-band) and the event shows in the access log.
Break-glass: a raw
UPDATE users SET is_superadmin = 1 …still works, but it writes no audit event and will show as out-of-band drift at/admin/access. Prefer the script; reconcile any drift.
Scoped role: billing_ops (ADR-0137)
Section titled “Scoped role: billing_ops (ADR-0137)”For someone who only fulfils payments, grant the least-privilege role instead
of full superadmin — same script, add --role billing_ops:
node scripts/superadmin-access.mjs \ --env prod --email <email> --action grant --role billing_ops \ --by <your-email> --reason "payments fulfilment, approved by <manager>"billing_ops can see the payment queue and Mark paid. It cannot open
any tenant’s health, fleet margins, incidents, or this access page — those stay
superadmin-only. (--role defaults to superadmin when omitted.) Revoke the
same way with --action revoke --role billing_ops.
Revoking
Section titled “Revoking”When someone leaves the staff role or no longer needs it — same script:
node scripts/superadmin-access.mjs \ --env prod --email <email> --action revoke \ --by <your-email> --reason "offboarding / no longer needed"Revoke promptly on offboarding.
Periodic review
Section titled “Periodic review”Quarterly, open /admin/access and confirm each current superadmin
still needs it. Two checks:
- Anyone who shouldn’t be there → revoke (script above).
- Anyone flagged out-of-band (holds the flag with no grant event) → either re-grant via the script to capture who/why, or revoke. Record the review date + outcome.
Why no UI
Section titled “Why no UI”A self-serve toggle for an account-wide, cross-tenant superpower is a privilege-
escalation foot-gun. An operator-run script by an existing superadmin, with a
recorded reason and a quarterly review, is the deliberate control (ADR-0134 D2 /
ADR-0136) — the audit lives in user_security_events, not a web grant
endpoint. The console itself is gated on this flag plus fresh MFA
(/admin/+layout.server.ts), with the per-page guards retained as defense in
depth.
Follow-up (ADR-0134): a scoped billing_ops capability for least-privilege.