Files
register-referentie/docs/architecture/adr-0026-mutable-default-fill-store.md
not d74270b0bd
CI / build (pull_request) Successful in 1m19s
CI / lint (pull_request) Successful in 1m32s
CI / unit (pull_request) Successful in 1m49s
CI / frontend (pull_request) Successful in 3m44s
CI / mutation (pull_request) Successful in 6m29s
CI / verify-stack (pull_request) Successful in 15m53s
docs+test(e2e): ADR-0026, S-15b demo note, default-fill e2e (refs #131)
2026-07-24 15:45:18 +02:00

2.7 KiB

ADR-0026: Runtime-mutable ACL default-fill (in-memory store, seeded from config)

  • Status: Accepted
  • Date: 2026-07-24
  • Deciders: Respellion engineering
  • Slice: S-15b (#131), second of the S-15 (#16) split

Context

ADR-0003 made the ACL default-fill the ZGW-mandatory fields it stamps on every zaak, supplied as static configuration (Acl:Defaults, read once at startup as an immutable singleton). S-15b lets a beheerder edit those values from the portal and have the next zaak reflect them — so the defaults must become mutable at runtime.

Two questions: what is editable, and where the mutable state lives.

Decision

Make the three ZGW default-fill fields a runtime-mutable, in-memory store (IDefaultFillStore), seeded from Acl:Defaults at startup. The ACL reads it per zaak; the beheer PUT /default-fill replaces it.

Only the three ZGW fill fields are editable

Acl:Defaults also carries the S-27 catalog-resolution keys (ZaaktypeIdentificatie, InformatieobjecttypeOmschrijving). Those feed the resolved-URL cache (CachedZaaktypeCatalog, ADR-0021); editing them at runtime would leave a stale cache and is catalogus wiring, not "default fill". So they stay static config and are out of scope for the CRUD. The editable set is exactly Bronorganisatie, VerantwoordelijkeOrganisatie, Vertrouwelijkheidaanduiding (DefaultFillSettings).

In-memory, not persisted

The store is a thread-safe in-memory singleton. An edit is lost on restart, when it reverts to the configured env. That is acceptable for this reference app: the slice demonstrates the pattern (beheer edits config that the ACL honours), not durable config management. The ACL stays stateless — no DB, no EF, no migration, no extra compose service.

  • ponytail ceiling: no persistence, no audit trail, no optimistic concurrency.
  • Upgrade path: back IDefaultFillStore with a DB (or an Objecten record) if durable, audited, multi-instance config is needed — the port stays the same.

Consequences

Positive

  • Demoable end to end (edit in portal → next zaak reflects it) with minimal moving parts.
  • The read path is per-zaak, so no restart and no cache concerns for the ZGW fields.

Negative / costs

  • Edits don't survive a restart and aren't shared across replicas (single-instance assumption). Documented ceiling above.
  • Two sources of default config now (static keys on AclDefaults, mutable fields in the store) — a deliberate split by editability.

Coupling rules touched (CLAUDE.md §8)

None new. The BFF→ACL edge already exists (ADR-0025); this adds a read/write pair on it. The ACL remains the owner of the ZGW-facing config.