From 4debf6614f3c011b1af477aaa96abed17c955df1 Mon Sep 17 00:00:00 2001 From: Edwin van den Houdt Date: Wed, 26 Aug 2026 17:48:48 +0200 Subject: [PATCH] docs(adr-0002): accept, and record the unbuilt Principal union as debt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR-C-005 from the ADR-conformance pass. Status Proposed -> Accepted. Two apps have shipped against this ADR and its structural rulings run in CI at severity: error with 0 violations; the other five ADRs are all Accepted. A decision CI enforces is not "Proposed". Drops two "out of scope, not built" bullets that have since shipped (WP-61..67) — the Behandeling backoffice, and the backend status lifecycle + authz DTOs: AanvraagStatusTag, GET /me (Program.cs:578), Domain/ Authorization/Authz.cs. Real authentication is the one that genuinely stays. Replaces the `Session -> Principal` deferral with a Known debt section. The deferral was conditional on the backoffice not existing yet; it does now, and the union did not follow. `grep -rn "Principal" apps libs` returns one hit, a comment. Consequently the two auth contexts are byte-identical (diff -rq: zero content differences), and behandelportal's Behandelaar still carries a bsn and logs in through DigiD — a backoffice user authenticating as a citizen, which is what §3 was written to prevent. The divergence that did happen took an orthogonal side door (medewerker.interceptor.ts) that never touches Session. The section says explicitly that the WP-67 amendment's "expected to diverge" reasoning still holds but has never been tested, so the identical copies are evidence §3 is unexecuted — not evidence §3 was wrong. Without that, a future reader is likely to "simplify" the duplication away and cement the citizen login into the backoffice. Co-Authored-By: Claude Opus 5 --- .../0002-user-groups-and-bounded-contexts.md | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/docs/reference/architecture/0002-user-groups-and-bounded-contexts.md b/docs/reference/architecture/0002-user-groups-and-bounded-contexts.md index c5cb2c8..67774bc 100644 --- a/docs/reference/architecture/0002-user-groups-and-bounded-contexts.md +++ b/docs/reference/architecture/0002-user-groups-and-bounded-contexts.md @@ -1,6 +1,6 @@ # ADR 0002 — User groups as actors, not bounded contexts -Status: Proposed · Date: 2026-07-01 +Status: Accepted · Date: 2026-07-01 · Amended 2026-08-01 (WP-67) ## Problem @@ -160,11 +160,35 @@ changes is purely the _packaging_: ## Out of scope here (next steps, not built) -- Building the Behandeling backoffice application. - Real authentication: DigiD (SSP) and employee SSO / eHerkenning (backoffice). -- The `auth` `Session → Principal` refactor — deferred until a second actor is actually introduced. -- The backend aanvraag status lifecycle + authorization endpoints/DTOs. -ponytail: this ADR draws the boundaries so nothing has to be undone later; it does **not** scaffold a -second app or a role system now. Introduce the `Principal` union and the status lifecycle when the -backoffice work actually starts — YAGNI until then. +Two bullets that stood here — building the Behandeling backoffice, and the backend aanvraag +status lifecycle + authorization endpoints/DTOs — **shipped** (WP-61…WP-67): `apps/behandelportal`, +`AanvraagStatusTag` (`Domain/Applications/AanvraagStatus.cs`), `GET /me` (`Program.cs:578`), +`Domain/Authorization/Authz.cs`. + +## Known debt: `Session → Principal` was never built + +§3's `Principal` union is the one decision here that has **not** been executed, and it is now +debt rather than a deferral. Actor #2 arrived — `apps/behandelportal` shipped — and the union +did not follow. `grep -rn "Principal" apps libs` returns a single hit: a comment in +`libs/shared/src/infrastructure/role.ts`. There is no such type. + +What that omission actually costs, measured 2026-08-26: + +- `apps/ssp/src/app/auth` and `apps/behandelportal/src/app/auth` are byte-identical — + `diff -rq` reports **zero** content differences across 9 of 11 files, the only delta being + two extra files in behandelportal. +- `behandelportal`'s Behandelaar still carries a `bsn` and logs in through `DigidAdapter`. + A backoffice user authenticates as a citizen, which is precisely what §3 was written to prevent. +- The divergence that _did_ occur took an orthogonal side door — `medewerker.interceptor.ts`, + a dev-only `X-Medewerker` header stamp that never touches `Session`. + +The WP-67 amendment above justifies keeping `auth` duplicated on the grounds that it is +"expected to diverge". That reasoning still holds — but it has never been **tested**, because +the change that would test it is this one. Read the two identical copies as evidence that +§3 is unexecuted, not as evidence that §3 was wrong. + +ponytail: this ADR draws the boundaries so nothing has to be undone later. The original +"YAGNI until the backoffice work starts" call was right when written and has now expired — +the backoffice started. `Principal` is owed.