Files
register-referentie/docs/architecture/adr-0001-loose-coupling.md
Edwin van den Houdt 77297a8d8e
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
docs: MkDocs scaffold, ADR-0001, README quickstart (refs #32)
Add mkdocs.yml (Material theme + nav), docs/index.md, and the first ADR
(docs/architecture/adr-0001-loose-coupling.md, Nygard template) recording
the loose-coupling stance from CLAUDE.md §8. Rewrite the README quickstart
to be accurate and reach a green local environment in under 10 minutes
(correct clone URL, .NET 10 + container-engine prereqs, `make ci` and the
compose smoke), and document building the docs site. Ignore .venv/ and site/.

Verified: `mkdocs build` succeeds; `make lint/build/unit` green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 14:13:19 +02:00

2.3 KiB

ADR-0001: Loose coupling to upstream Common Ground modules

  • Status: Accepted
  • Date: 2026-06-03
  • Deciders: Respellion engineering
  • Template note: This is the first ADR and doubles as the worked example of the Nygard template. Copy its shape for new ADRs (adr-NNNN-title.md).

Context

This reference application orchestrates several upstream Common Ground modules — OpenZaak (ZGW APIs), Open Notificaties (NRC), Objecten/Objecttypen, Flowable, Keycloak. Each is an independently developed, independently deployed peer. The temptation in a demo is to reach straight into a peer's database or couple to its internal schema to move faster. That coupling is exactly what makes Common Ground landscapes brittle and un-upgradeable in practice.

We need a stance, recorded up front, on how our services may talk to these peers.

Decision

We integrate with upstream modules only through their documented public APIs, and we isolate that integration behind explicit anti-corruption boundaries.

Concretely (mirrors CLAUDE.md §8):

  1. The ACL is the only code that talks to ZGW APIs; no other service constructs ZGW URLs.
  2. The Workflow Client is the only code that talks to Flowable; BPMN models hold no OpenZaak knowledge.
  3. Portals talk only to the BFF — never directly to a backend or a peer module.
  4. No direct database access across services or to any peer. Each service owns its schema; the Read Projection is a rebuildable derived artefact.
  5. Idempotency at every event boundary (the Event Subscriber tolerates duplicate and out-of-order NRC events).

Bending any of these is an ADR-worthy moment (CLAUDE.md §14): stop and open an adr-proposal issue first.

Consequences

Positive

  • Upstream modules can be upgraded or swapped behind their APIs without rippling through our services.
  • Coupling is visible and minimal — anti-corruption code lives in one named place.
  • The architecture teaches the Common Ground pattern by enforcing it.

Negative / costs

  • More indirection: a translation layer (ACL, Workflow Client) instead of direct calls. Accepted — it's the point.
  • Eventual consistency across aggregates must be designed for, not assumed away.

Follow-up

  • Each integration slice that touches a boundary references this ADR; new boundary decisions get their own ADR.