ci: cap storybook-a11y resources + document the ACL learnings
- test-storybook:ci gets --maxWorkers=2 so the Jest runner stops spawning one headless Chromium per core and OOM-ing the Gitea runner host (the root cause). - storybook-a11y job gains a container resource ceiling (--cpus=2 --memory=4g) as a belt-and-suspenders guardrail; noted it needs a docker-mode act_runner. - openzaak-integration.md: add "Anti-corruption layer — two nested boundaries" teaching section (BFF ACL vs upstreams + FE ACL vs BFF, and the principles). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,42 @@ path async if OpenZaak becomes the default.
|
||||
}
|
||||
```
|
||||
|
||||
## Anti-corruption layer — two nested boundaries (what to learn)
|
||||
|
||||
This setup is an anti-corruption layer (ACL) **twice over**, and seeing them as a pair is the
|
||||
lesson worth taking away:
|
||||
|
||||
1. **The BFF guards everything against upstream systems.** OpenZaak's foreign model —
|
||||
URL-as-identity, a `zaaktype` that is a URL _into another service_, `{count,next,previous,
|
||||
results}` pagination, HS256 JWT auth — never leaves the BFF. `ZgwZaakMapper` translates it
|
||||
into the BFF's own `ApplicationSummaryDto`; `IZaakSource` makes the boundary swappable
|
||||
(`LocalZaakSource` vs `OpenZaakZaakSource` return the _same_ DTO).
|
||||
2. **The Angular app guards itself against the BFF.** `infrastructure/` is the only layer that
|
||||
touches the network (lint-enforced); every response crosses a `parse*` (`Result`) trust
|
||||
boundary + a `toDomain` mapper before any domain/UI code sees it (ADR-0001, ARCHITECTURE §6).
|
||||
|
||||
The DTO at `/api/v1` is the membrane between them — which is why wiring OpenZaak touched **zero
|
||||
frontend code and produced zero api-client drift**. That was the proof the ACL held.
|
||||
|
||||
Principles this demonstrates:
|
||||
|
||||
- **An ACL is a _mapping_, not a passthrough.** A DTO that is the upstream shape renamed is
|
||||
corruption with extra steps; the valuable ACLs here (`ZgwZaakMapper`, the `parse*`/`toDomain`
|
||||
pairs) actively translate a foreign model into a local one.
|
||||
- **Put the ACL where trust changes, and make it the _only_ place.** One choke point per
|
||||
boundary — the `Zgw/` folder + `IZaakSource` server-side, `infrastructure/` client-side.
|
||||
- **Decision DTOs and the ACL are complementary.** BFF-lite (server decides, FE renders) is an
|
||||
ACL against _business-rule_ drift, layered on the ACL against _data-shape_ drift.
|
||||
- **A real seam is swap-testable offline.** Because the ACL returns a stable DTO, the ZGW
|
||||
client is unit-testable with fixtures + a stub handler — no live OpenZaak.
|
||||
- **Mark the honest edges.** The `ponytail:` sync-over-async note and the "coarse status map"
|
||||
comment in `ZgwZaakMapper` show where the ACL is deliberately thin — an ACL need not be
|
||||
complete on day one, but its shortcuts should be visible.
|
||||
|
||||
Caveat: today only the cases **read** path has a source interface (`IZaakSource`). Other BFF
|
||||
endpoints still read `SeedData`/static stores directly — ACL-ready (the DTO seam exists) but not
|
||||
yet swappable. That is the WP-50/51/52 roadmap.
|
||||
|
||||
## See also
|
||||
|
||||
- [ADR-0005 — OpenZaak behind the BFF](architecture/0005-openzaak-behind-bff.md) — the decision.
|
||||
|
||||
Reference in New Issue
Block a user