refactor: strip WP-/RB- ticket refs from backend (RD-19)
The backend half of the sweep RD-18 did for the front end. git blame holds the provenance and stays correct when the code moves; the comment names a closed ticket and tells the reader nothing the sentence around it does not. public/letter.css and LetterHtml.golden.html change together, because the renderer inlines the CSS and the golden file snapshots the result. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+17
-17
@@ -1,4 +1,4 @@
|
||||
# OpenZaak integration harness (WP-54)
|
||||
# OpenZaak integration harness
|
||||
|
||||
A real OpenZaak, for developing/testing the ZGW seam (`backend/src/BigRegister.Api/Zgw/`)
|
||||
against something that isn't a fixture or a stub `HttpMessageHandler`. Deliberately **not**
|
||||
@@ -22,7 +22,7 @@ published), and one zaak (`BIG-2026-000123`) with an initiator rol for the seede
|
||||
(`111222333` — the same fixture BSN `OpenZaakZaakSourceTests.cs` uses). It writes what it
|
||||
seeded to `seeded.env` (gitignored) and prints a summary.
|
||||
|
||||
**Idempotent (WP-56)** — every resource is looked up by its natural key (the same field(s)
|
||||
**Idempotent** — every resource is looked up by its natural key (the same field(s)
|
||||
OpenZaak enforces identity on: catalogus by `domein`+`rsin`, zaaktype by `catalogus`+
|
||||
`identificatie`, statustype by `zaaktype`+`volgnummer`, roltype by `zaaktype`+
|
||||
`omschrijvingGeneriek`, zaak by `identificatie`) before creating it, so re-running against an
|
||||
@@ -81,7 +81,7 @@ and is **excluded** from the default `dotnet test` run and from CI (`ci.yml`,
|
||||
`scripts/ci-local.sh` both filter `Category!=Integration`) — it only passes with this harness
|
||||
up, so it never runs where the harness doesn't exist.
|
||||
|
||||
## Notifications-enabled profile (WP-58)
|
||||
## Notifications-enabled profile
|
||||
|
||||
The base harness above never delivers a real notification (`NOTIFICATIONS_DISABLED: 'true'`,
|
||||
no celery worker) — fine for the read/write ZGW seam, not for proving a live webhook round-trip.
|
||||
@@ -137,7 +137,7 @@ already high going in; `ZGW_DEBUG_HTTP=1` on `api`, see `docker-compose.openzaak
|
||||
diagnostics to help nail the cause next time it reproduces). Prints the URLs to check
|
||||
afterward and the teardown commands.
|
||||
|
||||
Two caveats, both non-fatal (WP-60 catches and flags rather than surfacing an error):
|
||||
Two caveats, both non-fatal (the BFF catches and flags rather than surfacing an error):
|
||||
**only `herregistratie` has a seeded zaaktype** here, so submit that wizard to prove a real
|
||||
write; and **no Documenten content is seeded**, so a document upload's ZGW half no-ops (pick
|
||||
"per post" in the wizard's document step, or ignore it).
|
||||
@@ -148,7 +148,7 @@ write; and **no Documenten content is seeded**, so a document upload's ZGW half
|
||||
docker compose -f docker-compose.openzaak.yml down -v
|
||||
```
|
||||
|
||||
## Production (WP-55)
|
||||
## Production
|
||||
|
||||
This dev harness stays dev-only: hardcoded `SECRET_KEY`, `POSTGRES_HOST_AUTH_METHOD=trust`,
|
||||
`IS_HTTPS: 'no'`, a client secret checked into `setup_configuration/data.yaml`. A real
|
||||
@@ -188,7 +188,7 @@ app change.
|
||||
Django migrations then `setup_configuration` against `setup_configuration/data.yaml`), and
|
||||
`web` (the OpenZaak API on `:8000`). Pinned to `openzaak/open-zaak:1.29.1`. No
|
||||
celery/celery-beat/celery-flower/nginx — trimmed for a lean, fast-booting harness; layer
|
||||
`docker-compose.openzaak.notificaties.yml` (WP-58) on top for a real async notification
|
||||
`docker-compose.openzaak.notificaties.yml` on top for a real async notification
|
||||
delivery round-trip.
|
||||
`NOTIFICATIONS_DISABLED=true` is required, not optional: without it, OpenZaak 500s (and
|
||||
**rolls back the whole create**) on any notified resource — see the compose file's comment.
|
||||
@@ -197,14 +197,14 @@ app change.
|
||||
one `bigregister-test` client with `heeft_alle_autorisaties: false` — this YAML mechanism
|
||||
(`vng_api_common`'s `ApplicatieConfigurationModel`) has no field for granular scopes at all,
|
||||
so the client starts with zero Autorisaties; `bootstrap-catalogus.sh` grants the exact ones
|
||||
it needs (WP-57).
|
||||
it needs.
|
||||
- `bootstrap-catalogus.sh` — the business content (catalogus/zaaktype/zaak/…) `setup_configuration`
|
||||
has no YAML for; every field value here was checked against OpenZaak's own OpenAPI spec and a
|
||||
live run of this exact script, not guessed (two OpenZaak quirks it works around: a zaaktype
|
||||
needs ≥1 resultaattype and 2 statustypen before it can be published, and its
|
||||
`selectielijstklasse` and the zaaktype's `selectielijstProcestype` must reference the same
|
||||
`procesType` on the public VNG selectielijst API). Idempotent (WP-56) — see "Bring it up" above.
|
||||
Also grants `bigregister-test`'s Autorisaties via `manage.py shell` (WP-57, see the script's
|
||||
`procesType` on the public VNG selectielijst API). Idempotent — see "Bring it up" above.
|
||||
Also grants `bigregister-test`'s Autorisaties via `manage.py shell` (see the script's
|
||||
top comment): `ztc` scopes (`catalogi.lezen`/`catalogi.schrijven`, this script's own
|
||||
content-creation needs) up front, `zrc` scopes (`zaken.aanmaken`/`zaken.bijwerken`/
|
||||
`zaken.lezen`, scoped to the one zaaktype the BFF and this script both use) once that
|
||||
@@ -213,26 +213,26 @@ app change.
|
||||
grant (scoped to a real `informatieobjecttype`, which this script would also need to seed)
|
||||
when a later WP wires DRC content into this harness.
|
||||
- **Not here**: Documenten (DRC) content, or a real Notificaties API (NRC) — add DRC content if a
|
||||
later WP needs to prove that round-trip against a live instance too (WP-51 is fixture-tested
|
||||
later change needs to prove that round-trip against a live instance too (fixture-tested
|
||||
today). A real NRC is a separate application (`open-notificaties`) this harness deliberately
|
||||
doesn't stand up — WP-58's notifications-enabled profile (below) proves live delivery without
|
||||
doesn't stand up — the notifications-enabled profile (below) proves live delivery without
|
||||
one, since this harness only ever has one subscriber.
|
||||
- `docker-compose.openzaak.notificaties.yml` (WP-58) — opt-in overlay: one celery worker for
|
||||
- `docker-compose.openzaak.notificaties.yml` — opt-in overlay: one celery worker for
|
||||
OpenZaak (async notification delivery needs it) + `NOTIFICATIONS_DISABLED: 'false'`, joined to
|
||||
the repo root's own compose network so it can reach the `api` container by name (tried
|
||||
`host.docker.internal:host-gateway` first; this environment's rootless Podman doesn't route
|
||||
container→host-port traffic through it). See "Notifications-enabled profile" below.
|
||||
- `bootstrap-notificaties.sh` (WP-58) — points OpenZaak's `NotificationsConfig` at the BFF's
|
||||
- `bootstrap-notificaties.sh` — points OpenZaak's `NotificationsConfig` at the BFF's
|
||||
webhook via a `zgw_consumers.Service` (`update_or_create`, idempotent) instead of provisioning
|
||||
a real NRC `abonnement`; preflights that the BFF is reachable with the right secret first
|
||||
(a misconfigured target here means every write to a notified resource 500s and rolls back).
|
||||
- `verify-notificatie.sh` (WP-58) — the runnable end-to-end check: PATCHes the seeded zaak, polls
|
||||
the BFF's own `/admin/audit` (WP-41) for the resulting `zgw:notificatie`/`allow` row.
|
||||
- `docker-compose.openzaak.prod.yml` (WP-55) — production overrides layered on top of
|
||||
- `verify-notificatie.sh` — the runnable end-to-end check: PATCHes the seeded zaak, polls
|
||||
the BFF's own `/admin/audit` for the resulting `zgw:notificatie`/`allow` row.
|
||||
- `docker-compose.openzaak.prod.yml` — production overrides layered on top of
|
||||
`docker-compose.openzaak.yml`: real `SECRET_KEY`/DB password/site domain/allowed-hosts from
|
||||
required env vars (fails fast if unset), password DB auth instead of `trust`, `IS_HTTPS: 'yes'`.
|
||||
Adds no image/service of its own — see "Production" above for the full flow.
|
||||
- `setup_configuration/data.prod.yaml.template` (WP-55) — the prod counterpart of `data.yaml`
|
||||
- `setup_configuration/data.prod.yaml.template` — the prod counterpart of `data.yaml`
|
||||
with no secret in it (`${OPENZAAK_CLIENT_SECRET}` etc. as placeholders); `render-prod-secrets.sh`
|
||||
fills it in to the gitignored `data.prod.yaml`, which the prod compose override mounts over
|
||||
the container's `data.yaml`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# WP-54 (seeding) / WP-56 (idempotency) — seeds business content
|
||||
# Seeds business content
|
||||
# (catalogus/zaaktype/statustype/roltype/zaak/status/rol) into the OpenZaak harness started
|
||||
# by docker-compose.openzaak.yml. `setup_configuration/data.yaml` only covers infra config
|
||||
# (JWTSecret + Applicatie) — confirmed by reading the installed `django_setup_configuration`
|
||||
@@ -17,7 +17,7 @@
|
||||
# zaak's `identificatie` + `url` on success; also writes them to seeded.env (repo-ignored) for
|
||||
# OpenZaakIntegrationTests.cs to assert against.
|
||||
#
|
||||
# WP-57: `bigregister-test` starts with ZERO Autorisaties (data.yaml sets
|
||||
# `bigregister-test` starts with ZERO Autorisaties (data.yaml sets
|
||||
# heeft_alle_autorisaties: false) — the setup_configuration YAML has no field for granular
|
||||
# scopes at all (confirmed from vng_api_common's own ApplicatieConfigurationModel), so this
|
||||
# script grants them itself via `manage.py shell` (Django ORM, inside the `web` container) at
|
||||
@@ -71,7 +71,7 @@ oz() {
|
||||
echo "$json"
|
||||
}
|
||||
|
||||
# Grant (replace) an Autorisatie for $CLIENT_ID directly via the ORM (see the WP-57 note up
|
||||
# Grant (replace) an Autorisatie for $CLIENT_ID directly via the ORM (see the note up
|
||||
# top for why this bypasses the REST Autorisaties API). $1 = component, $2 = python list
|
||||
# literal of scopes, $3.. = extra `Autorisatie(...)` kwargs as `name=value` (value already a
|
||||
# valid Python literal, e.g. a quoted URL).
|
||||
@@ -168,7 +168,7 @@ print(json.dumps({
|
||||
echo " created: $zaaktype_url"
|
||||
fi
|
||||
|
||||
echo "Granting zrc scopes (zaken.aanmaken, zaken.bijwerken, zaken.lezen, zaken.statussen.toevoegen), scoped to $zaaktype_url — the one zaaktype this harness (and the BFF's Zgw:ZaaktypeUrls config) ever uses. zaken.statussen.toevoegen is needed for WP-66's besluit write: zaken.aanmaken only covers the ONE status set at zaak creation, a later status (the besluit's eindstatus) needs this scope or OpenZaak 403s ('mag je slechts 1 status zetten')..."
|
||||
echo "Granting zrc scopes (zaken.aanmaken, zaken.bijwerken, zaken.lezen, zaken.statussen.toevoegen), scoped to $zaaktype_url — the one zaaktype this harness (and the BFF's Zgw:ZaaktypeUrls config) ever uses. zaken.statussen.toevoegen is needed for the besluit write: zaken.aanmaken only covers the ONE status set at zaak creation, a later status (the besluit's eindstatus) needs this scope or OpenZaak 403s ('mag je slechts 1 status zetten')..."
|
||||
grant_scopes zrc '["zaken.aanmaken", "zaken.bijwerken", "zaken.lezen", "zaken.statussen.toevoegen"]' \
|
||||
"zaaktype=\"$zaaktype_url\"" \
|
||||
'max_vertrouwelijkheidaanduiding="openbaar"'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# WP-58 — points OpenZaak's own NotificationsConfig straight at this repo's BFF webhook
|
||||
# (POST /api/v1/zgw/notificaties, WP-52) instead of standing up a real Notificaties API (NRC)
|
||||
# Points OpenZaak's own NotificationsConfig straight at this repo's BFF webhook
|
||||
# (POST /api/v1/zgw/notificaties) instead of standing up a real Notificaties API (NRC)
|
||||
# + abonnement — see docker-compose.openzaak.notificaties.yml's ponytail note for why. Requires
|
||||
# that overlay running (adds the celery worker + flips NOTIFICATIONS_DISABLED) AND the repo
|
||||
# root's own `docker compose up` running (the overlay joins its `api` container's network —
|
||||
@@ -41,7 +41,7 @@ from zgw_consumers.models import Service
|
||||
service, _ = Service.objects.update_or_create(
|
||||
slug="bff-webhook",
|
||||
defaults=dict(
|
||||
label="BIG-register BFF webhook (WP-58)",
|
||||
label="BIG-register BFF webhook",
|
||||
api_type=APITypes.orc,
|
||||
api_root="$BFF_API_ROOT",
|
||||
auth_type=AuthTypes.api_key,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
# 1. Why container-to-container instead of `http://localhost:8000`: this dev environment's
|
||||
# rootless Podman drops container→host-port traffic through `host.docker.internal`
|
||||
# (confirmed for the WP-58 notifications overlay's celery worker — DNS resolves it, every
|
||||
# (confirmed for the notifications overlay's celery worker — DNS resolves it, every
|
||||
# TCP connect times out).
|
||||
#
|
||||
# 2. Why the ROOT project's `api` joins INTO this project's network (below), not the other way
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# WP-58 — notifications-enabled overlay, layered ON TOP of docker-compose.openzaak.yml
|
||||
# Notifications-enabled overlay, layered ON TOP of docker-compose.openzaak.yml
|
||||
# (never alone):
|
||||
#
|
||||
# docker compose -f docker-compose.openzaak.yml -f docker-compose.openzaak.notificaties.yml up -d
|
||||
#
|
||||
# The base file stays the WP-54 fast-iteration default (NOTIFICATIONS_DISABLED=true, no
|
||||
# The base file stays the fast-iteration default (NOTIFICATIONS_DISABLED=true, no
|
||||
# worker) so nobody testing the read/write seam has to pull/boot this. This overlay flips
|
||||
# NOTIFICATIONS_DISABLED off and adds the one celery worker needed to actually deliver a
|
||||
# notification (see base file's ponytail note).
|
||||
@@ -14,7 +14,7 @@
|
||||
# bootstrap-notificaties.sh points OpenZaak's NotificationsConfig straight at the BFF's webhook
|
||||
# instead — same delivery proof (a real write → a real HTTP POST → the BFF's audit trail), far
|
||||
# less harness to stand up and keep alive. Add a real NRC (+ abonnement/kanaal routing) if a
|
||||
# later WP needs more than one subscriber or real kanaal-filtered fan-out.
|
||||
# later change needs more than one subscriber or real kanaal-filtered fan-out.
|
||||
#
|
||||
# No celery-beat here: send_notification is a plain async task (client.post on save), not a
|
||||
# scheduled one — beat only matters on a real NRC's polling side, which this harness doesn't have.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# WP-55 — production overrides for docker-compose.openzaak.yml: real secrets, real DB auth,
|
||||
# Production overrides for docker-compose.openzaak.yml: real secrets, real DB auth,
|
||||
# HTTPS-aware settings. Use ON TOP of the base file, never alone (it has no image/ports of its
|
||||
# own to add — see backend/openzaak/README.md for the required env vars and full flow):
|
||||
#
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# WP-54 — a real OpenZaak to develop/test the ZGW seam against, kept OUT of the root
|
||||
# A real OpenZaak to develop/test the ZGW seam against, kept OUT of the root
|
||||
# docker-compose.yml on purpose (see backend/openzaak/README.md): OpenZaak is a full Django
|
||||
# stack (postgres + redis), heavy compared to this repo's own FE+BFF, and nobody who isn't
|
||||
# touching the ZGW slice should have to pull/boot it.
|
||||
#
|
||||
# ponytail: trimmed vs. open-zaak's own published compose — no celery/celery-beat/celery-flower
|
||||
# (async notification delivery, never asserted by the integration test) and no nginx (the test
|
||||
# hits web's port directly). Add them back only if a later WP needs an actual notification
|
||||
# round-trip against this harness (NRC delivery is already covered by fixture tests, WP-52).
|
||||
# hits web's port directly). Add them back only if a later change needs an actual notification
|
||||
# round-trip against this harness (NRC delivery is already covered by fixture tests).
|
||||
services:
|
||||
db:
|
||||
image: postgis/postgis:17-3.5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# WP-55 — renders setup_configuration/data.prod.yaml.template into the gitignored
|
||||
# Renders setup_configuration/data.prod.yaml.template into the gitignored
|
||||
# data.prod.yaml docker-compose.openzaak.prod.yml mounts over the container's data.yaml.
|
||||
# Run this once before `docker compose ... up` in a production deploy; re-run whenever the
|
||||
# secrets rotate. Fails fast (no output file) if a required env var is missing — never
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Prod counterpart of data.yaml (WP-54's dev-only version, kept as-is for local iteration —
|
||||
# Prod counterpart of data.yaml (the dev-only version, kept as-is for local iteration —
|
||||
# see docker-compose.openzaak.yml's own comment on why it hardcodes a client secret). This
|
||||
# template has no secret in it; render-prod-secrets.sh substitutes OPENZAAK_CLIENT_SECRET
|
||||
# into it to produce the gitignored data.prod.yaml that docker-compose.openzaak.prod.yml
|
||||
# mounts over the container's data.yaml.
|
||||
#
|
||||
# Least-privilege client scopes (WP-57): heeft_alle_autorisaties is false, matching the dev
|
||||
# Least-privilege client scopes: heeft_alle_autorisaties is false, matching the dev
|
||||
# harness (setup_configuration has no YAML field for granular `autorisaties` — see
|
||||
# data.yaml's comment). This template only covers infra config; a real deploy must grant this
|
||||
# client's Autorisaties the same way bootstrap-catalogus.sh does for the dev harness — via
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# documented CLI config mechanism — see docker-compose.openzaak.yml) instead of the Django
|
||||
# admin. Creates the ONE application the bootstrap script + integration test authenticate as.
|
||||
#
|
||||
# heeft_alle_autorisaties is false (WP-57, least privilege) — but
|
||||
# heeft_alle_autorisaties is false (least privilege) — but
|
||||
# `ApplicatieConfigurationModel` (vng_api_common's setup_configuration step) has no field for
|
||||
# granular `autorisaties` at all, only this boolean. So this client starts with ZERO scopes;
|
||||
# bootstrap-catalogus.sh grants the exact ones it needs via `manage.py shell` (Django ORM,
|
||||
@@ -12,7 +12,7 @@ sites_config_enable: true
|
||||
sites_config:
|
||||
items:
|
||||
- domain: localhost:8000
|
||||
name: OpenZaak (WP-54 harness)
|
||||
name: OpenZaak (harness)
|
||||
|
||||
vng_api_common_credentials_config_enable: true
|
||||
vng_api_common_credentials:
|
||||
@@ -26,5 +26,5 @@ vng_api_common_applicaties:
|
||||
- uuid: 5a09b3c9-6a54-4b2b-8f3c-1f9b6b6a3a01
|
||||
client_ids:
|
||||
- bigregister-test
|
||||
label: BIG-register BFF (WP-54 test harness)
|
||||
label: BIG-register BFF (test harness)
|
||||
heeft_alle_autorisaties: false
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# WP-58 — proves the "real write -> real webhook delivery" round-trip end-to-end: PATCHes the
|
||||
# Proves the "real write -> real webhook delivery" round-trip end-to-end: PATCHes the
|
||||
# zaak bootstrap-catalogus.sh seeded (a notified ZRC resource), then polls the BFF's own audit
|
||||
# trail (WP-41) for the resulting `zgw:notificatie` row. Requires bootstrap-catalogus.sh and
|
||||
# trail for the resulting `zgw:notificatie` row. Requires bootstrap-catalogus.sh and
|
||||
# bootstrap-notificaties.sh to have already run.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||
@@ -29,7 +29,7 @@ jwt() {
|
||||
printf '%s.%s' "$signing_input" "$sig"
|
||||
}
|
||||
|
||||
echo "Triggering a real write: PATCH $ZAAK_URL (bijwerken — WP-57 granted zaken.aanmaken"
|
||||
echo "Triggering a real write: PATCH $ZAAK_URL (bijwerken — the client is granted zaken.aanmaken"
|
||||
echo "for exactly ONE status, so a second status create 403s; a zaak update is the write this"
|
||||
echo "client's narrowed scope can repeat)..."
|
||||
response=$(curl -sS -X PATCH -H "Authorization: Bearer $(jwt)" -H 'Content-Type: application/json' \
|
||||
|
||||
Reference in New Issue
Block a user