adr-proposal: correlate the citizen reference with the openbaar register (enrich projection via the ACL) #78

Closed
opened 2026-07-14 10:02:26 +00:00 by not · 0 comments
Contributor

Problem

The self-service confirmation shows the domain registrationId (a Registration aggregate GUID), while the openbaar register shows the OpenZaak zaakId (the zaak UUID, from the NRC notification's hoofdObject). They are independent id spaces and can never match, so a citizen's reference is not findable in the public register.

Why the projection can't carry it today

Per ADR-0008: the NRC zaken/zaak/create notification carries only the zaak URL + fixed kenmerken (bronorganisatie, zaaktype, vertrouwelijkheidaanduiding) — not the registrationId. The event-subscriber may not read ZGW directly (§8.1). ADR-0008 explicitly foresaw this: "populating [bsn/naam] requires reading the zaak through the ACL (§8.1) and is its own follow-up."

Proposed decision (option #1 — correlate via the zaak identificatie, enriched through the ACL)

  1. ACL sets zaak.identificatie = registrationId at creation (domain passes its reference; extends ADR-0003 default-fill). Boundary-internal.
  2. ACL exposes a public-safe read of a zaak (the ACL is the only code that may read ZGW, §8.1) — returning at least identificatie/status.
  3. Event-subscriber, on a zaak-create notification, calls the ACL (not OpenZaak) to fetch the zaak's identificatie and stores it as a reference on the projection row and in the processed_notifications replay log, so a rebuild stays log-only (no ZGW/ACL at rebuild) per ADR-0008.
  4. Openbaar displays reference; it now equals the confirmation's registrationId.

§8 impact (why this ADR)

Introduces a new service boundary: event-subscriber → ACL (the ADR-0008 "enrich via the ACL" follow-up). This is the same mechanism that will later populate bsn/naam, so the decision is broader than the reference alone.

Open sub-decisions to settle here

  • Rebuild sourcing: store reference in the replay log (rebuild reprojects it, no ACL needed) — recommended — vs. re-fetch from the ACL at rebuild (needs the stack up).
  • Enrichment timing/idempotency: the ACL read happens on first projection of a zaak; a redelivered notification must not double-fetch (the log guard already dedups).
  • What the ACL read exposes (public-safe: identificatie, status; defer bsn/naam or include now).

Alternatives considered

  • #2 — confirmation shows the zaak reference (portal polls the domain for the zaak once opened): matches references with no boundary change, but the citizen's reference becomes a zaak UUID and it's async (no immediate reference at submit).
  • Event-subscriber reads OpenZaak directly: rejected — violates §8.1 (contradicts ADR-0008).
  • Domain writes the projection directly: rejected — blurs the read-model ownership (ADR-0008) and complicates rebuild.

Scope: services/acl, services/event-subscriber, services/projection-api (schema + reference column/migration), apps/openbaar, e2e, ADR. Sizeable — a full vertical slice.

## Problem The self-service confirmation shows the **domain `registrationId`** (a `Registration` aggregate GUID), while the openbaar register shows the **OpenZaak `zaakId`** (the zaak UUID, from the NRC notification's `hoofdObject`). They are independent id spaces and can never match, so a citizen's reference is not findable in the public register. ## Why the projection can't carry it today Per ADR-0008: the NRC `zaken/zaak/create` notification carries only the zaak URL + fixed `kenmerken` (`bronorganisatie`, `zaaktype`, `vertrouwelijkheidaanduiding`) — not the `registrationId`. The event-subscriber may not read ZGW directly (§8.1). ADR-0008 explicitly foresaw this: *"populating [bsn/naam] requires reading the zaak through the ACL (§8.1) and is its own follow-up."* ## Proposed decision (option #1 — correlate via the zaak identificatie, enriched through the ACL) 1. **ACL** sets `zaak.identificatie = registrationId` at creation (domain passes its reference; extends ADR-0003 default-fill). Boundary-internal. 2. **ACL** exposes a public-safe read of a zaak (the ACL is the only code that may read ZGW, §8.1) — returning at least `identificatie`/`status`. 3. **Event-subscriber**, on a zaak-create notification, calls the **ACL** (not OpenZaak) to fetch the zaak's `identificatie` and stores it as a `reference` on the projection row **and in the `processed_notifications` replay log**, so a rebuild stays log-only (no ZGW/ACL at rebuild) per ADR-0008. 4. **Openbaar** displays `reference`; it now equals the confirmation's `registrationId`. ## §8 impact (why this ADR) Introduces a **new service boundary: event-subscriber → ACL** (the ADR-0008 "enrich via the ACL" follow-up). This is the same mechanism that will later populate `bsn`/`naam`, so the decision is broader than the reference alone. ## Open sub-decisions to settle here - **Rebuild sourcing:** store `reference` in the replay log (rebuild reprojects it, no ACL needed) — recommended — vs. re-fetch from the ACL at rebuild (needs the stack up). - **Enrichment timing/idempotency:** the ACL read happens on first projection of a zaak; a redelivered notification must not double-fetch (the log guard already dedups). - **What the ACL read exposes** (public-safe: `identificatie`, `status`; defer bsn/naam or include now). ## Alternatives considered - **#2 — confirmation shows the zaak reference** (portal polls the domain for the zaak once opened): matches references with **no boundary change**, but the citizen's reference becomes a zaak UUID and it's async (no immediate reference at submit). - **Event-subscriber reads OpenZaak directly:** rejected — violates §8.1 (contradicts ADR-0008). - **Domain writes the projection directly:** rejected — blurs the read-model ownership (ADR-0008) and complicates rebuild. _Scope: `services/acl`, `services/event-subscriber`, `services/projection-api` (schema + `reference` column/migration), `apps/openbaar`, e2e, ADR. Sizeable — a full vertical slice._
not closed this issue 2026-07-14 14:01:52 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: eho/register-referentie#78