Files
atomic-design-poc/docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-001.md
T
ehoandClaude Opus 5 25a5d415a5 docs(adr): land ADR-C-001, ADR-C-003, ADR-C-007 and ADR-C-009
The architect approved the four ADR-fix tickets. All four change what the
architecture documents claim. No code changes.

ADR-0001, ADR-C-001: the worked example claimed the POC has no real backend.
It rewrites against `backend/src/BigRegister.Api`. Every path it named is
repointed. The out-of-scope list drops two discharged bullets: 33 `parse*`
boundaries exist, and `npm run gen:api` is real.

ADR-0001, ADR-C-003: a new section states that the generated client is the wire
contract. A hand-written `contracts/*.dto.ts` is the exception for two cases
only. The four survivors stay, because NSwag emits every property as optional
and flattens `RegistrationStatusDto` into five optional strings. The `parse*`
trust boundary stays mandatory, because a generated type is a compile-time
claim about the wire and not a runtime guarantee.

ADR-0003, ADR-C-007: four paths moved in WP-67 and are repointed. Point 4 kept
the principle and changed its example to `skeleton` and `spinner`. Two of its
claims were false and the amendment says so: `app-alert` wraps the vendored
`.feedback` classes, and `site-header` composes the vendored `.titlebar`.

ADR-0004, ADR-C-009: the exception section states a four-part test instead of
one named exception. `OrgTemplateStore` and `FeatureFlagStore` both pass it. RB-07
gated this ticket, because clause 4 needs an audited allow path. RB-07 landed
that, so the ADR does not ratify a control that the code lacks.

Three tickets need a matching CLAUDE.md correction in the same diff. CLAUDE.md
section 2 loses the false `alert` example. Section 4 gets the generated-client
rule and the four-part test.

Two findings were wrong. ADR-C-001 asked to keep an out-of-scope bullet that
reads "SessionStore is in-memory". The session persists to `localStorage` now,
so the bullet covers multi-tab sync only. ADR-C-007 flagged one half of point 4
and missed that the other half is equally false.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 18:29:05 +02:00

4.9 KiB

ADR-C-001 — rewrite ADR-0001's worked example against the shipped system

Status: implemented · 2026-08-27 · Source finding: 06-adr-conformance.md §ADR-C-001

What was wrong

ADR-0001's §"Worked example in this POC" opened with "This POC has no real backend (static mock JSON + fake submit timers), so the 'BFF output' is a static file". That premise is false and every path the section cited was gone. The decision itself was intact; only the description had drifted.

What changed

File Change
docs/reference/architecture/0001-...md §Worked example rewritten against backend/src/BigRegister.Api; all six paths repointed
same file, §Out of scope here 4 bullets → 2, plus a paragraph recording which two were discharged and why

No code changed. No CLAUDE.md edit was required for this finding.

Paths corrected, each verified

Claimed Actual
"no real backend … static file" backend/src/BigRegister.Api, var api = app.MapGroup("/api/v1") at Program.cs:168
public/mock/dashboard-view.json GET /api/v1/dashboard-view (Program.cs:172)
public/mock/intake-policy.json GET /api/v1/intake/policy (Program.cs:193)
src/app/registratie/contracts/dashboard-view.dto.ts apps/ssp/src/app/registratie/contracts/dashboard-view.dto.ts
src/app/registratie/infrastructure/dashboard-view.adapter.ts apps/ssp/.../infrastructure/dashboard-view.adapter.ts, parseDashboardView at :50
src/app/herregistratie/contracts/intake-policy.dto.ts deleted — the DTO is now the generated IntakePolicyDto; the adapter is apps/ssp/src/app/herregistratie/infrastructure/intake-policy.adapter.ts

apps/ssp/public/mock/ does not exist (ls: no such directory).

The finding was wrong about one out-of-scope bullet

ADR-C-001 said to "reduce §Out of scope to the two items still genuinely open (the BigProfileStore optimistic-update race, and session persistence / multi-tab sync)", carrying the original bullet's parenthetical "SessionStore is in-memory". That parenthetical is no longer true, so the bullet could not be kept verbatim.

  • apps/ssp/src/app/auth/application/session.store.ts:13 reads parseStoredPrincipal(localStorage.getItem(STORAGE_KEY)), and :41 writes it back. Session persistence has landed (RB-10 extracted the parser, RB-13 renamed it parseStoredPrincipal). The file even carries a ponytail: note explaining the choice of localStorage over sessionStorage.
  • Multi-tab sync has not landed: grep for a storage event listener across apps and libs returns nothing.

The bullet was therefore narrowed to multi-tab sync only, and states that the session itself now persists. Recording this because the finding, taken literally, would have re-asserted a false claim in the same edit that removed two others.

The other two survivors were verified rather than assumed: BigProfileStore still holds pending as a bare signal(false) with begin/confirm/rollback mutating it (big-profile.store.ts:61-74), so the concurrent-submit race is real.

Discharged bullets, both verified

  • "Runtime DTO validation on every endpoint (only the dashboard view has it)" — 33 distinct export function parse* boundary functions exist across apps and libs.
  • "Real OpenAPI/TypeSpec codegen toolchain"npm run gen:api (package.json:12) runs dotnet swagger tofile then nswag run, emitting libs/shared/src/infrastructure/api-client.ts (2329 lines). CI's api-client-drift job regenerates and runs git diff --exit-code (.github/workflows/ci.yml:319-321).

Scope discipline

Descriptive drift only, as the finding states. The decision, the options table, the two policy shapes and the migration sequence are untouched.