Mock UAE Government Services

One container — gov-data lookup + UAE PASS OIDC stub — sharing one persona registry.

Endpoints

GET  /gov/persons/:emiratesId
GET  /gov/persons/:emiratesId?services=icp,mohre,gpssa

GET  /uaepass/idshub/authorize?client_id=…&redirect_uri=…&login_hint=…
POST /uaepass/idshub/token
GET  /uaepass/idshub/userinfo
GET  /uaepass/idshub/.well-known/jwks.json
GET  /uaepass/.well-known/openid-configuration

The :emiratesId parameter accepts dashed or undashed form (784-2010-0123456-7 and 784201001234567 resolve to the same persona). Omit ?services on the gov endpoint to receive all ten. The /uaepass/* routes implement the OIDC authorization-code flow with RS256-signed id_tokens — flip UAE_PASS_ENV=mock in Keycloak's env and re-run bun run keycloak:bootstrap to broker against it.

Services

KeySourceReturns
uaePass UAE PASS SOP3 profile attributes (uuid, idn, names EN/AR, nationality, mobile, email)
icp Identity & Citizenship Authority Demographics, passport, emirate, guardians, dependents
mohre Ministry of Human Resources & Emiratisation Private-sector labour contract, work permit, employer
mohesr Ministry of Higher Education & Scientific Research Registered qualifications + equivalency status
gpssa General Pension & Social Security Authority Public-sector pension membership, contributory salary, service months
mopa Ministry of Presidential Affairs Scholarships, social-assistance records
adpf Abu Dhabi Pension Fund Abu Dhabi government employment, contributory salary, months of service
cbuae Central Bank of the UAE Employment at CBUAE-licensed banks & financial institutions
mocd Ministry of Community Development Beneficiary status, social-welfare category, active program names
moe Ministry of Education K-12 school records — school, emirate, grade level, enrolment status

Seeded personas

Every Keycloak user from users-seed.json has a matching hand-authored fixture below. Same Emirates ID, same names, same nationality — so a profile synced from UAE PASS at first login lines up with the seed.

Response shape

{
  "emiratesId": "784-2010-0123456-7",
  "services": {
    "uaePass": { /* raw UAE PASS attributes */ },
    "icp":     { /* raw ICP record */ },
    "mohre":   { "error": "no_active_permit", "reason": "..." },
    "mohesr":  { /* raw MoHESR qualifications */ },
    "gpssa":   { "error": "not_enrolled",     "reason": "..." },
    "mopa":    { /* raw MOPA scholarships */ },
    "adpf":    { "error": "no_records",       "reason": "..." },
    "cbuae":   { "error": "no_records",       "reason": "..." },
    "mocd":    { "error": "not_beneficiary",  "reason": "..." },
    "moe":     { /* raw MoE school records */ }
  }
}

Each slot is either the source's native payload or { error, reason } when no record exists. Field names mirror each source's public naming so consumers can map 1:1.

Notes

Emiratis-only. Nafis is restricted to UAE nationals, so every persona's nationalityCode is AE. Non-citizen branches were removed from the synthesizer.

Deterministic. Unknown Emirates IDs fall through to an FNV-1a-seeded synthesizer — the same EID always returns the same persona across calls.

Public-sector vs private-sector. A persona has either mohre or gpssa, never both. The other slot returns { error }.

Cross-source overlap. adpf and cbuae are employer-side registries that may coexist with a federal gpssa record (e.g. an Abu Dhabi government employee shows up in both ADPF and GPSSA; a banker shows up in both CBUAE and MoHRE).