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>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user