Citizen services¶
The platform ships both a citizen-facing service portal and an
officer-facing queue. Both sit on one data model: a gov_services
catalogue, gov_applications requests, and an append-only timeline.
The vocabulary is aligned with CPSV-AP 3.2.0 (SEMIC — Public Service, Evidence, Life Event); the outcome vocabulary follows the Dutch ZGW model.
Two surfaces¶
| Surface | Who | Path | Permission |
|---|---|---|---|
| Citizen portal | Any signed-in user | /me/services, /me/applications, /me/references, /me/notifications, /me/payments, /me/appointments |
signed in |
| Officer queue | Manager / case officer | /manager/requests, /manager/dashboard |
gov.review |
Fulfilment modes¶
| Mode | Meaning |
|---|---|
auto |
Read straight from the registry and issued (references, certificates of fact). No human in the loop — fulfilled in a single transaction at submission. |
manual |
Fulfilled after an officer reviews and decides. |
Application state machine¶
The allowed transitions are declared once in the domain, and the repository
SQL enforces them again as WHERE status IN (...) — which closes the race
between two decisions arriving at the same time.
stateDiagram-v2
[*] --> submitted
submitted --> registered
submitted --> cancelled
registered --> in_review
registered --> info_required
registered --> approved
registered --> completed
registered --> rejected
registered --> expired
in_review --> info_required
in_review --> approved
in_review --> completed
in_review --> rejected
info_required --> in_review
info_required --> approved
info_required --> completed
info_required --> rejected
approved --> completed
completed --> [*]
rejected --> [*]
cancelled --> [*]
expired --> [*]
| Status | Meaning |
|---|---|
submitted |
The citizen sent it |
registered |
Formally registered — the SLA clock starts |
in_review |
An officer is reviewing |
info_required |
Waiting for extra evidence from the citizen |
approved |
Decided, but the output has not been delivered yet (physical ID card, certificate) |
completed |
The output was issued |
rejected · cancelled · expired |
Terminal states |
approved vs completed
When the output can be issued immediately (a reference), the application
goes straight to completed — an intermediate state would be noise. When
the output is a physical artefact, approved means "decided, not yet
delivered" and completed follows later.
Outcome vocabulary¶
granted · refused · withdrawn · not_admissible · processed
Each agency may define its own progress vocabulary, but a shared outcome vocabulary is what makes reporting and statistics possible.
Citizen endpoints¶
| Method | Path | What |
|---|---|---|
GET |
/api/v1/gov/services |
Service catalogue |
GET |
/api/v1/gov/life-events |
Grouped by life event |
GET |
/api/v1/gov/overview |
Home page roll-up |
GET · POST |
/api/v1/gov/applications |
List / submit |
GET |
/api/v1/gov/applications/{id}/timeline |
Append-only progress log |
POST |
/api/v1/gov/applications/{id}/cancel |
Citizen withdraws |
POST |
/api/v1/gov/applications/{id}/provide-info |
Supply extra evidence |
GET · POST |
/api/v1/gov/references |
List / request a reference |
GET |
/api/v1/gov/notifications |
Notifications |
POST |
/api/v1/gov/notifications/{id}/read, /read-all |
Mark read |
GET |
/api/v1/gov/payments |
Taxes, fees, fines |
POST |
/api/v1/gov/payments/{id}/pay |
Pay |
GET · POST |
/api/v1/gov/appointments |
Appointments |
POST |
/api/v1/gov/appointments/{id}/cancel |
Cancel |
Every write goes through the govWrite limiter (30/min, burst 15).
Officer queue¶
Only gov.review holders reach /api/v1/gov/officer/*. The check is applied as
route-level middleware, so it is not repeated per handler.
| Method | Path | What |
|---|---|---|
GET |
/officer/stats |
Queue roll-up (separate from the citizen overview) |
GET |
/officer/queue |
Filterable queue |
GET |
/officer/queue/{id} |
One application |
POST |
/officer/queue/{id}/assign |
Assign to self or someone else |
POST |
/officer/queue/{id}/decide |
Decision (approved / rejected) |
POST |
/officer/queue/{id}/complete |
Issue the output and close |
POST |
/officer/queue/{id}/request-info |
Ask the citizen for more |
The public catalogue¶
The catalogue is readable without signing in:
GET /api/v1/catalog/services— published servicesGET /api/v1/catalog/services/{id}— one service passportGET /api/v1/catalog/life-events— life events
Its source of truth is the service registry (R1) — see Registry & Relay. A service does not appear in the public catalogue until it is published.