Identity & RBAC
Three principals. One auth contract. Zero ambiguity about who did what.
Identity & RBAC is the foundational surface that every other Trinitite API leans on. Before a request reaches the proxy, the MCP gateway, the CLI firewall, or the audit ledger, it passes through a single authorization layer that answers three questions in the same order every time: who are you, what are you permitted to do, and are you scoped to this tenant?
The Three Principals
Three Principals, One Auth Contract
Every surface — proxy, gateway, firewall, vault, ledger — accepts all three principals identically. The scope resolution is different; the wire contract is not.
A human authenticates with a password (plus MFA) and carries a refreshable session token. Roles and permissions resolve through full RBAC.
An API key is a long-lived machine credential bound to an organization with an explicit scope array. No role lookup — the scopes on the key are the authorization set.
A non-human identity (NHI) is an autonomous agent or workload. It authenticates with a short-lived, just-in-time token (X-Trinitite-Nhi-Token) whose scope derives from the NHI's tier plus any explicit Guardian binding. See NHI Governance for the federation and tier story.
All three share the same header contract and the same organization-scope resolution. Your application code does not branch on principal type.
How Every Protected Endpoint Resolves
Permission Resolution — Every Protected Endpoint
One matcher, three discriminators:
- Auth type — inspected from the credential format, not the URL.
Authorization: Bearer <session>resolves to RBAC; an API key bearer token resolves to scope arrays; an NHI header triggers tier-and-binding resolution. - Permission set — roles → permissions for humans, scopes directly for keys, tier-default plus explicit binding for NHIs.
- Matcher —
*:*(platform super-admin) wins first, then<resource>:*, then the explicitresource:action. Anything else returns403 Forbiddenwitherror.details.required_permissionnaming the permission that would have been needed.
This is the same engine whether you're calling /v1/chat, /v1/mcp, /v1/cli/evaluate, /v1/logs, or /v1/attestation/*. One place to audit the authorization logic.
Tenancy Is Implicit
Organization scope is never sent in a request body. It is always derived from the credential. That design choice eliminates the entire class of "I sent the wrong org_id and leaked another tenant's data" vulnerabilities — the API simply does not accept org_id from the caller in the first place.
Every Trinitite table enforces row-level isolation on organization_id. Every compiled query carries a mandatory organization_id predicate. The safe-query builder refuses to compile a query that doesn't have one.
Public Verification Without Credentials
Public Verification — No Credential Required
Every Trinitite receipt is signed. The public key is published at a stable, unauthenticated URL — an external party can verify a Trinitite-issued attestation using a browser fetch + standard JWK tooling. No Trinitite credentials. No “trust us.”
Every Trinitite receipt — governance verdict, attestation bundle, SSAE 21 report, DSR shred confirmation — is signed with an asymmetric key (Ed25519 or ECDSA). The public half of that key is published at /v1/public/jwks and /.well-known/jwks.json, both unauthenticated endpoints.
An external auditor, regulator, or counterparty can fetch the JWKS from their own browser, cache it, and verify Trinitite-issued artifacts offline. No Trinitite API key. No portal login. No "take our word for it." This is how Trinitite artifacts work in a courtroom: the signature is verifiable without access to the platform that issued it.
Sessions, API Keys, Invitations
The operational surfaces around principals:
| Surface | Endpoint family | What it does |
|---|---|---|
| Auth | /auth/login, /auth/refresh, /auth/logout | Human session lifecycle including MFA enrolment |
| API Keys | /auth/api-keys | Create, list, rotate, revoke — scope array is immutable after issuance (new key = new scopes) |
| Users | /v1/users | CRUD for humans within the org, role assignment, suspension |
| Roles | /v1/roles | System roles (immutable) + custom roles (CRUD-able) — each role is a bundle of permission strings |
| Organization | /v1/organization | Tenant-level settings, including MFA_REQUIRED, MFA_REQUIRED_FOR_ADMINS, SSO enforcement |
| Sessions | /v1/sessions | List active sessions for a user, revoke individually or in bulk |
| Invitations | /v1/invitations | Token-based onboarding — one-shot consumable with a parallel SSO-bypass branch for SSO-enforced orgs |
For endpoint-level request/response schemas, see the API Reference → Org & RBAC section.
What You Get
| Capability | Without Trinitite | With Trinitite |
|---|---|---|
| Principal types | Users only; agents = "just another API key" | Humans + API keys + NHIs with tier-aware scoping |
| Permission resolution | Per-service middleware | One matcher, one catalogue, one audit surface |
| Tenancy enforcement | App-layer WHERE org_id = ? everywhere | Row-level + compiled-predicate guarantees |
| External verification | "Trust our logs" | Signed receipts verifiable from any browser via public JWKS |
| SSO / MFA | Bolted on per app | AUTH_ADAPTER + MFA_REQUIRED as platform-wide env vars |
| Audit of access | Scattered application logs | Every auth event in the same canonical security stream |
Next Steps
→ NHI Governance — how non-human identities federate from AWS IAM, GCP, K8s, Astrix, Aembit.
→ Policy Intelligence — turn your compliance documents into the rules the matcher enforces.
→ Glass Box Ledger — where every authorization decision is anchored for forensic replay.