Roles & access
| Role | Description |
|---|---|
analyst |
read-only on own tenant |
admin |
administrator of own tenant — agents, rules, billing, identity |
owner |
full control of own tenant + role management |
auditor |
external accountant; bundle export download via Auditor Workbench (TOTP-prod) |
msp_operator |
cross-tenant operator — exclusively /api/v1/msp/overview |
(is_superadmin) |
platform superadmin; all MSP endpoints + tenant-suspend |
Endpoint gates
Section titled “Endpoint gates”Cookie auth + tenant scope is the baseline for every user.* route. On
top of that:
| Endpoint | Extra gate |
|---|---|
POST /api/v1/trust-score/weights |
role=admin|owner + TOTP-prod |
POST /api/v1/auditor/bundle |
role=admin|owner|auditor + TOTP-prod |
GET /api/v1/auditor/bundles/:t/download |
atomic one-shot, 24h expiry |
GET /api/v1/msp/overview |
role=msp_operator OR is_superadmin |
POST /api/v1/agents/:id/console/start |
role=admin|owner + TOTP-prod + reason ≥20 chars |
All agentAuth.* routes (ingest, register, whoami, heartbeat) go through
the SHA-256 bearer-token check; no role check needed.
TOTP purpose buckets
Section titled “TOTP purpose buckets”Every TOTP-gated action has its own purpose so cross-feature replay is
impossible:
| Purpose | Used by |
|---|---|
console_session |
console start |
trust_score_weights |
weights override POST |
auditor_bundle |
bundle generation POST |
force_update |
force-update push to agents |
unlock_evidence |
AI evidence pack content unlock |
A 6-digit code consumed for console_session stays invalid for that same
purpose for 30 seconds, but IS usable for auditor_bundle within that
same 30-second window — different row in consumed_totp_codes.
Every tenant table has ENABLE ROW LEVEL SECURITY with a
tenant_isolation policy. Important: this is defense in depth.
set_config('app.current_tenant', …, true) does not survive pgxpool’s
connection recycling, so every production query MUST contain an explicit
WHERE tenant_id = $1.
Exception: hub-side workers (TrustScoreWorker, IdentityHygieneWorker, SupplyChainWorker, CorrelationWorker, AuthGeoWorker) intentionally run cross-tenant — they emit/aggregate per tenant via the inner-loop scope.
Audit log
Section titled “Audit log”Every role change, weights update, bundle creation/download, link creation,
and delete operation goes through audit_log with event_type =
<feature>.<action>. Filterable in the Audit page (/audit).