docs(adr-0002): accept, and record the unbuilt Principal union as debt
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 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# ADR 0002 — User groups as actors, not bounded contexts
|
# 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
|
## Problem
|
||||||
|
|
||||||
@@ -160,11 +160,35 @@ changes is purely the _packaging_:
|
|||||||
|
|
||||||
## Out of scope here (next steps, not built)
|
## Out of scope here (next steps, not built)
|
||||||
|
|
||||||
- Building the Behandeling backoffice application.
|
|
||||||
- Real authentication: DigiD (SSP) and employee SSO / eHerkenning (backoffice).
|
- 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
|
Two bullets that stood here — building the Behandeling backoffice, and the backend aanvraag
|
||||||
second app or a role system now. Introduce the `Principal` union and the status lifecycle when the
|
status lifecycle + authorization endpoints/DTOs — **shipped** (WP-61…WP-67): `apps/behandelportal`,
|
||||||
backoffice work actually starts — YAGNI until then.
|
`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.
|
||||||
|
|||||||
Reference in New Issue
Block a user