feat(behandelportal): WP-62 medewerker caller identity + authz seam

Splits backend CallerIdentity into the two ADR-0002 §3 actor kinds
(ZorgverlenerCaller/MedewerkerCaller), a stub X-Medewerker/X-Rollen header
path mirroring WP-53's citizen stub, and Authz.CanBeoordelen as the first
medewerker capability — backend-only, no consumer until WP-64. Also fixes
the backlog README's stale WP-61 status (done, but table said todo).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-31 23:47:43 +02:00
co-authored by Claude Sonnet 5
parent e4ea75414b
commit a09c4ed87b
21 changed files with 289 additions and 72 deletions
+16
View File
@@ -229,6 +229,22 @@ CallerIdentity.cs`):
instead of calling `ApplicationStore` directly — the last "reads a static store directly" gap
the ACL caveat below used to flag for a citizen-facing endpoint.
**WP-62 split `CallerIdentity` into the two actor kinds ADR-0002 §3 requires** — a
`ZorgverlenerCaller` (citizen, the WP-53 shape above) or a `MedewerkerCaller` (backoffice
employee: `MedewerkerId` + `Rollen`, no BSN), backend-only, unused by any frontend until WP-64.
`StubIdentityProvider` selects the medewerker kind when `X-Medewerker` is present (its value is
the medewerkerId; `X-Rollen` is a comma-separated rollen list, defaulting to `Behandelaar`) —
takes precedence over `X-Subject`; absent, every request today, falls through to the
zorgverlener path unchanged. `CallerIdentity.SubjectId` (BSN or medewerkerId) is what
`ZgwTokenProvider.Mint` now reads instead of `.Bsn` directly, so the ZGW JWT's `user_id` is
correct for either kind with no further change (WP-66's besluit write mints this for free). The
ownership-scoping seams (`ctx.Zorgverlener()`, `IDocumentSource.Upload`, `IZaakSource
.ListMyCases`) are narrowed to `ZorgverlenerCaller` — a medewerker hitting a citizen-scoped SSP
endpoint is a 500 today (unreachable, since no consumer sends `X-Medewerker` yet; WP-64 upgrades
it to a 403 once real backoffice traffic exists). `Authz.CanBeoordelen(CallerIdentity)` is the
first medewerker capability (rol-based, `MedewerkerRol.Behandelaar`), shipped only as a decision
flag, never a rollen matrix.
## The five ZGW APIs (context for later slices)
| API | Component | Used by |