# Demo script A running log of demoable outcomes, one section per slice. Each entry is a short, copy-pasteable walkthrough against a local `make up` stack. --- ## S-07 — BFF: the portals' single backend **Outcome:** the BFF validates Keycloak `digid` tokens on the self-service submit (forwarding the bsn to the domain) and serves the openbaar register anonymously with only public-safe fields — the front door the portals (S-08/S-09) will talk to. **The path:** portal → BFF `POST /self-service/registrations` (token-gated) → domain; and BFF `GET /openbaar/register` (anonymous) → projection-api. See ADR-0010. ```bash # 1. Bring the full stack up. make up # 2. Drive the BFF end-to-end (401 without a token, 202 with a real digid token, anonymous openbaar). make verify-bff # → "OK — BFF: 401 without token, 202 with a digid token, anonymous ..." # 3. Try it by hand (BFF on host port 8080). # a) A digid access token for the mock user jan-burger (bsn 123456782): tok=$(curl -s -X POST http://localhost:8180/realms/digid/protocol/openid-connect/token \ -d grant_type=password -d client_id=big-portal -d username=jan-burger -d password=test123 \ | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])") # b) Submit — without the token it is 401; with it, 202: curl -s -o /dev/null -w "no token -> %{http_code}\n" -X POST http://localhost:8080/self-service/registrations curl -s -o /dev/null -w "with token-> %{http_code}\n" -X POST http://localhost:8080/self-service/registrations \ -H "Authorization: Bearer $tok" # c) The openbaar register is anonymous and exposes only id + status (never the bsn): curl -fsS http://localhost:8080/openbaar/register | jq ``` > The self-service token is validated against Keycloak's `digid` realm; the openbaar lookup needs no > token (S-09). The generated contract lives at `services/bff/openapi.json` — S-08's client is built > from it. --- ## S-05 — BIG Domain Service: submit a registration **Outcome:** submitting a registration starts a Flowable process; the external-task worker opens a zaak via the ACL and records it on the aggregate — the upstream half of the skeleton that produces the zaak S-06 then projects. **The path:** domain `POST /registrations` → Flowable `registratie` process → `OpenZaakAanmaken` worker → ACL → OpenZaak; `GET /registrations/{id}` shows the opened zaak (ADR-0009). ```bash # 1. Bring the full stack up (seeds config, builds our services, waits for health). make up # 2. Drive the full path end-to-end. This also seeds a published BIG zaaktype and points the # ACL at it (the zaak's zaaktype URL is server-assigned, so it isn't known at bring-up). make verify-domain # → "OK — the domain opened a zaak and recorded it on the registration" # 3. Submit one yourself (domain on host port 8130). Returns 202 + a Location to read back. loc=$(curl -fsS -D - -o /dev/null -X POST http://localhost:8130/registrations \ -H 'Content-Type: application/json' -d '{"bsn":"123456782"}' | sed -n 's/\r$//; s/^[Ll]ocation: //p') # 4. The worker opens the zaak off the request path (eventual consistency, ADR-0009); poll # until zaakUrl is filled. (Step 2 must have run first, so the ACL knows the zaaktype.) curl -fsS "http://localhost:8130$loc" | jq # → { "registrationId": "...", "status": "Ingediend", "zaakUrl": "http://.../zaken/api/v1/zaken/" } ``` > Registration state is in-memory for this slice (ADR-0009); the rebuildable read model is the > projection (S-06), fed by the very zaak this flow opens. --- ## S-06 — Event Subscriber + read projection **Outcome:** a zaak created in OpenZaak flows through NRC to the Event Subscriber, which projects it into a rebuildable read projection the projection-api serves. **The path:** OpenZaak → (notification) NRC → (abonnement callback) Event Subscriber → `register_projection` → projection-api `GET /register`. ```bash # 1. Bring the full stack up (seeds config, builds our services, waits for health). make up # 2. Register the Event Subscriber's abonnement and create a zaak, then read it back. # (The verify-projection check does exactly this end-to-end and asserts the result.) make verify-projection # → "OK — projection-api serves zaak with status INGEDIEND" # 3. Observe the projection directly via the read API (host port 8120). curl -fsS http://localhost:8120/register | jq # → [ { "id": "", "status": "INGEDIEND", "bsn": null, "naamPlaceholder": null } ] # 4. Idempotency + rebuild: replays don't duplicate; a rebuild repopulates from the # notification log (no OpenZaak access needed — ADR-0008). curl -fsS -X POST http://localhost:8110/admin/rebuild # Event Subscriber, host port 8110 curl -fsS http://localhost:8120/register | jq 'length' # → unchanged ``` > `bsn` / `naam_placeholder` are deferred (ADR-0008) — the notification doesn't carry them and > the subscriber may not read OpenZaak directly (§8.1). They surface in a later slice.