- user.is_platform_admin (drizzle 0010), input:false in better auth —
a client payload carrying it is refused outright (FIELD_NOT_ALLOWED,
integration-proven). only write path is bun run grant-admin
- staff gate reads the bit fresh per request, never session claims;
every denial is a 404 — /admin existence is not disclosed, same
posture as non-member org urls
- new "staff" class in server-fn-classification; the boundary test
asserts each admin fn's middleware chain matches
- /admin (counts), /admin/users (status filter, search, bulk approve,
two-step reject), /admin/orgs (expandable members, role select).
paginated + clamped, no unbounded selects
- approve writes through promoteUserAccess (the invite-redemption
path — already stamps reviewedAt/By, already idempotent);
rejectUserAccess added as its mirror, the first writer of "rejected"
- role-change invariants extracted to assertRoleChangeAllowed, shared
by the plugin hook and updateMemberRoleForStaff — the portal cannot
demote a last admin or touch a personal org
- ops + audit gap in DECISIONS.md: revisit before the first
non-founder staff grant