OpenResidency Docs

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).

ActorWhereBy design?
Offline verifiers (anyone)GET /.well-known/did.json, /.well-known/status/*Yes — the offline-verification model
Public credential verifierPOST /residency/verify, POST /offline/qrYes — verifying needs no auth
Discovery / status probeGET /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 loginYes — capability is the interaction uid + cookie
Identity-verify callerPOST /identity/verify, /identity/challengeYes — 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:
RoleCan do
registrarEnrol citizens, issue credentials
revokerRevoke credentials
auditorRead the hash-chained audit log
supportRead registry, consent, presentation data
adminManage 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

GuardWho it admitsFile
OperatorGuard + RequireRolesOperators (5 roles)common/operator.guard.ts
UssdGatewayGuardThe USSD aggregatorcommon/ussd-gateway.guard.ts
AdminKeyGuardShared admin keycommon/api-key.guard.ts

On this page