feat(infra): seed BIG catalogus + JWT client for OpenZaak (refs #2)
Some checks failed
CI / lint (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / unit (pull_request) Has been cancelled
CI / compose-smoke (pull_request) Has been cancelled

Provision a JWT client declaratively via OpenZaak setup_configuration
(infra/openzaak/setup_configuration/data.yaml: JWTSecret + Applicatie with
all authorizations), and seed the BIG catalogus + a lean BIG-REGISTRATIE
zaaktype (concept) + a bsn eigenschap via the ZTC API with an idempotent
stdlib seed (infra/openzaak/seed_catalogus.py, `make openzaak-seed`).

Disable outbound notifications until NRC lands (S-01-c) so ZTC writes don't
500. Bind-mount the config with :z (SELinux) for rootless Podman. Record
the design in ADR-0002; document seeding + the dev JWT client in the
OpenZaak runbook.

Verified clean-slate: down --volumes -> up -> `make openzaak-seed` creates
the catalogus/zaaktype/eigenschap and the JWT client lists BIG-REGISTRATIE;
re-runs are all-skip (idempotent).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 15:42:27 +02:00
parent 8c5bbe05a9
commit 5966571920
6 changed files with 256 additions and 6 deletions

View File

@@ -0,0 +1,53 @@
# ADR-0002: BIG catalogus design and OpenZaak seeding
- **Status:** Accepted
- **Date:** 2026-06-03
- **Deciders:** Respellion engineering
- **Relates to:** S-01 (#2)
## Context
S-01 needs a reproducible `BIG` catalogus in OpenZaak with a **lean** `BIG-registratie`
zaaktype (only schema-mandatory fields) plus a `bsn` eigenschap, and a JWT client that
can list zaaktypen. We had to decide *how* to provision this idempotently at startup.
Findings from the OpenZaak image (`openzaak/open-zaak:latest`):
- `setup_configuration` (run by the init container) is declarative and idempotent, with
steps for **JWT secrets** and **applicaties** (`vng_api_common_credentials`,
`vng_api_common_applicaties`) — but **no step for catalogi/zaaktypen**.
- Catalogus/zaaktype/eigenschap can only be created through the **ZTC REST API**.
- Publishing a zaaktype requires ≥1 roltype, ≥1 resultaattype and ≥2 statustypen.
## Decision
1. **Provision the JWT client declaratively** via `infra/openzaak/setup_configuration/data.yaml`:
a `JWTSecret` (`big-reference-seed` / dev secret) and an `Applicatie` with
`heeft_alle_autorisaties: true`. Idempotent, runs in the init container.
2. **Seed the catalogus/zaaktype/eigenschap via the ZTC API** with an idempotent,
stdlib-only script (`infra/openzaak/seed_catalogus.py`, `make openzaak-seed`). It mints
a ZGW JWT from the provisioned client and matches existing objects (by `domein` /
`identificatie` / `naam`, querying `status=alles` so concepts are seen) before creating.
3. **Keep the zaaktype a CONCEPT (not published).** Publishing pulls in roltypen,
statustypen and resultaattypen, which go beyond "schema-mandatory"; those arrive with
the workflow/zaak slices that actually need a published type. Listing uses `status=alles`.
4. **Disable outbound notifications** (`NOTIFICATIONS_DISABLED=true`) until Open Notificaties
(NRC) lands in S-01-c — otherwise every ZTC write 500s trying to notify.
5. **Fixed dev values:** RSIN `517439943` (elfproef-valid test value); the JWT secret is
dev-only and documented as such.
## Consequences
- **Reproducible & version-robust:** the API-driven seed doesn't depend on fixture PKs or
a catalogi `setup_configuration` step that may change between versions.
- **Teaches the pattern:** the seed talks to OpenZaak exactly the way the ACL will later —
through the documented ZGW API, with a JWT (ADR-0001).
- The seed is a script, but a **data loader is explicitly anticipated** (PRD §8); it lives
under `infra/openzaak/`, not as ad-hoc tooling.
- **Follow-ups:** re-enable notifications when NRC is up (S-01-c); publish the zaaktype (add
the related types) when a slice needs to create real zaken; pin the OpenZaak image tag.
## Alternatives considered
- **Fully declarative in `data.yaml`** — rejected: no catalogi/zaaktype step exists.
- **Django `loaddata` fixture** — rejected: brittle, tied to model PKs and the exact image
version; bypasses the API the rest of the system uses.

View File

@@ -9,9 +9,32 @@ migrations, the OpenZaak API, and a celery worker.
```bash
make openzaak-up # start the stack (first run pulls images + migrates: 1-3 min)
make openzaak-smoke # start + assert it's up with auth enforced (403/302/200)
make openzaak-seed # start + seed the BIG catalogus (idempotent)
make openzaak-down # stop and wipe data
```
## Seed the BIG catalogus
`make openzaak-seed` brings the stack up and runs `infra/openzaak/seed_catalogus.py`,
which creates (idempotently, via the ZTC API):
- catalogus **BIG**
- a lean **BIG-REGISTRATIE** zaaktype (concept; only schema-mandatory fields)
- a **bsn** eigenschap on it
then confirms the JWT client can list it. See **ADR-0002** for the design (why the
zaaktype stays a concept, why notifications are disabled, why the API not a fixture).
**JWT client** (provisioned declaratively by `setup_configuration/data.yaml`, **dev only**):
| | |
|---|---|
| client_id | `big-reference-seed` |
| secret | `insecure-dev-secret-change-me` |
| authorizations | `heeft_alle_autorisaties` (all) |
The seed mints a ZGW JWT (HS256) from these and calls `/catalogi/api/v1/...`.
`make openzaak-smoke` polls until the API responds, then asserts:
| Check | Expected |
@@ -43,8 +66,9 @@ The Makefile auto-points `DOCKER_HOST` at the Podman socket when it exists, so t
- **Not in `make ci`.** The OpenZaak smoke is a separate, heavier check (large image
pull + migrations); it is intentionally kept out of `make ci` so the core gate
stays fast. Run `make openzaak-smoke` when you touch the OpenZaak stack.
- **No catalogus/zaaktypen yet.** Seeding the `BIG` catalogus + `BIG-registratie`
zaaktype and a JWT client is the next slice (**S-01-b**); authenticated zaaktype
listing isn't testable until then.
- **Notifications disabled.** `NOTIFICATIONS_DISABLED=true` until Open Notificaties
(NRC) lands in S-01-c — otherwise ZTC writes 500 trying to notify. Re-enable then.
- **Zaaktype is a concept**, not published (publishing needs roltypen/statustypen/
resultaattypen — beyond the lean seed). List with `?status=alles`.
- **Image tag.** Currently `openzaak/open-zaak:latest` via `${OPENZAAK_TAG}`; pin to
a known-good tag as part of the catalogus-design ADR.
a known-good tag (ADR-0002 follow-up).