Appearance
Authorization
Authorization is role-based with rank and row-level overlays, enforced server-side on every protected route and re-checked inside the database for the operations that matter most. Frontend visibility (which buttons render) mirrors these rules for usability only — it is never the security boundary.
The layers
text
1. Identity browser session (live agents row) or API key
2. Clearance clearance_level ≥ threshold (CLEARANCE_POLICY)
3. Rank supervisor / reassignment / Director gates
4. Allowlist admin_users table (System Administration)
5. Row-level assignment + supervisor-flag checks per report
6. Database RPC whitelists, rank/self-edit guards, row locks1
2
3
4
5
6
2
3
4
5
6
Clearance-based authorization
CLEARANCE_POLICY (in authz.py) maps capabilities to minimum clearance levels 1–5. /auth/me returns every flag; authorize_dashboard(permission) enforces it. The full table is in the Permissions reference.
Key entries: view_dashboard 1, view_agents 1, view_analytics 2, add_case_note/add_evidence 1, manage_dockets 2, reassign_docket 4, decide_appeal 4, manage_agents 5, delete_docket 5, view_punishments 2, manage_punishments 4.
Clearance is checked against the live agents row every request — a demotion takes effect immediately, independent of any cached frontend state.
Rank-based authorization
Ranks (lowest → highest): Trial Agent, Probationary Agent, Agent, Senior Agent, Head Investigator, Lead Agent, Director, Department Director.
| Gate | Rank requirement |
|---|---|
| Supervisor reports, supervisor queue, audit visibility, trainer eligibility | Senior Agent + |
| Case reassignment | Head Investigator + |
Director-only admin capabilities (admin_reports, admin_schema, access management) | Director / Department Director |
| Rank/clearance changes on other agents | Director (via rpc_admin_agent_update guards) |
Director authority is derived from the live rank — a demotion to Lead Agent revokes Director capabilities immediately even if clearance_level is left untouched. This is enforced both in authz.py and inside the RPCs (admin_requester_is_director).
Agent permissions and claims
- Assignment claims: a report's
assigned_agentis compared exactly (never prefix/substring) against the caller's identifiers —Name (userid)forms split and compare the userid againstdiscord_id/agent_id/name. Unassigned is never a match. Only the assigned agent (or supervisor rank) may update, note, evidence, timeline, action, or contact a case. - Supervisor reports:
is_supervisorrows are invisible to agents below Senior Agent: list items are replaced withrestrictedplaceholders, supervisor counts are zeroed, and row-level routes return 403. - Claim: claiming requires
manage_dockets; the database rejects claims on already-assigned cases (ALREADY_CLAIMED).
Supervisor/admin restrictions
- System Administration (
require_admin) requires, in order:- a valid browser session (the API key is always rejected — 403);
- membership in
admin_userswithactive = true; - the clearance level for the specific capability;
- Director rank for Director-only capabilities (
admin_reports,admin_schema, access management) — a Lead Agent with clearance 5 is still rejected.
- Hierarchy guard: admins may only modify agents at or below their own rank (
_rank_ge+ DBRANK_MANAGE_REQUIRED). - Self-modification is blocked entirely (
SELF_PROMOTION_BLOCKED) — nobody can edit their own agent record, preventing both self-promotion and soft-locking yourself out of the site. - Directors are protected: they cannot be removed from the admin allowlist (
DIRECTOR_PROTECTED).
Mutation authorization
Every mutation type re-checks its own authorization inside the authoritative RPC:
| Mutation | API gate | DB re-check |
|---|---|---|
| Report actions | manage_dockets + assignment + supervisor row | status guard under row lock |
| Report update | manage_dockets/reassign_docket + assignment | (whitelist at API; RPC for actions) |
| Report delete | delete_docket + reason | pre-image + audit in transaction |
| Agent update | admin_agents + allowlist + reason | field whitelist, Director/rank/self-edit guards |
| Punishment CRUD | view_punishments/manage_punishments | field whitelist, status enum, revoke guard |
| Admin queue/access/schema | admin_* + allowlist (+ Director) | p_requester_id Director checks |
| Training controls | trainer role + session ownership | (API-owned; no RPCs) |
Ownership/claim restrictions
- Reports are owned by their
assigned_agent(or claimable when unassigned); supervisors can act on any case. - Training sessions are owned by their
trainer_idfor controls and theirtrainee_idfor trainee views; the trainee is additionally locked toactive/paused/completedstates (NO_ACTIVE_SESSIONotherwise). - Punishments are issuer-recorded but not issuer-owned: management is clearance-gated (
manage_punishments), not ownership-gated.