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.
In plain terms. The whole system as a single story, start to finish: a state sets it up, a member of staff enrols a resident, the resident receives their credential, and then uses it to sign in to services.
The whole system is one flow. Everything else is detail hanging off this spine.
Deployer (day-0: config + keys)
→ Operator (registrar) enrols a citizen
→ foundational verify (the identity RECORD is genuine)
+ applicant binding (this person OWNS it)
+ residence (they live in this unit; origin ≠ residence)
→ mint ResidentID + sign a Verifiable Credential
→ deliver (QR / OpenID4VCI → wallet)
→ Citizen "Sign in with <State>" (Verifiable Presentation, or OTP fallback)
→ each relying party gets a pairwise sub + only consented claims, never the national ID
→ consent recorded + hash-chained audit eventStep by step
0. The deployer stands it up (day-0)
Before anyone can act, the deployer writes the jurisdiction YAML (foundational source, units, policies, relying parties) and provisions the keys and secrets. The OIDC Provider is assembled from that configuration at boot — it doesn't configure itself.
1–3. Enrolment (the registrar's job)
Enrolment is POST /residency/issue, an operator action (behind OperatorGuard +
registrar). The core ResidencyService.issue
establishes three separate proofs — never conflated:
| Proof | Question it answers | Result |
|---|---|---|
| Foundational verify | Is this a real record in the national source? | assurance level |
| Applicant binding | Is the person at the desk actually them? | none / authoritative_authentication / face_match / attended_comparison |
| Residence | Do they live in the claimed unit? | RAL0–3 |
A bare lookup passes proof #1 but binds nothing (method: none) and proves no residence — and
the credential says so, rather than implying ownership. The raw national ID is never stored;
only a tokenized subjectRef (an HMAC).
4. Issue & deliver
The service mints a ResidentID, assigns a revocation index, signs a VC, and persists a minimized record. The credential reaches the citizen as a QR (offline) or pulled into a wallet over OpenID4VCI.
5. Sign in (the citizen's job)
Later, the citizen signs in once — "Sign in with <State>". The primary factor is a Verifiable Presentation (scan a QR with the wallet); the fallback is a one-time code for feature phones. Each relying party receives a pairwise subject (a different opaque id per service) and only the claims the citizen consented to — never the national ID.
6. Consent & audit
Consent is a first-class record tied to the OIDC grant (revoked together), and every step — verify, issue, revoke, login, consent — lands on a hash-chained, tamper-evident audit log.
Where enrolment meets SSO
Enrolment's outputs are exactly what sign-in consumes: the resident record (which the OIDC provider resolves into id-token claims) and the credential (which the wallet presents as the primary login factor). So: operator enrols → record + credential exist → citizen can sign in. Continue to Credentials & trust for how the credential is verified offline.
The actor catalog
Every principal in OpenResidency, organised by authentication posture — anonymous, authenticated human, authenticated machine, and external system.
Architecture
The core / delivery / ports split — a hexagonal design where the framework-free core is the real asset and the NestJS delivery layer is disposable.