docs(backlog): lift the HALT, record CD batch 1 as complete

The operator approved 99-backlog.md, so Phase 3 started. RB-01..RB-06 are
marked done in the table, _status.md gains a Phase 3 section tracking all six
batches, and the halt notice is replaced by what batch 1 leaves for later
batches to pick up:

- RB-01's residual is RB-09's problem — the document-content endpoint is
  reached by a plain browser navigation with no identity header, so it
  resolves to the seeded citizen and works only because one citizen owns
  every document in the POC. That is BIO-002.
- Pii.MaskTail now lives in Domain/People/Pii.cs; RB-11 should use it rather
  than hand-rolling a second masker.
- RB-06 additionally deleted SubmissionRules.RejectRegistratie, which its row
  did not ask for.

Also records the standing OpenZaakIntegrationTests failure, which needs a
live container and is unrelated to any of these tickets.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-08-27 11:06:10 +02:00
co-authored by Claude Opus 5
parent 0298ecc506
commit d682f91b54
2 changed files with 80 additions and 48 deletions
@@ -13,8 +13,24 @@
**47 findings in, 33 open tickets + 5 ADR-fixes + 1 shipped set out.** Everything below **47 findings in, 33 open tickets + 5 ADR-fixes + 1 shipped set out.** Everything below
traces to at least one `TE-`/`CQ-`/`ADR-C-`/`BIO-` finding and cites a baseline metric. traces to at least one `TE-`/`CQ-`/`ADR-C-`/`BIO-` finding and cites a baseline metric.
**HALT.** This file is the deliverable. No Implementation Agent starts until a human has **HALT lifted 2026-08-27** — the operator approved the backlog and Phase 3 started.
approved it. Nothing in this pass was implemented; no source file was modified. **CD batch 1 (RB-01..RB-06) is implemented**, one commit per ticket on branch
`refactor/adr-c-006-shared-route-guards`, each with a note in `implementation/rb-0N.md`.
Batches 2–6 are untouched. The `Status` column below is the source of truth.
Two batch-1 findings had knock-on effects a later ticket must not re-derive:
- **RB-01's residual is RB-09's problem.** Both callers of the document-content endpoint
reach it as a plain browser navigation (`<a href>` / `previewUrl`), carrying no identity
header and passing through no interceptor, so `StubIdentityProvider` answers with the
seeded citizen. The links keep working only because one citizen owns every document in
the POC. That is BIO-002; RB-09 needs this endpoint to receive a real credential.
- **RB-06 also deleted `SubmissionRules.RejectRegistratie`**, which the row did not ask for.
It was reachable only from the deleted endpoint and contradicted by the live submit path.
Recorded as the ticket's one judgement call in `implementation/rb-06.md`.
`Pii.MaskTail` now lives in `Domain/People/Pii.cs` (moved out of `Program.cs` by RB-03) —
**RB-11 and any later redaction work should use it rather than hand-rolling a second copy.**
--- ---
@@ -84,41 +100,41 @@ deployed first_, not _must ship together_.
Every ticket tracing to a `BIO-` finding, plus every row on agent 07's authoritative Every ticket tracing to a `BIO-` finding, plus every row on agent 07's authoritative
16-row "Compliance review required" list, carries it — regardless of priority. 16-row "Compliance review required" list, carries it — regardless of priority.
| ID | Module | Category | Description | Baseline metric improved | Effort | Risk | Priority | CD batch # | Depends on | Compliance | Status | | ID | Module | Category | Description | Baseline metric improved | Effort | Risk | Priority | CD batch # | Depends on | Compliance | Status |
| --------- | -------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------ | -------- | -------- | ---------- | ---------- | ------------ | ------ | | --------- | -------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------ | -------- | -------- | ---------- | ---------- | ------------ | -------- |
| **RB-01** | backend/Program.cs + Data | security | Add an owner/capability check to `GET /uploads/{id}/content` and `/uploads/status`; 404 not 403 | §3c Data 75.5% branch vs 99.0% line (BL-005) | S | Low | **P1** | 1 | — | **SIGN-OFF** | open | | **RB-01** | backend/Program.cs + Data | security | Add an owner/capability check to `GET /uploads/{id}/content` and `/uploads/status`; 404 not 403 | §3c Data 75.5% branch vs 99.0% line (BL-005) | S | Low | **P1** | 1 | — | **SIGN-OFF** | **done** |
| **RB-02** | backend/Program.cs + Data | privacy | Stop concatenating the BSN into `AuthzAudit.Resource`; assert on **values** in the test | §3c Data 75.5% branch (BL-005) | S | Low | **P1** | 1 | — | **SIGN-OFF** | open | | **RB-02** | backend/Program.cs + Data | privacy | Stop concatenating the BSN into `AuthzAudit.Resource`; assert on **values** in the test | §3c Data 75.5% branch (BL-005) | S | Low | **P1** | 1 | — | **SIGN-OFF** | **done** |
| **RB-03** | backend/Contracts | privacy | `MaskTail(a.Owner, 3)` in `ToAdminSummaryDto` — both cross-owner lists inherit it | §3a bhp/behandeling 91.6%/81.5%; §7 Mapping row | S | Low | **P1** | 1 | — | **SIGN-OFF** | open | | **RB-03** | backend/Contracts | privacy | `MaskTail(a.Owner, 3)` in `ToAdminSummaryDto` — both cross-owner lists inherit it | §3a bhp/behandeling 91.6%/81.5%; §7 Mapping row | S | Low | **P1** | 1 | — | **SIGN-OFF** | **done** |
| **RB-04** | backend/Data | privacy | Mask the BSN used as `AuditEntry.Actor` on document audit rows (ownership column untouched) | §3c Data 99.0% line / 75.5% branch | S | Low | **P1** | 1 | — | **SIGN-OFF** | open | | **RB-04** | backend/Data | privacy | Mask the BSN used as `AuditEntry.Actor` on document audit rows (ownership column untouched) | §3c Data 99.0% line / 75.5% branch | S | Low | **P1** | 1 | — | **SIGN-OFF** | **done** |
| **RB-05** | backend/Zgw | privacy | Drop the BSN-bearing query + body snippet from the `ZgwHttpClient` exception message | §3c Zgw 98.1%/85.5% (best backend branch) — a design gap, not a test gap | S | Low | **P1** | 1 | — | **SIGN-OFF** | open | | **RB-05** | backend/Zgw | privacy | Drop the BSN-bearing query + body snippet from the `ZgwHttpClient` exception message | §3c Zgw 98.1%/85.5% (best backend branch) — a design gap, not a test gap | S | Low | **P1** | 1 | — | **SIGN-OFF** | **done** |
| **RB-06** | backend/Program.cs | security | Delete the dead `POST /registrations` (no FE caller) — or add the `ForeignIds` guard | BL-003 (48 mappings in 940 lines, file CC 78) | S | Low | **P1** | 1 | — | **SIGN-OFF** | open | | **RB-06** | backend/Program.cs | security | Delete the dead `POST /registrations` (no FE caller) — or add the `ForeignIds` guard | BL-003 (48 mappings in 940 lines, file CC 78) | S | Low | **P1** | 1 | — | **SIGN-OFF** | **done** |
| **RB-07** | backend/Program.cs | audit | Audit the **allow** path in all five authz gates + the 3 brief transitions and the besluit | §3c Program.cs 84.8% branch; BL-003 | S–M | Med | **P1** | 2 | — | **SIGN-OFF** | open | | **RB-07** | backend/Program.cs | audit | Audit the **allow** path in all five authz gates + the 3 brief transitions and the besluit | §3c Program.cs 84.8% branch; BL-003 | S–M | Med | **P1** | 2 | — | **SIGN-OFF** | open |
| **RB-08** | backend/Program.cs | security | Route `DELETE /admin/uploads/{id}` through `CasesAdmin`; delete the orphaned `IsAdmin` gate | BL-003; §7 CQRS-light wrappers row | S | Low | **P1** | 2 | RB-07 | **SIGN-OFF** | open | | **RB-08** | backend/Program.cs | security | Route `DELETE /admin/uploads/{id}` through `CasesAdmin`; delete the orphaned `IsAdmin` gate | BL-003; §7 CQRS-light wrappers row | S | Low | **P1** | 2 | RB-07 | **SIGN-OFF** | open |
| **RB-09** | backend/Domain + Program.cs | security | `IIdentityProvider` can express "no identity"; stub Development-only; fail fast in Production | §7 "Single-impl interface `IIdentityProvider`"; BL-006 | S | Med | **P1** | 2 | — | **SIGN-OFF** | open | | **RB-09** | backend/Domain + Program.cs | security | `IIdentityProvider` can express "no identity"; stub Development-only; fail fast in Production | §7 "Single-impl interface `IIdentityProvider`"; BL-006 | S | Med | **P1** | 2 | — | **SIGN-OFF** | open |
| **RB-10** | ssp/auth + bhp/auth + ssp/shell | testability | Extract `parseStoredSession` (×2 apps) + spec `redactProfile`; assert a stored BSN yields `''` | §3a auth 42.9%/46.2% (worst FE line, §8); file LH 2/LF 20, BRH 3/BRF 13 | S | Low | **P1** | 2 | — | **SIGN-OFF** | open | | **RB-10** | ssp/auth + bhp/auth + ssp/shell | testability | Extract `parseStoredSession` (×2 apps) + spec `redactProfile`; assert a stored BSN yields `''` | §3a auth 42.9%/46.2% (worst FE line, §8); file LH 2/LF 20, BRH 3/BRF 13 | S | Low | **P1** | 2 | — | **SIGN-OFF** | open |
| **RB-11** | ssp/brief + libs/shared/infra | security | Dev hatches out of prod on the 3 hand-written `fetch` paths; export their parse boundaries; fix the doc | §3b ssp/brief 42% reach (11/26, none `ui/`); §3a 68.8% branch | M | Med | **P1** | 2 | — | **SIGN-OFF** | open | | **RB-11** | ssp/brief + libs/shared/infra | security | Dev hatches out of prod on the 3 hand-written `fetch` paths; export their parse boundaries; fix the doc | §3b ssp/brief 42% reach (11/26, none `ui/`); §3a 68.8% branch | M | Med | **P1** | 2 | — | **SIGN-OFF** | open |
| **RB-12** | backend/tests (CI) | security gate | One test enumerating the route table; every route hits an authz wrapper or an explicit allow-list | BL-006 (zero backend architecture enforcement) | M | Low | **P1** | 3 | — | **SIGN-OFF** | open | | **RB-12** | backend/tests (CI) | security gate | One test enumerating the route table; every route hits an authz wrapper or an explicit allow-list | BL-006 (zero backend architecture enforcement) | M | Low | **P1** | 3 | — | **SIGN-OFF** | open |
| **RB-13** | ssp/auth + bhp/auth | ADR execution | Land `Session → Principal`; `MedewerkerAdapter`; backoffice login stops being a DigiD/BSN form | BL-002 (211→151 dup after ADR-C-006; expected <40 after this) | M | Med | **P1** | 3 | RB-09 | **SIGN-OFF** | open | | **RB-13** | ssp/auth + bhp/auth | ADR execution | Land `Session → Principal`; `MedewerkerAdapter`; backoffice login stops being a DigiD/BSN form | BL-002 (211→151 dup after ADR-C-006; expected <40 after this) | M | Med | **P1** | 3 | RB-09 | **SIGN-OFF** | open |
| **RB-14** | repo (CI) | security gate | `dotnet list package --vulnerable --include-transitive` as a failing step | BL-006; §7 (the .NET tree is entirely unscanned today) | S | Low | P2 | 3 | — | **SIGN-OFF** | open | | **RB-14** | repo (CI) | security gate | `dotnet list package --vulnerable --include-transitive` as a failing step | BL-006; §7 (the .NET tree is entirely unscanned today) | S | Low | P2 | 3 | — | **SIGN-OFF** | open |
| **RB-15** | backend/Program.cs | security | Wrap Swagger + the OpenAPI document in `if (app.Environment.IsDevelopment())` | BL-003; §3c Program.cs 97.4%/84.8% | S | Low | P2 | 3 | — | **SIGN-OFF** | open | | **RB-15** | backend/Program.cs | security | Wrap Swagger + the OpenAPI document in `if (app.Environment.IsDevelopment())` | BL-003; §3c Program.cs 97.4%/84.8% | S | Low | P2 | 3 | — | **SIGN-OFF** | open |
| **RB-16** | backend/Stamdata | input valid. | `DateOnly.TryParse` on `?peildatum=` → 400 instead of an unhandled 500 | §3c Stamdata 96.8% line / **71.7% branch** (BL-005) | S | Low | P2 | 3 | — | **SIGN-OFF** | open | | **RB-16** | backend/Stamdata | input valid. | `DateOnly.TryParse` on `?peildatum=` → 400 instead of an unhandled 500 | §3c Stamdata 96.8% line / **71.7% branch** (BL-005) | S | Low | P2 | 3 | — | **SIGN-OFF** | open |
| **RB-17** | libs/shared/app + brief + beheer | CQRS-light | Split `runResult` (fold) from `runSubmit` (fold + idempotency mint); point the 5 reads at it | BL-007; §7 "read adapters 20 / mutations inline ~13" | S | Low | P2 | 3 | — | **SIGN-OFF** | open | | **RB-17** | libs/shared/app + brief + beheer | CQRS-light | Split `runResult` (fold) from `runSubmit` (fold + idempotency mint); point the 5 reads at it | BL-007; §7 "read adapters 20 / mutations inline ~13" | S | Low | P2 | 3 | — | **SIGN-OFF** | open |
| **RB-18** | backend/Data | security | Key `IdempotencyStore` on `{SubjectId}:{idemKey}` | §7 stores "Not behind any port"; agent 02's Data note (no TTL, no reset) | S | Low | P2 | 3 | RB-17 | **SIGN-OFF** | open | | **RB-18** | backend/Data | security | Key `IdempotencyStore` on `{SubjectId}:{idemKey}` | §7 stores "Not behind any port"; agent 02's Data note (no TTL, no reset) | S | Low | P2 | 3 | RB-17 | **SIGN-OFF** | open |
| **RB-19** | backend/Program.cs | structure | Reorder all 48 endpoints under read/write sub-banners; regroup admin-cases + org-template preview | BL-003 (940 lines, file CC 78 vs next-highest 27) | S | **High** | P2 | 4 | RB-12 | **SIGN-OFF** | open | | **RB-19** | backend/Program.cs | structure | Reorder all 48 endpoints under read/write sub-banners; regroup admin-cases + org-template preview | BL-003 (940 lines, file CC 78 vs next-highest 27) | S | **High** | P2 | 4 | RB-12 | **SIGN-OFF** | open |
| **RB-20** | ssp/registratie | CQRS-light | `ApplicationsStore.cancel` / `AdminCasesStore.delete` through `runSubmit`; surface the error | BL-007; §7 "Command factories 3" | S | Low | P2 | 4 | — | **SIGN-OFF** | open | | **RB-20** | ssp/registratie | CQRS-light | `ApplicationsStore.cancel` / `AdminCasesStore.delete` through `runSubmit`; surface the error | BL-007; §7 "Command factories 3" | S | Low | P2 | 4 | — | **SIGN-OFF** | open |
| **RB-21** | ssp/registratie | CQRS-light | Extract the read half of `createDraftSync` into `application/find-concept.ts` | §4a `createDraftSync` 143 lines — longest fn in the repo; §9 (>40) | M | Med | P2 | 4 | — | — | open | | **RB-21** | ssp/registratie | CQRS-light | Extract the read half of `createDraftSync` into `application/find-concept.ts` | §4a `createDraftSync` 143 lines — longest fn in the repo; §9 (>40) | M | Med | P2 | 4 | — | — | open |
| **RB-22** | ssp/brief | CQRS-light | _(expand)_ `BriefStore.load()` tolerates a 404 by calling the existing `reset()` once | BL-003; §7 Backend CQRS-light row | S | Low | P2 | 4 | — | **SIGN-OFF** | open | | **RB-22** | ssp/brief | CQRS-light | _(expand)_ `BriefStore.load()` tolerates a 404 by calling the existing `reset()` once | BL-003; §7 Backend CQRS-light row | S | Low | P2 | 4 | — | **SIGN-OFF** | open |
| **RB-23** | backend/Program.cs + Data | CQRS-light | _(contract)_ `GET /brief` 404s when absent; `GetOrCreate` → `Get` | BL-003; §7 Backend CQRS-light row | S | Med | P2 | 4 | RB-22 | **SIGN-OFF** | open | | **RB-23** | backend/Program.cs + Data | CQRS-light | _(contract)_ `GET /brief` 404s when absent; `GetOrCreate` → `Get` | BL-003; §7 Backend CQRS-light row | S | Med | P2 | 4 | RB-22 | **SIGN-OFF** | open |
| **RB-24** | libs/shared/upload | ADR conform. | Move `upload/` into `infrastructure`/`domain`/`application`; **delete** the depcruise carve-out | BL-010; §7 "+1 adapter outside `infrastructure/`", "8 of 9 machines in `domain/`"; §3b shared/domain 0% reach | M | Med | P2 | 5 | — | **SIGN-OFF** | open | | **RB-24** | libs/shared/upload | ADR conform. | Move `upload/` into `infrastructure`/`domain`/`application`; **delete** the depcruise carve-out | BL-010; §7 "+1 adapter outside `infrastructure/`", "8 of 9 machines in `domain/`"; §3b shared/domain 0% reach | M | Med | P2 | 5 | — | **SIGN-OFF** | open |
| **RB-25** | libs/shared/upload | testability | `UPLOAD_TRANSPORT` injection token (the `SESSION_PORT` shape) instead of `inject(KeepaliveTransport)` | §3a upload 52.0%/50.0%; §3b file unreached, non-`ui/` | S | Low | P2 | 5 | RB-24 | **SIGN-OFF** | open | | **RB-25** | libs/shared/upload | testability | `UPLOAD_TRANSPORT` injection token (the `SESSION_PORT` shape) instead of `inject(KeepaliveTransport)` | §3a upload 52.0%/50.0%; §3b file unreached, non-`ui/` | S | Low | P2 | 5 | RB-24 | **SIGN-OFF** | open |
| **RB-26** | libs/shared/upload | testability | Move the accept/reject decision to `planFileSelection` in `upload.machine.ts` | §3a upload 52.0%/50.0%; §4a module max CC 27 | S | Low | P2 | 5 | RB-24 | **SIGN-OFF** | open | | **RB-26** | libs/shared/upload | testability | Move the accept/reject decision to `planFileSelection` in `upload.machine.ts` | §3a upload 52.0%/50.0%; §4a module max CC 27 | S | Low | P2 | 5 | RB-24 | **SIGN-OFF** | open |
| **RB-27** | libs/shared/upload | testability | Extract `uploadOutcome(status, responseText)` out of the XHR closure | file LH 5/64 (**7.8% line**), BRH 3/57 (**5.3% branch**) | S–M | Low | P2 | 5 | RB-25 | **SIGN-OFF** | open | | **RB-27** | libs/shared/upload | testability | Extract `uploadOutcome(status, responseText)` out of the XHR closure | file LH 5/64 (**7.8% line**), BRH 3/57 (**5.3% branch**) | S–M | Low | P2 | 5 | RB-25 | **SIGN-OFF** | open |
| **RB-28** | libs/beheer + ssp/brief | testability | `BLOB_PRESENTER` token; the 3 commands' success paths become assertable | §3a beheer/application **40.5% branch — worst FE**; brief.store BRH 32/64 | S–M | Low | P2 | 5 | — | **SIGN-OFF** | open | | **RB-28** | libs/beheer + ssp/brief | testability | `BLOB_PRESENTER` token; the 3 commands' success paths become assertable | §3a beheer/application **40.5% branch — worst FE**; brief.store BRH 32/64 | S–M | Low | P2 | 5 | — | **SIGN-OFF** | open |
| **RB-29** | backend/Domain | testability | Thread the existing `at` through `LetterHtml.ResolveAuto` instead of reading `UtcNow` | §3c Domain 82.0% branch; §4b `LetterHtml.cs` CC 21 | S | Low | P2 | 5 | — | — | open | | **RB-29** | backend/Domain | testability | Thread the existing `at` through `LetterHtml.ResolveAuto` instead of reading `UtcNow` | §3c Domain 82.0% branch; §4b `LetterHtml.cs` CC 21 | S | Low | P2 | 5 | — | — | open |
| **RB-30** | backend/Data + Domain | testability | Extract 5 brief guards into `Domain/Letters/BriefRules.cs`; add `tests/Domain/BriefRuleTests.cs` | §3c Data **75.5% branch** (BL-005); §4b `BriefStore.cs` CC 17, `ToDto` CC 16 | M | Med | P2 | 5 | — | **SIGN-OFF** | open | | **RB-30** | backend/Data + Domain | testability | Extract 5 brief guards into `Domain/Letters/BriefRules.cs`; add `tests/Domain/BriefRuleTests.cs` | §3c Data **75.5% branch** (BL-005); §4b `BriefStore.cs` CC 17, `ToDto` CC 16 | M | Med | P2 | 5 | — | **SIGN-OFF** | open |
| **RB-31** | 4 app contexts (specs only) | ADR conform. | Replace hand-rolled state literals with `given(reduce, initial)` replays in 4 machine specs | §7 Elm machines 9 (1 has a `*.testing.ts`); §3a herreg 67.8% / brief 68.8% branch | M | Low | P2 | 6 | — | — | open | | **RB-31** | 4 app contexts (specs only) | ADR conform. | Replace hand-rolled state literals with `given(reduce, initial)` replays in 4 machine specs | §7 Elm machines 9 (1 has a `*.testing.ts`); §3a herreg 67.8% / brief 68.8% branch | M | Low | P2 | 6 | — | — | open |
| **RB-32** | libs/shared/docs | ADR conform. | Add the missing `language-switcher` row to the CIBG gap register (9 markers vs 8 rows) | §2 libs/shared 86 files / 5 194 lines; §6 layout Ca 22 | S | Low | P3 | 6 | — | — | open | | **RB-32** | libs/shared/docs | ADR conform. | Add the missing `language-switcher` row to the CIBG gap register (9 markers vs 8 rows) | §2 libs/shared 86 files / 5 194 lines; §6 layout Ca 22 | S | Low | P3 | 6 | — | — | open |
| **RB-33** | libs/shared/testing | ADR conform. | Adopt `unwrapOk` at its one call site — **or delete it**; both satisfy ADR-0006 §3 | BL-004; §3a libs/shared/testing 3 files, 100% line | S | Low | P3 | 6 | — | — | open | | **RB-33** | libs/shared/testing | ADR conform. | Adopt `unwrapOk` at its one call site — **or delete it**; both satisfy ADR-0006 §3 | BL-004; §3a libs/shared/testing 3 files, 100% line | S | Low | P3 | 6 | — | — | open |
--- ---
@@ -1,13 +1,29 @@
# Agent run status # Agent run status
| Agent | Status | Last module processed | Last updated | Notes | | Agent | Status | Last module processed | Last updated | Notes |
| --------------- | -------------------------- | ----------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --------------- | ------------------- | ----------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| baseline | complete | all (18 FE + 7 BE modules) | 2026-08-26 | 0 layering violations. 11 observations BL-001..BL-011. Thresholds for Phase 1 in §9 — agent 01's `[N] lines` = 40 (TS fn) / 60 (C# method) / 400 (file). Read BL-001, BL-002 and BL-004 before filing complexity, duplication or coverage findings. | | baseline | complete | all (18 FE + 7 BE modules) | 2026-08-26 | 0 layering violations. 11 observations BL-001..BL-011. Thresholds for Phase 1 in §9 — agent 01's `[N] lines` = 40 (TS fn) / 60 (C# method) / 400 (file). Read BL-001, BL-002 and BL-004 before filing complexity, duplication or coverage findings. |
| readability | skipped | n/a | 2026-08-27 | **skipped** — deliberate. BL-001: 23 of the 25 TS functions over CC 10 are reducers / `parse*` boundaries / `validate*`, all mandated house idioms; TS fn-length p99 is 34 with only 2 functions over 75 lines. Little left for this agent to find that is not a false positive. Revisit if the CC>10 population grows outside those three shapes. | | readability | skipped | n/a | 2026-08-27 | **skipped** — deliberate. BL-001: 23 of the 25 TS functions over CC 10 are reducers / `parse*` boundaries / `validate*`, all mandated house idioms; TS fn-length p99 is 34 with only 2 functions over 75 lines. Little left for this agent to find that is not a false positive. Revisit if the CC>10 population grows outside those three shapes. |
| testability | complete | all 24 modules | 2026-08-26 | 9 findings TE-001..TE-009; 15 modules explicit "no findings". Corrected BL-004 — `libs/shared/domain` and `libs/beheer/contracts` are pure type declarations, 0% is unimprovable (amendment note in 00-baseline.md §10). TE-009 is also a latent correctness bug (dead `ActiveOn` branches). Acquitted `createDraftSync`, `httpClientFetch`, `Contracts/Mappers.cs` in writing. | | testability | complete | all 24 modules | 2026-08-26 | 9 findings TE-001..TE-009; 15 modules explicit "no findings". Corrected BL-004 — `libs/shared/domain` and `libs/beheer/contracts` are pure type declarations, 0% is unimprovable (amendment note in 00-baseline.md §10). TE-009 is also a latent correctness bug (dead `ActiveOn` branches). Acquitted `createDraftSync`, `httpClientFetch`, `Contracts/Mappers.cs` in writing. |
| ddd-hexagonal | skipped | n/a | 2026-08-27 | **skipped** — deliberate. FE layering is clean (baseline §6: 0 violations, healthy instability gradient, `kernel` I=5% vs contexts I>=83%); backend `Domain/` is verified EF/ASP-free. The agent may only _extend_ existing hexagonal structure, and the one real target (`Program.cs`) has no `Features/` folder to extend — agent 04 already filed that as out-of-mandate OOM-A. | | ddd-hexagonal | skipped | n/a | 2026-08-27 | **skipped** — deliberate. FE layering is clean (baseline §6: 0 violations, healthy instability gradient, `kernel` I=5% vs contexts I>=83%); backend `Domain/` is verified EF/ASP-free. The agent may only _extend_ existing hexagonal structure, and the one real target (`Program.cs`) has no `Features/` folder to extend — agent 04 already filed that as out-of-mandate OOM-A. |
| cqrs-light | complete | all (16 FE + 6 BE modules) | 2026-08-26 | 7 findings CQ-001..CQ-007; 12 modules clean. Corrected BL-007 (see the amendment note in 00-baseline.md §10) and found 3 mutations the baseline missed. `Program.cs` → `Features/`+handlers filed as out-of-mandate OOM-A, not a ticket; CQ-006 is its prerequisite. `bhp/behandeling` named the reference implementation — do not "clean it up". | | cqrs-light | complete | all (16 FE + 6 BE modules) | 2026-08-26 | 7 findings CQ-001..CQ-007; 12 modules clean. Corrected BL-007 (see the amendment note in 00-baseline.md §10) and found 3 mutations the baseline missed. `Program.cs` → `Features/`+handlers filed as out-of-mandate OOM-A, not a ticket; CQ-006 is its prerequisite. `bhp/behandeling` named the reference implementation — do not "clean it up". |
| bdd | skipped | n/a | 2026-08-27 | **skipped** — deliberate. No BDD tooling present, and the prompt forbids proposing any; it self-reduces to a single structural note. `gen:behaviour-spec` already extracts behaviours from spec names into `libs/shared/docs/behaviour-spec.mdx`, which covers the intent. | | bdd | skipped | n/a | 2026-08-27 | **skipped** — deliberate. No BDD tooling present, and the prompt forbids proposing any; it self-reduces to a single structural note. `gen:behaviour-spec` already extracts behaviours from spec names into `libs/shared/docs/behaviour-spec.mdx`, which covers the intent. |
| adr-conformance | complete | all 6 ADRs | 2026-08-26 | 11 findings: 6 code, **5 ADR-fix (architect approval required)**. Sharpened BL-002 — `Principal` was never built, so ADR-0002 was untested not falsified (amendment note in 00-baseline.md §10). ADR-0005 fully conformed. Gates: ADR-C-005→ADR-C-004; ADR-C-003 gates contracts/ cleanup. 3 ADR-fixes need a matching CLAUDE.md correction in the same diff. | | adr-conformance | complete | all 6 ADRs | 2026-08-26 | 11 findings: 6 code, **5 ADR-fix (architect approval required)**. Sharpened BL-002 — `Principal` was never built, so ADR-0002 was untested not falsified (amendment note in 00-baseline.md §10). ADR-0005 fully conformed. Gates: ADR-C-005→ADR-C-004; ADR-C-003 gates contracts/ cleanup. 3 ADR-fixes need a matching CLAUDE.md correction in the same diff. |
| bio2-compliance | complete | all modules + 7 control areas | 2026-08-27 | 20 findings BIO-001..BIO-020 (12 **defect now**, 8 **production gate**). High: BIO-008 BSN concatenated into the authz audit `Resource` (`Program.cs:674`, verified); BIO-004 `GET /uploads/{documentId}/content` has no authz at all (verified). Answered agent 06's handoff as BIO-002 — a production behandelportal build resolves to the seeded **zorgverlener**, failing closed on backoffice caps but open on citizen-scoped ones incl. `CanRevealBigNummer`. Carries the mandatory **"compliance review required"** list: 16 rows over agents 02/04/06. Also a pre-production checklist (~25 boxes). | | bio2-compliance | complete | all modules + 7 control areas | 2026-08-27 | 20 findings BIO-001..BIO-020 (12 **defect now**, 8 **production gate**). High: BIO-008 BSN concatenated into the authz audit `Resource` (`Program.cs:674`, verified); BIO-004 `GET /uploads/{documentId}/content` has no authz at all (verified). Answered agent 06's handoff as BIO-002 — a production behandelportal build resolves to the seeded **zorgverlener**, failing closed on backoffice caps but open on citizen-scoped ones incl. `CanRevealBigNummer`. Carries the mandatory **"compliance review required"** list: 16 rows over agents 02/04/06. Also a pre-production checklist (~25 boxes). |
| consolidation | halted (awaiting approval) | all inputs | 2026-08-27 | **HALTED for human approval** (per spec) — `99-backlog.md` written, nothing implemented. 33 open tickets RB-01..RB-33 + 5 ADR-fixes + 5 already-shipped, from 47 findings. RB-01 (no authz on upload content) and RB-02 (BSN in the audit `Resource`) sort above all structural work. Gate relaxed to the 4 agents that ran; a "Coverage of this backlog" note records what the 3 skips leave unowned. Caught two orchestrator errors: **CQ-002 is NOT fixed** (verified — `ApplicationsStore.cancel`/`AdminCasesStore.delete` still swallow errors → RB-20), and **CQ-004 shipped with half its compliance criterion unmet** (no audit row on `PUT /admin/flags/{key}`, verified → RB-07, which blocks signing ADR-C-009). OOM-D: re-run the baseline before using it to verify any ticket — ADR-C-006 and BL-008 moved it. | | consolidation | complete (approved) | all inputs | 2026-08-27 | **HALTED for human approval** (per spec) — `99-backlog.md` written, nothing implemented. 33 open tickets RB-01..RB-33 + 5 ADR-fixes + 5 already-shipped, from 47 findings. RB-01 (no authz on upload content) and RB-02 (BSN in the audit `Resource`) sort above all structural work. Gate relaxed to the 4 agents that ran; a "Coverage of this backlog" note records what the 3 skips leave unowned. Caught two orchestrator errors: **CQ-002 is NOT fixed** (verified — `ApplicationsStore.cancel`/`AdminCasesStore.delete` still swallow errors → RB-20), and **CQ-004 shipped with half its compliance criterion unmet** (no audit row on `PUT /admin/flags/{key}`, verified → RB-07, which blocks signing ADR-C-009). OOM-D: re-run the baseline before using it to verify any ticket — ADR-C-006 and BL-008 moved it. **Approved 2026-08-27; HALT lifted.** |
## Phase 3 — implementation
| CD batch | Tickets | Status | Notes |
| -------- | ---------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 1 | RB-01, RB-02, RB-03, RB-04, RB-05, RB-06 | **complete** | Six commits on `refactor/adr-c-006-shared-route-guards`, one per ticket, each with `implementation/rb-0N.md`. `npm run ci` green. Every ticket left a test that was verified red without its fix. Carryover: RB-01's residual belongs to **RB-09** (the content endpoint is reached by a plain browser navigation with no identity header — BIO-002); `Pii.MaskTail` now lives in `Domain/People/Pii.cs`, **use it in RB-11** rather than hand-rolling a second masker; RB-06 additionally deleted `SubmissionRules.RejectRegistratie` (judgement call, recorded). |
| 2 | RB-07, RB-08, RB-09, RB-10, RB-11 | not started | RB-08 depends on RB-07. RB-07 gates signing ADR-C-009. |
| 3 | RB-12, RB-13, RB-14, RB-15, RB-16, RB-17 | not started | RB-13 depends on RB-09. |
| 4 | RB-18..RB-23 | not started | RB-19 is the only **High**-risk ticket; it needs RB-12's route-table test first. |
| 5 | RB-24..RB-30 | not started | RB-25/26/27 all depend on RB-24. |
| 6 | RB-31, RB-32, RB-33 | not started | |
**Standing caveat for every batch:** `dotnet test` reports one failure,
`OpenZaakIntegrationTests.Admin_cases_returns_the_seeded_zaak_mapped_through_real_HTTP_and_JWT`,
which needs a live OpenZaak container. It fails identically on a stashed tree — it is not
caused by any of these tickets. `npm run ci` does not run it.