Two backlog trees are complete: `docs/project/backlog/` (75 files, every WP done) and `docs/project/refactor-backlog-setup/` (the arc before it). Move both under `docs/project/archive/` with `git mv`, so history stays intact through `git log --follow`. `SHOWCASE-ROADMAP.md` moves with them, because it points at the now-archived backlog README. Add `docs/project/archive/README.md`. It states that these trees are historical and names the two directories that are still live. Repoint every inbound reference named in RD-30's Files table: CLAUDE.md, the root README, both backend READMEs, `LetterHtml.cs`, `a11y.mdx`, the `document-feature` and `new-ssp` skills, and the readable-codebase PLAN, README, and RD-19 ticket. Fix two upward-relative links inside the moved WP files (WP-68, WP-69) that gained a directory level and would otherwise break. Repoint `.prettierignore`'s two agent-prompt exclusions to their new path, so prettier keeps leaving those files' exact wording alone. Mark RD-30 done and check off its acceptance criteria; flip its README row to done. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3.7 KiB
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 SessionStores 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.