docs: refactoring-backlog workspace — baseline + 3 Phase 1 agents

Runs the multi-agent refactoring-backlog pipeline in docs/project/
refactor-backlog-setup/ up to and including three of the seven Phase 1
agents.

00-baseline.md establishes the metrics every later agent must cite, using
only tooling already in the repo (vitest lcov, coverlet cobertura, ESLint's
core `complexity` rule at threshold 0 for a full distribution, depcruise
--metrics). Duplication and C# complexity had no tooling, so
tools/baseline-scan.mjs adds a deterministic ~200-line text scan rather
than a new dependency; the approximations are labelled as such.

Headline: FE 75.1% line coverage but only over the 98 of 220 source files a
spec loads; BE 97.6% line / 79.6% branch; 0 layering violations; 7.1%
duplication; 25 of 2085 TS functions over CC 10.

Then 02-testability, 04-cqrs-light and 06-adr-conformance (27 findings).
01/03/05 were skipped deliberately — the baseline shows little for them to
find; 07 (BIO2) and 08 (consolidation) are still open.

Each agent corrected a baseline observation of mine, and in every case the
error was in something derived rather than measured:

- BL-007 counted ~13 adapter "mutations" from the `runSubmit` helper name;
  5 of those call sites are reads. It also missed 3 real mutations that
  reach the raw ApiClient and never return a Result.
- BL-002 diagnosed the 100%-duplicated auth folders as ADR-0002's
  divergence prediction failing. It never had a chance to fail: §3's
  `Principal` union was never built.
- BL-004 named libs/shared/domain and libs/beheer/contracts as coverage
  gaps; both are pure type declarations where 0% is unimprovable.

All three corrections are recorded inline in 00-baseline.md §10, so agent
08 does not inherit the bad numbers.

.prettierignore excludes the agent prompt directories — reflowing their
markdown would edit the prompt text itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-08-26 16:44:32 +02:00
co-authored by Claude Opus 5
parent 0ad02e651a
commit 664a43bf2d
36 changed files with 3488 additions and 0 deletions
@@ -0,0 +1,58 @@
# ADR-C-006 — extract the actor-agnostic route guards to `libs/shared`
Status: **implemented** · 2026-08-26 · Source finding: `06-adr-conformance.md` §ADR-C-006
## What changed
| File | Change |
| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `libs/shared/src/application/auth.guard.ts` | **new**`authGuard` + `capabilityGuard`, injecting `SESSION_PORT` instead of an app-local `SessionStore` |
| `libs/shared/src/application/auth.guard.spec.ts` | **new** — the single spec, provides `SESSION_PORT`; one case added asserting the guard reads the port |
| `libs/shared/src/application/session.port.ts` | widened by one member: `readonly isAuthenticated: Signal<boolean>` |
| `apps/ssp/src/app/auth/auth.guard.ts` | now a re-export |
| `apps/behandelportal/src/app/auth/auth.guard.ts` | now a re-export |
| `apps/{ssp,behandelportal}/src/app/auth/auth.guard.spec.ts` | **deleted** — both were byte-identical to the new shared spec |
Neither `app.routes.ts` was touched: both still `import { authGuard, capabilityGuard }
from '@auth/auth.guard'`. Routing asks the auth context for its guards, which is the
direction the boundary should read.
## Why the port widening was free
Both `SessionStore`s already exposed `readonly isAuthenticated = computed(() =>
this._session() !== null)` (`session.store.ts:40` in each app), and both apps already
registered `{ provide: SESSION_PORT, useExisting: SessionStore }`
(`app.config.ts:64` / `:65`). `SessionPort` is satisfied structurally, so adding the
member required no change in either app — the seam existed, it was just narrower than
what it already carried.
## Scope discipline
Only the guards moved. Per the finding, **no** ticket to merge `session.store.ts`,
`session.ts`, `digid.adapter.ts`, `login-form.component.ts` or `login.page.ts`, and no
relaxation of ADR-0002 §3. Those five are identical because ADR-C-004 (`Session →
Principal`) was never executed; merging them would cement a citizen DigiD/BSN login as
the backoffice's shared login, which is the outcome §3 exists to prevent.
## Measured effect
Re-ran `tools/baseline-scan.mjs --dup` after the change:
| Metric | Before | After |
| --------------------------- | -----: | --------: |
| `ssp/auth` duplicated lines | 211 | **151** |
| `bhp/auth` duplicated % | 86.8% | **82.5%** |
| Repo-wide duplication | 7.1% | **6.6%** |
The `auth.guard.spec.ts` (36 windows) and `auth.guard.ts` (21 windows) clone pairs have
dropped out of the top-clones list entirely. The remaining `ssp/auth``bhp/auth`
duplication is `session.store.ts` (39), `login-form.component.ts` (35) and `login.page.ts`
(23) — exactly the three ADR-C-004 is expected to differentiate. Re-measure BL-002 after
that lands; the finding's expectation is a drop to under 40 lines.
## Verification
`npm run lint` · `npm run typecheck` · `npm run dep:check` (0 violations, 224 modules)
· `npx prettier --check apps libs` — all clean.
Tests: shared 122, ssp 235, behandelportal 27, beheer 23 — **407 passed, 0 failed**.
`ng build --localize` for both apps.