From d31e054504e07f4e10ed9d86cbb443ed664109fe Mon Sep 17 00:00:00 2001 From: Edwin van den Houdt Date: Tue, 8 Sep 2026 23:11:03 +0200 Subject: [PATCH] docs: cite symbols, not lines, in ARCHITECTURE 6a (RD-31) Section 6a cited line numbers and two paths from before the monorepo split (WP-67). A line number goes stale on the next edit; a symbol survives it. Replace every L citation in the section with the named symbol, fix the two dead paths (environment.ts now lives under libs/shared, proxy.conf.json is now one file per app), and point the read walkthrough at mijn-registratie.section.ts, where the RD-03 split moved the dashboard's block. Mark RD-31 done and update its README row. Co-Authored-By: Claude Opus 5 --- .../RD-31-architecture-6a.md | 93 +++++++++++++++++++ docs/project/readable-codebase/README.md | 2 +- docs/reference/architecture/ARCHITECTURE.md | 25 +++-- 3 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 docs/project/readable-codebase/RD-31-architecture-6a.md diff --git a/docs/project/readable-codebase/RD-31-architecture-6a.md b/docs/project/readable-codebase/RD-31-architecture-6a.md new file mode 100644 index 0000000..9846c8f --- /dev/null +++ b/docs/project/readable-codebase/RD-31-architecture-6a.md @@ -0,0 +1,93 @@ +# RD-31 — `ARCHITECTURE.md` §6a cites lines that moved + +Status: done +Phase: 5 — fix the docs that describe this flow + +## Why + +Section 6a, "The request lifecycle today" +(`docs/reference/architecture/ARCHITECTURE.md:564`), is the best onboarding artifact in the +repo. It walks one read and one write from the template to the backend and back. It has rotted. + +A line citation is only true until the next commit. Two of the cited paths belong to the tree +from before the monorepo (WP-67). A reader who follows them meets a comment about ZGW client +timeouts and two files that do not exist. That is worse than no citation, because the reader +does not know which half to trust. + +## Read first + +- `docs/project/readable-codebase/PLAN.md`, phase 5 item 2 (line 822). +- `docs/reference/architecture/ARCHITECTURE.md:564-608` — the whole section. + +## Decisions (pre-made, do not relitigate) + +1. **Cite symbols, not lines.** Write "`Program.cs`, `api.MapGet("/dashboard-view")`", never + "`Program.cs` L80". A symbol survives an edit above it; a line number does not. Apply this + to all 15 citations in the section, including the ones that happen to be correct today. +2. **Keep the Markdown links to the files.** The link tells the reader where to look; the + symbol tells them what to look for. Both, not one. +3. **Keep the `RemoteData` statement.** `PLAN.md` withdrew the claim that it is + wrong. `DashboardView` is a pair of `BigProfile` and `HerregistratieDecisions`, not a second + name for either. Do not collapse it. +4. **Do not rewrite the section.** It is accurate in structure and good prose. This ticket + corrects addresses, not the argument. + +## The facts, measured against the current tree + +| The section says | The tree says | +| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `src/environments/environment.ts` | `libs/shared/src/environments/environment.ts` (plus `environment.prod.ts`) | +| `proxy.conf.json` | `apps/ssp/proxy.conf.json`, and `apps/behandelportal/proxy.conf.json` | +| `Program.cs` `/dashboard-view` L80 | L80 is `builder.Services.AddSingleton(zgw)`. The endpoint is `api.MapGet("/dashboard-view")`, L172 today | +| `Program.cs` `/change-requests` L120 | L120 is the correlation-id middleware. The endpoint is `api.MapPost("/change-requests")`, L238 today | +| `app.config.ts` L37 | L37 is inside a view-transition comment. `provideApiClient()` is L63 today | +| `api-client.provider.ts` L47-82, L86-92 | Correct today (`httpClientFetch` L47, `provideApiClient` L86). Cite the symbols anyway | +| the read starts at the dashboard page | `` now lives in `mijn-registratie.section.ts:25`, after the RD-03 split. `wat-moet-ik-regelen.section.ts:24` reads the same store | + +The proxy bullet also needs one addition: each app now carries its own `proxy.conf.json`, and +both point at `http://localhost:5000`. + +## Files + +- `docs/reference/architecture/ARCHITECTURE.md` — section 6a only. + +Check the rest of the document for the same two dead paths before you stop: + +```bash +grep -rn "src/environments\|proxy.conf.json\|L[0-9][0-9]" docs/reference/architecture/ +``` + +## Steps + +1. Fix the two dead paths. +2. Replace every `L` citation in §6a with a symbol. +3. Correct the read walkthrough's entry point to the section component. +4. Run the grep above. Fix any hit outside §6a that is wrong for the same reason. +5. `npm run ci`. + +## Acceptance criteria + +- [x] No `L` citation remains in §6a. +- [x] Every path in §6a resolves. Verify by following each link. +- [x] The read walkthrough names `mijn-registratie.section.ts`. +- [x] The `RemoteData` statement is unchanged. +- [x] `npm run ci` is green. + +## Verification + +1. `npm run ci` — the format check covers the file. +2. For each Markdown link in §6a, run `ls `. Every one must exist. +3. For each symbol cited, `grep -n "" `. Every one must return a hit. + +## Out of scope + +- Sections 1 to 6 and section 7. RD-32 and RD-33 own the other documents. +- The `backend/README.md` and the ADRs. + +## Risks + +1. **A symbol that is not unique.** `runSubmit` and `toDomain` appear in more than one file. + Cite the file with the symbol, never the symbol alone. +2. **Line citations elsewhere in the document.** The grep in Files finds them. Fix only the + ones that are wrong; a correct citation outside §6a is not this ticket's work, but a wrong + one that you leave behind makes the ticket a half measure. diff --git a/docs/project/readable-codebase/README.md b/docs/project/readable-codebase/README.md index 5492a90..1889897 100644 --- a/docs/project/readable-codebase/README.md +++ b/docs/project/readable-codebase/README.md @@ -125,7 +125,7 @@ two. Note that RD-15 exists because 22 abandoned agent worktrees are still on di | RD-28 | Layer-tag fixes + the `libs/beheer` title rule | 27 | yes | done | | RD-29 | The 3 atomic-ladder rules in dependency-cruiser | 27 | | done | | RD-30 | Archive the finished backlogs (16,300 lines) + an archive README | 01 | | done | -| RD-31 | `ARCHITECTURE.md` section 6a: symbols not lines, 2 dead paths, new names | 03, 08, 16 | | todo | +| RD-31 | `ARCHITECTURE.md` section 6a: symbols not lines, 2 dead paths, new names | 03, 08, 16 | | done | | RD-32 | `fp-tea-atomic-design.md`: 11 broken paths + the broken anchor | 27 | | todo | | RD-33 | CLAUDE.md + `atomic-design.mdx` + the `ui-component` skill | 03, 27, 29 | yes | todo | | RD-34 | _(optional)_ `NO_SUBORGS`/`NO_TABLES` become `RemoteData.Empty` | 11 | | todo | diff --git a/docs/reference/architecture/ARCHITECTURE.md b/docs/reference/architecture/ARCHITECTURE.md index e9186cb..69f51cb 100644 --- a/docs/reference/architecture/ARCHITECTURE.md +++ b/docs/reference/architecture/ARCHITECTURE.md @@ -571,27 +571,34 @@ no longer hand-written DTOs — it's an **NSwag-generated typed client** - **Proxy.** The app uses a relative base URL (`apiBaseUrl: ''`), so `/api` calls are same-origin and `ng serve` proxies them to the backend on `:5000`. - ([`environment.ts`](../../../src/environments/environment.ts), - [`proxy.conf.json`](../../../proxy.conf.json)). Under `docker compose up` the app is served - localized (both locales) by `scripts/serve-i18n.mjs`, which proxies `/api` to the `api` - container itself (`API_PROXY_TARGET`). + ([`environment.ts`](../../../libs/shared/src/environments/environment.ts), + [`proxy.conf.json`](../../../apps/ssp/proxy.conf.json)). Each app carries its own + `proxy.conf.json` — `apps/ssp` and + [`apps/behandelportal`](../../../apps/behandelportal/proxy.conf.json) — and both point at + `http://localhost:5000`. Under `docker compose up` the app is served localized (both + locales) by `scripts/serve-i18n.mjs`, which proxies `/api` to the `api` container itself + (`API_PROXY_TARGET`). - **Client → HttpClient seam.** The NSwag client's `fetch` is routed through Angular's `HttpClient` by `httpClientFetch` — the one place cross-cutting concerns live: `X-Correlation-Id` on every call, `Idempotency-Key` on non-GETs, a 10 s timeout, and GET-only retry. Routing through `HttpClient` is exactly what lets the interceptors see API traffic. ([`api-client.provider.ts`](../../../libs/shared/src/infrastructure/api-client.provider.ts): - `httpClientFetch` L47-82, `provideApiClient` L86-92; registered in - [`app.config.ts`](../../../apps/ssp/src/app/app.config.ts) L37.) + `httpClientFetch`, `provideApiClient`; registered in + [`app.config.ts`](../../../apps/ssp/src/app/app.config.ts): `provideApiClient()`.) - **Interceptors (dev-only, stripped in prod).** `scenario.interceptor.ts` (the `?scenario=` toggle) and `role.interceptor.ts` (`X-Role` on role-aware endpoints). -**A read (dashboard):** `` → +**A read (dashboard):** `` in +[`mijn-registratie.section.ts`](../../../apps/ssp/src/app/registratie/ui/dashboard/mijn-registratie.section.ts) +(`MijnRegistratieSection`) → [`BigProfileStore`](../../../apps/ssp/src/app/registratie/application/big-profile.store.ts) → `DashboardViewAdapter.dashboardViewResource()` = `resource({ loader: () => client.dashboardView() })` ([`dashboard-view.adapter.ts`](../../../apps/ssp/src/app/registratie/infrastructure/dashboard-view.adapter.ts)) → GET `/api/v1/dashboard-view` → `httpClientFetch` → proxy → backend → back through the `parseDashboardView(json): Result` trust boundary → `RemoteData` → rendered. +[`wat-moet-ik-regelen.section.ts`](../../../apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.ts) +reads the same store. **A write (change address):** the `Submitting` effect (§2d) → `createSubmitChangeRequest` ([`submit-change-request.ts`](../../../apps/ssp/src/app/registratie/application/submit-change-request.ts)) @@ -603,8 +610,8 @@ ProblemDetails → string ([`submit.ts`](../../../libs/shared/src/application/su **Backend.** A single minimal-API host computes business decisions server-side (BFF-lite), returns ProblemDetails on rule rejection, and dedupes replays via `Idempotency-Key` -([`Program.cs`](../../../backend/src/BigRegister.Api/Program.cs): `/dashboard-view` L80, -`/change-requests` L120). +([`Program.cs`](../../../backend/src/BigRegister.Api/Program.cs): `api.MapGet("/dashboard-view")`, +`api.MapPost("/change-requests")`). ---