The actor catalog
Every principal in OpenResidency, organised by authentication posture — anonymous, authenticated human, authenticated machine, and external system.
In plain terms. A list of everyone and everything that can touch the system, grouped by how much they must prove about themselves first — anonymous members of the public at one end, named government staff at the other.
The system has far more principals than "issuer, holder, verifier". Here they are by authentication posture — the sharpest way to reason about who can do what. Each guard in the code is a distinct trust boundary.
Tier 0 — anonymous / unauthenticated
Endpoints with no guard. Public by design — except one that isn't (see the callout).
| Actor | Where | By design? |
|---|---|---|
| Offline verifiers (anyone) | GET /.well-known/did.json, /.well-known/status/* | Yes — the offline-verification model |
| Public credential verifier | POST /residency/verify, POST /offline/qr | Yes — verifying needs no auth |
| Discovery / status probe | GET /residency/countries, GET /residency/:residentId | ~ Semi-public (non-sensitive status only) |
| Developer / integrator | /openapi.yaml, /docs, the sdk/ | Yes — public API docs |
| Pre-authentication citizen | /interaction/* during login | Yes — capability is the interaction uid + cookie |
| Identity-verify caller | POST /identity/verify, /identity/challenge | Yes — operator-only, and rate limited |
Why identity lookup is operator-only
Asking "does this person exist in the national register?" is a question with a cost. Answered freely, it lets anyone confirm whether a given identity number is real, probe for details, and run up charges on the government's gateway. So the lookup sits behind an operator login and a per-caller rate limit — a named member of staff asks it, on the record, or nobody does.
Tier 1 — authenticated humans
- Citizen / resident — authenticates to sign in, via a Verifiable Presentation (primary) or a one-time code (fallback).
- Operators — government staff, five roles, each gating different routes:
| Role | Can do |
|---|---|
registrar | Enrol citizens, issue credentials |
revoker | Revoke credentials |
auditor | Read the hash-chained audit log |
support | Read registry, consent, presentation data |
admin | Manage operator accounts & keys — implies all roles |
- Oversight / regulator — reads the tamper-evident audit chain (via
auditor). A first-class consumer, not an afterthought.
Tier 2 — authenticated machines
- Sector RP — an OIDC client authenticating at the token endpoint.
- Operator API key — a machine acting as an operator identity (inherits its roles), bounded lifetime.
- USSD gateway — the SMS/USSD aggregator, authenticated by a shared secret; trusted to assert the caller's phone number.
- Shared admin key — an identity-less keyholder; demo / bootstrap only.
Tier 3 — external systems
Foundational ID source (NIN/NIMC, Aadhaar, REST/XML/dataset) · federated staff IdP (for operator SSO) · messaging aggregator · external contact directory · wallet (Inji / OpenWallet) · edge / Ingress gateway.
The deployer (day-0), and a non-actor
- Deployer / platform administrator — the DevOps actor who, before anyone else acts, writes the jurisdiction config, provisions keys/secrets, and boots the service. It is the most privileged actor of all (it defines what every guard checks), yet it is not an in-app principal — which is exactly why the HSM custody and fail-closed startup guards exist: to constrain it.
- No background/system actor — there is no cron/worker/scheduler in the codebase. Every action is externally triggered. (This is why the "reconcile provisional credentials" gap needs new background-job infrastructure, not just a handler.)
The guards, in code
| Guard | Who it admits | File |
|---|---|---|
OperatorGuard + RequireRoles | Operators (5 roles) | common/operator.guard.ts |
UssdGatewayGuard | The USSD aggregator | common/ussd-gateway.guard.ts |
AdminKeyGuard | Shared admin key | common/api-key.guard.ts |
Roles & role mapping
How the abstract Issuer/Holder/Verifier roles map onto OpenResidency's concrete parties — the Provider, the code, relying parties, operators, and the deployer.
The trust flow
The end-to-end lifecycle — deployer stands up the platform, an operator enrols a citizen, a credential is issued, the citizen signs in, and consent and audit record it.