You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
API Authorization Matrix — V2 Backend (issue #458 / V2-BE-104)
Design Principles
TruthBounty's API is a deterministic indexing, projection, authentication, and delivery layer. It must never invent, mutate, or override protocol truth. Smart contracts and finalized canonical Optimism/EVM events remain authoritative for all protocol state.
The authorization layer follows these invariants:
Fail closed — any uncertainty in identity, role, signature, or configuration results in denial, never silent permit.
Two independent identity planes — the app-user plane (Prisma/wallet-based) and the admin-operator plane (TypeORM admin_users table) are kept separate with distinct guards, keys, and hierarchy models.
TypeORM only for domain persistence — Prisma manages auth-adjacent user/wallet models; no second domain ORM is introduced.
Optimism/EVM only — no Stellar, Soroban, Freighter, or alternate-chain runtime paths.
No protocol authority — the backend never issues settlement, rewards, treasury, governance, claim, or dispute mutations that would override canonical chain state.
Identity Planes
App-User Plane (Prisma UserRole)
Authenticated via wallet-signature → JWT. Role is stored in the Prisma User.role field.
Role
Description
contributor
Default. Can read public data and submit claims, evidence, votes, disputes.
moderator
Can perform state transitions on disputes and governance proposals.
admin
Full app-user privileges including reward management, reconcile, proposal execution.
Admin-Operator Plane (TypeORM AdminRole)
A separate DB-backed identity (admin_users table). Requires AdminGuard (DB lookup) + RolesGuard (hierarchy check). Roles are ordered numerically.
Role
Hierarchy Score
Capabilities
super_admin
100
All admin capabilities
administrator
80
All below + maintenance, emergency, legal holds
security_analyst
60
Security events, incidents, moderation
governance_operator
60
Governance administration
moderator
50
Moderation queue, reports
auditor
30
Read-only audit logs, reports
Guard Stack
Every request passes through guards in this order:
Request
├─ GlobalAuthGuard (APP_GUARD)
| Requires JWT for all POST/PATCH/PUT/DELETE
| GET methods public by default
| @Public() decorator bypasses this guard
├─ WalletThrottlerGuard (APP_GUARD)
Rate-limits by wallet address
├─ [Route-level guards applied via @UseGuards()]
| ├─ JwtAuthGuard — enforces valid JWT
| ├─ RolesGuard (auth/) — enforces app-user Prisma role
| ├─ AdminGuard (admin/) — DB lookup in admin_users
| ├─ RolesGuard (admin/) — hierarchy check on request.admin
| └─ ServiceAuthGuard — X-service-api-key header
|
└─ Controller handler
Route Authorization Table
Notation:
PUBLIC — no authentication required
AUTHN — valid JWT and authenticated user required
ROLE(x) — JWT + Prisma UserRole ∈ x (app-user plane)
All failure modes throw exceptions — no silent fallback to fabricated or permissive state.
Capability Tokens (PREWAVE-BE-082)
Authentication alone grants no capability. Protected API mutations require a short-lived, least-privilege capability token in addition to a valid session.
Token Claims (JWS)
Claim
Purpose
aud
Audience must match the canonical audience for the route (e.g. internal:operations).
sub
Subject — the actor identity (app-user or admin-operator).
cap
Capability name (e.g. operations.retry).
resource
Resource scope (e.g. operation:<queueId>).
nonce
Single-use nonce, recorded in the replay store.
iat/exp
Issued at / expiry (short lived).
chain
Chain identifier (e.g. Optimism chain id).
release
Release identifier bound at issuance.
deployment
Deployment identifier bound at issuance.
artifact
Artifact provenance digest bound at issuance.
Tokens are signed with the capability signing key and verified on every use. Signature verification is fail-closed: any algorithm, key, or signature mismatch results in 401.
Request Headers
Protected operations require:
X-Authority-Capability: <token> — the JWS capability token.
X-Authority-Expires-At: <iso-8601> — client-declared expiry, must match the token exp and be in the future.
Mismatch or missing headers fail closed.
Lifecycle
Issuance — authorized actor requests a capability for a specific capability/resource; server binds aud/sub/cap/resource/nonce/iat/exp/chain/release/deployment/artifact and signs.
Use — guard verifies signature, aud, sub, cap, resource, validity window, chain/release/deployment/artifact context, revocation state, and nonce unused.
Replay — nonce is consumed on first use; subsequent use returns 401. Replay store fails closed if Redis is unreachable.
Revocation — token ids or actors can be revoked; revocation store is checked on every use and fails closed.
Expiry — tokens are short-lived; expired or not-yet-valid tokens return 401.
Auditing
Issuance and use are audited with audience, subject, capability, resource, nonce id, chain/release/deployment/artifact context, and outcome. Token bytes, signatures, and secrets must never be logged.
Admin-plane routes under /v1/operations, guarded by AdminGuard + RolesGuard.
Retry submission additionally requires an Idempotency-Key, a precondition
token, and revalidated capability + expiry (fail closed).