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
62 lines
2.7 KiB
Markdown
62 lines
2.7 KiB
Markdown
# 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.
|