diff --git a/.claude/skills/document-feature/SKILL.md b/.claude/skills/document-feature/SKILL.md index 766fa29..c7679ef 100644 --- a/.claude/skills/document-feature/SKILL.md +++ b/.claude/skills/document-feature/SKILL.md @@ -20,11 +20,11 @@ The repo splits docs by kind (`docs/README.md`). Pick one — don't write all th _decision/pattern_ (a tradeoff, a "we chose X over Y"). One format, no drift: `# ADR-NNNN — Title`, then `Status: Accepted · Date: YYYY-MM-DD`, then Problem / Options / Decision / Consequences. -- **WP** — `docs/project/backlog/WP-NN-.md`. Tracked work; use the template at the - bottom of `docs/project/backlog/README.md`. +- **WP** — `docs/project/archive/backlog/WP-NN-.md`. Tracked work; use the template at the + bottom of `docs/project/archive/backlog/README.md`. Then **add the index row**: `docs/README.md` table for a reference doc/ADR, -`docs/project/backlog/README.md` for a WP. A doc with no index row is invisible. +`docs/project/archive/backlog/README.md` for a WP. A doc with no index row is invisible. ## Adjusted feature → update what already describes it diff --git a/.claude/skills/new-ssp/SKILL.md b/.claude/skills/new-ssp/SKILL.md index f87742b..1adac8d 100644 --- a/.claude/skills/new-ssp/SKILL.md +++ b/.claude/skills/new-ssp/SKILL.md @@ -62,7 +62,7 @@ Work through that checklist, keeping the GREEN gate below passing at every step. re-target it at an arbitrary new context, so it's deleted alongside `registratie`, along with its three wiring lines in `shell.component.ts` (import, `imports:` entry, template tag). - The `dashboard` route is **not** deleted even though it currently imports - `@registratie/ui/dashboard.page` — too much else hardcodes `/dashboard` (login's post-auth + `@overzicht/ui/overzicht.page` — too much else hardcodes `/dashboard` (login's post-auth redirect, `authGuard`'s fallback, header nav/logo, breadcrumb trail, several stories/specs). The script rewrites its `loadComponent` to point at the freshly scaffolded `--context` page instead (a `TODO(create-frontend)` stopgap landing page, not a real overview). @@ -85,8 +85,8 @@ Work through that checklist, keeping the GREEN gate below passing at every step. placeholder path and creates an empty `public/-huisstijl/` — it cannot generate a real house style. Vendor your CSS there, then re-point the `--rhc-*` bridge in `src/styles.scss` (ADR-0003 pattern: bridge, don't rewrite tokens), then `npm run check:tokens`. -- `docs/project/backlog/` WPs, PRDs, and memory-specific docs — new portal, new backlog - (keep `docs/project/backlog/README.md`'s WP process/template if you like the workflow). +- `docs/project/archive/backlog/` WPs, PRDs, and memory-specific docs — new portal, new backlog + (keep `docs/project/archive/backlog/README.md`'s WP process/template if you like the workflow). `docs/reference/scaffolding.md` also names `BigRegister.Api` in prose — update by hand. - `e2e/*.spec.ts` (`smoke.spec.ts`, `brief-v2.spec.ts`, `error-state.spec.ts`): full BIG-register user-flow tests (BSN login → registration wizard → submission assertions). diff --git a/.claude/skills/ui-component/SKILL.md b/.claude/skills/ui-component/SKILL.md index a565b35..fbb77ca 100644 --- a/.claude/skills/ui-component/SKILL.md +++ b/.claude/skills/ui-component/SKILL.md @@ -5,13 +5,13 @@ description: Add a shared UI building block (atom, molecule, organism) with its # UI component (atom / molecule / organism) -First: check `shared/ui/` and `shared/layout/` — a new page should be composition of -existing blocks. Only add a block when nothing fits. +First: check `libs/shared/src/ui/` and `libs/shared/src/layout/` — a new page should be +composition of existing blocks. Only add a block when nothing fits. ## Rules -- **Folder = atomic layer**: `shared/ui/` atoms → molecules → organisms; - `shared/layout/` templates. Each level only uses levels below. +- **Folder = atomic layer**: `libs/shared/src/ui/` atoms → molecules → organisms; + `libs/shared/src/layout/` templates. Each level only uses levels below. - Standalone component, **English name** (shared = language-agnostic), signal `input()`s only, `inject()` over constructor DI. - **Atoms are thin wrappers over CIBG Huisstijl (Bootstrap 5.2) classes** (`btn`, @@ -21,7 +21,8 @@ existing blocks. Only add a block when nothing fits. - **Tokens only** — `var(--rhc-*)` / `var(--app-*)`, never hardcoded colors (`npm run check:tokens` fails the build; escape hatch: `token-ok` marker + reason). - **No hardcoded Dutch** in shared components — expose copy as `input()`s with - `$localize` defaults; the domain caller supplies the text (see `shared/ui/async`). + `$localize` defaults; the domain caller supplies the text (see + `libs/shared/src/ui/molecules/async`). - Components with content-projected slots export a spread constant so callers import one thing: `export const ASYNC = [AsyncComponent, AsyncLoadedDirective, …] as const;` @@ -41,9 +42,10 @@ UI test surface. ## Worked examples -- Atom: `src/app/shared/ui/button/` — typed variant API over `btn` classes. -- Molecule: `src/app/shared/ui/async/` — slot directives, localizable input defaults, spread constant. -- Template: `src/app/shared/layout/wizard-shell/` — the canonical wizard outline. +- Atom: `libs/shared/src/ui/atoms/button/` — typed variant API over `btn` classes. +- Molecule: `libs/shared/src/ui/molecules/async/` — slot directives, localizable input + defaults, spread constant. +- Template: `libs/shared/src/layout/wizard-shell/` — the canonical wizard outline. ## Verify diff --git a/.prettierignore b/.prettierignore index 07cb7ce..63284c5 100644 --- a/.prettierignore +++ b/.prettierignore @@ -28,5 +28,5 @@ plop-templates/ backend/ # Agent prompts — their exact wording is the input, reflowing markdown edits the prompt -docs/project/refactor-backlog-setup/agents/ -docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/ +docs/project/archive/refactor-backlog-setup/agents/ +docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/ diff --git a/CLAUDE.md b/CLAUDE.md index f81bc1c..44aead4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,7 +12,7 @@ signals. Auth is faked; **data and business rules are served by a minimal ASP.NE Core backend** (`backend/`, see its README) and consumed through an NSwag-generated typed client. The FE renders the backend's decisions. Reference data mimicking BRP/DUO (`Data/SeedData.cs`) is in-memory; applications, documents and the brief -persist to a SQLite file via EF Core (WP-22) — `docs/project/backlog/WP-22-durable-persistence.md`. +persist to a SQLite file via EF Core (WP-22) — `docs/project/archive/backlog/WP-22-durable-persistence.md`. **Monorepo (WP-67):** two Angular projects share one backend + one shared library — `apps/ssp` (Zorgverlener self-service, this doc's main subject) and `apps/behandelportal` @@ -72,7 +72,7 @@ so this doesn't depend on a human remembering to run `/model` at the right momen `git status`/`grep`, verifying a file exists. No Edit/Write access. Delegate to the matching agent only when the _current_ session isn't already on that -model — don't add indirection for its own sake. `docs/project/backlog/README.md`'s +model — don't add indirection for its own sake. `docs/project/archive/backlog/README.md`'s session protocol is the worked example of this in practice. ## The decisions (non-negotiable working agreements) @@ -81,10 +81,11 @@ session protocol is the worked example of this in practice. `apps//src/app///` for an app-local context; `libs//src//` for a cross-app library (WP-67). Two apps today: `apps/ssp` (Zorgverlener self-service — -contexts `auth`, `registratie`, `herregistratie`, `brief` (letter-composition teaching -slice), `showcase` (teaching page, not a feature; **sanctioned** to read every context in -its own app — nothing imports it)) and `apps/behandelportal` (Behandelaar backoffice, -ADR-0002 — contexts `auth`, `behandeling`). Two cross-app libraries: `libs/shared` (the +contexts `auth`, `overzicht` (the portal home; composes `registratie`'s dashboard sections +plus its own cross-context nav sections), `registratie`, `herregistratie`, `brief` +(letter-composition teaching slice), `showcase` (teaching page, not a feature; **sanctioned** +to read every context in its own app — nothing imports it)) and `apps/behandelportal` +(Behandelaar backoffice, ADR-0002 — contexts `auth`, `behandeling`). Two cross-app libraries: `libs/shared` (the design system + kernel + generated API client — no business logic) and `libs/beheer` (the admin/stamdata context, identical for both apps today — WP-67 folded a silently-diverging duplicate copy back into one). `auth` is deliberately **not** shared even though today it's @@ -106,10 +107,11 @@ depend on `libs/beheer` either — it stays the base). `ui`/`layout` never impor lint-enforced (per app, since each app is cruised against its own tsconfig — WP-67's `.dependency-cruiser.base.js` + one thin `.dependency-cruiser..js` per app). An app may not import the other app's source directly. Cross-context only -`herregistratie → registratie → libs/shared|beheer`, `auth → libs/shared|beheer`, -`brief → libs/shared|beheer` (ssp); `behandeling → libs/shared|beheer`, `auth → -libs/shared|beheer` (behandelportal). Imports use aliases as direction statements: -`@shared/* @beheer/* @auth/* @registratie/* @herregistratie/* @brief/*` (ssp) — +`overzicht → registratie → libs/shared|beheer`, `herregistratie → registratie → +libs/shared|beheer`, `auth → libs/shared|beheer`, `brief → libs/shared|beheer` (ssp); +`behandeling → libs/shared|beheer`, `auth → libs/shared|beheer` (behandelportal). Imports use +aliases as direction statements: +`@shared/* @beheer/* @auth/* @overzicht/* @registratie/* @herregistratie/* @brief/*` (ssp) — `@shared/* @beheer/* @auth/* @behandeling/*` (behandelportal); each app's own `tsconfig.json` declares its full map (the root `tsconfig.json` intentionally has no `paths` — see its comment). `domain/` imports nothing from Angular. @@ -129,6 +131,18 @@ the design system does the visuals. (Where CIBG lacks a class — e.g. `skeleton `// CIBG-GAP EXTENSION:` marker; see ADR-0003. `alert` is **not** such a case: it wraps the vendored `.feedback feedback-*` classes.) +**The step-component contract.** A wizard step follows the same rule as +`address-fields.component.ts`: values in, events out, no internal state. Three clauses: + +1. **Inputs down.** A step reads its data only from `input()`s the container passes it. +2. **One narrow output up.** A step emits one specific event, not the container's whole + `dispatch`. +3. **`dispatch` is never passed down.** The container owns the Model and decides what a + step's event means; a step never calls `dispatch` itself. + +Corollary: a step gets **no** story of its own. The wizard's own story already mounts every +step, because it seeds the machine. + ### 3. State: make illegal states unrepresentable Default reflex — **if you're about to add a second/third boolean to track state, @@ -136,7 +150,7 @@ model a discriminated union instead.** Three tools, all in `libs/shared/src/appl - **`RemoteData`** (`remote-data.ts`) — `Loading | Empty | Failure{error} | Success{value}`. Combine sources with `map`/`map2`/`andThen` (Failure > Loading > Success). - Render it via the `` molecule (`libs/shared/src/ui/async`) — one of four + Render it via the `` molecule (`libs/shared/src/ui/molecules/async`) — one of four templates, mutually exclusive by construction. Default loading spinner/skeleton is delay-gated (~250ms) so fast connections don't flash. - **Elm-style store** (`store.ts` → `createStore(initial, reduce)`) — all state in @@ -242,7 +256,7 @@ organism doesn't get its own `Organisms/` bucket). (`` $localize`:@@context.key:Tekst` ``). Source locale is `nl`; a second locale is a translation file, not a code change (the seam). Shared/English components must **not** hardcode Dutch — expose copy as `input()`s with localizable defaults; the domain caller - supplies the text (see `libs/shared/src/ui/async`). Format-validation messages in + supplies the text (see `libs/shared/src/ui/molecules/async`). Format-validation messages in `domain/value-objects/` stay co-located but are still `$localize`-wrapped. - **Forms = one idiom.** Any form with validation or submission uses a `*.machine.ts` (Model/Msg/reduce) + value objects + a `submit-*` command returning `Result` — the @@ -272,7 +286,10 @@ organism doesn't get its own `Organisms/` bucket). - Prettier; `.editorconfig`. tsconfig: `noImplicitReturns`, `noPropertyAccessFromIndexSignature`, `noFallthroughCasesInSwitch`, `isolatedModules`. - **Enforced, not just hoped-for:** `npm run lint` (`eslint.config.mjs`, scoped to - `{apps,libs}/**`) fails the build on `any`; `npm run dep:check` + `{apps,libs}/**`) fails the build on `any`; the same config's `max-lines` rule caps every + `{apps,libs}/**/*.{page,component,section,step}.ts` file at 250 lines + (`skipBlankLines: true`, `skipComments: true`). 250 is reachable, not a style-guide + default — the dashboard page lands at 42 lines. `npm run dep:check` (`.dependency-cruiser.base.js` + one `.dependency-cruiser..js` per app, WP-67) fails on illegal imports — `domain/` importing Angular, a context importing "upward" (the `herregistratie → registratie → shared`, `auth → shared` direction), an app importing the diff --git a/README.md b/README.md index 7f97110..3447eba 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ Admin pages (`/beheer/*`, `/brief/huisstijl`) need the `admin` role — see | know _why_ a decision was made | [the ADRs](docs/reference/architecture/) — BFF-lite, contexts, huisstijl, stamdata, ZGW, test data | | work on the backend / BFF | [backend/README.md](backend/README.md) | | run OpenZaak locally | [backend/openzaak/README.md](backend/openzaak/README.md) | -| see what shipped, or pick up work | [docs/project/backlog/README.md](docs/project/backlog/README.md) | +| see what shipped, or pick up work | [docs/project/archive/backlog/README.md](docs/project/archive/backlog/README.md) | | build a feature the house way | [`.claude/skills/`](.claude/skills/) — invocable recipes (`new-feature`, `form-machine`, …) | | know the import rules | [dependencies.md](docs/reference/architecture/dependencies.md) — enforced by `dep:check` | | work on this repo as an AI agent | [CLAUDE.md](CLAUDE.md) | diff --git a/apps/ssp/src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts b/apps/ssp/src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts index 254da49..1e99ba8 100644 --- a/apps/ssp/src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts +++ b/apps/ssp/src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts @@ -263,10 +263,13 @@ export class HerregistratieWizardComponent { constructor() { // An explicit seed (stories/tests) wins; otherwise resume the backend draft // (`?aanvraag=`) or start fresh. Persistence is the draftSync controller's job. - const seeded = this.seed(); - queueMicrotask(() => - seeded !== initial ? this.dispatch({ tag: 'Seed', state: seeded }) : this.draftSync.resume(), - ); + // Read `seed()` INSIDE the microtask: Angular binds inputs after the constructor + // runs, so an eager read here always returns the `initial` default. + queueMicrotask(() => { + const seeded = this.seed(); + if (seeded !== initial) this.dispatch({ tag: 'Seed', state: seeded }); + else void this.draftSync.resume(); + }); } /** Reset the wizard to a fresh, empty start. */ diff --git a/apps/ssp/src/app/herregistratie/ui/intake-wizard/intake-wizard.component.spec.ts b/apps/ssp/src/app/herregistratie/ui/intake-wizard/intake-wizard.component.spec.ts index 69b0804..fe153e9 100644 --- a/apps/ssp/src/app/herregistratie/ui/intake-wizard/intake-wizard.component.spec.ts +++ b/apps/ssp/src/app/herregistratie/ui/intake-wizard/intake-wizard.component.spec.ts @@ -26,14 +26,30 @@ const buitenlandJa: IntakeState = { scholingThreshold: 1000, }; +/** Mount with a seed and let the constructor's microtask apply it. */ +async function mountSeeded(state: IntakeState) { + TestBed.configureTestingModule({ + providers: [provideHttpClient(), provideApiClient()], + }); + const fixture = TestBed.createComponent(IntakeWizardComponent); + fixture.componentRef.setInput('seed', state); + await Promise.resolve(); // the seed is applied in a queueMicrotask + fixture.detectChanges(); + return fixture; +} + describe('IntakeWizardComponent', () => { - it('renders each field group as its own grey
', () => { - TestBed.configureTestingModule({ - providers: [provideHttpClient(), provideApiClient()], - }); - const fixture = TestBed.createComponent(IntakeWizardComponent); - fixture.componentInstance.dispatch({ tag: 'Seed', state: buitenlandJa }); - fixture.detectChanges(); + // Regression: the constructor must read `seed()` INSIDE its microtask. Angular binds + // inputs after the constructor runs, so an eager read silently yields the `initial` + // default and every seeded story renders step 1 instead of the state it asked for. + it('honours the seed input', async () => { + const fixture = await mountSeeded(buitenlandJa); + + expect(fixture.componentInstance.state()).toEqual(buitenlandJa); + }); + + it('renders each field group as its own grey
', async () => { + const fixture = await mountSeeded(buitenlandJa); const fieldsets: HTMLElement[] = Array.from( fixture.nativeElement.querySelectorAll('form.form-horizontal fieldset'), diff --git a/apps/ssp/src/app/herregistratie/ui/intake-wizard/intake-wizard.component.ts b/apps/ssp/src/app/herregistratie/ui/intake-wizard/intake-wizard.component.ts index bfe20b9..56cbab7 100644 --- a/apps/ssp/src/app/herregistratie/ui/intake-wizard/intake-wizard.component.ts +++ b/apps/ssp/src/app/herregistratie/ui/intake-wizard/intake-wizard.component.ts @@ -212,10 +212,13 @@ export class IntakeWizardComponent { constructor() { // An explicit seed (stories/tests) wins; otherwise resume the backend draft // (`?aanvraag=`) or start fresh. Persistence is the draftSync controller's job. - const seeded = this.seed(); - queueMicrotask(() => - seeded !== initial ? this.dispatch({ tag: 'Seed', state: seeded }) : this.draftSync.resume(), - ); + // Read `seed()` INSIDE the microtask: Angular binds inputs after the constructor + // runs, so an eager read here always returns the `initial` default. + queueMicrotask(() => { + const seeded = this.seed(); + if (seeded !== initial) this.dispatch({ tag: 'Seed', state: seeded }); + else void this.draftSync.resume(); + }); // Apply the server-owned threshold into machine state as it arrives. Track // only the policy value; untrack the dispatch (it reads the state signal // internally, which would otherwise make this effect loop on its own write). diff --git a/apps/ssp/src/app/overzicht/ui/overzicht.page.ts b/apps/ssp/src/app/overzicht/ui/overzicht.page.ts index ad66f00..567136a 100644 --- a/apps/ssp/src/app/overzicht/ui/overzicht.page.ts +++ b/apps/ssp/src/app/overzicht/ui/overzicht.page.ts @@ -1,15 +1,15 @@ import { Component } from '@angular/core'; import { PageShellComponent } from '@shared/layout/page-shell/page-shell.component'; -import { MijnAanvragenSection } from '@registratie/ui/dashboard/mijn-aanvragen.section'; -import { WatMoetIkRegelenSection } from '@registratie/ui/dashboard/wat-moet-ik-regelen.section'; -import { MijnRegistratieSection } from '@registratie/ui/dashboard/mijn-registratie.section'; -import { SpecialismenSection } from '@registratie/ui/dashboard/specialismen.section'; +import { MijnAanvragenSection } from '@registratie/ui/overzicht-secties/mijn-aanvragen.section'; +import { WatMoetIkRegelenSection } from '@registratie/ui/overzicht-secties/wat-moet-ik-regelen.section'; +import { MijnRegistratieSection } from '@registratie/ui/overzicht-secties/mijn-registratie.section'; +import { SpecialismenSection } from '@registratie/ui/overzicht-secties/specialismen.section'; import { WatWiltUDoenSection } from './wat-wilt-u-doen.section'; import { BeheerLinksSection } from './beheer-links.section'; /** Page: "Mijn overzicht" — the portal home, following the NL Design System "Mijn omgeving" pattern. Composition only: each section below answers its own data - question (own store, own async state) — four sections stay in `registratie/ui/dashboard/` + question (own store, own async state) — four sections stay in `registratie/ui/overzicht-secties/` (they render registratie data), two live here (cross-context navigation). */ @Component({ selector: 'app-overzicht-page', diff --git a/apps/ssp/src/app/registratie/ui/aanvraag-block/aanvraag-block.stories.ts b/apps/ssp/src/app/registratie/ui/aanvraag-block/aanvraag-block.stories.ts index 449567c..c4fbe4b 100644 --- a/apps/ssp/src/app/registratie/ui/aanvraag-block/aanvraag-block.stories.ts +++ b/apps/ssp/src/app/registratie/ui/aanvraag-block/aanvraag-block.stories.ts @@ -17,57 +17,17 @@ const meta: Meta = { title: 'Domein/Registratie/Aanvraag Block', component: AanvraagBlockComponent, decorators: [applicationConfig({ providers: [provideRouter([])] })], - render: (args) => ({ - props: args, - // A row is an
  • — the keuzelijst styling needs the real list context. - template: `
    `, - }), - parameters: { - // Structural: app-aanvraag-block's host sits between the keuzelijst
      and its
    • - // — axe's list/listitem rule needs them adjacent regardless of `display:contents`. - // WP-11 (CIBG markup fidelity) reworks this markup; see docs/project/backlog/WP-11-markup-fidelity.md. - a11y: { disable: true }, - }, + // A Concept renders as a CIBG melding (block element), not a keuzelijst
    • — no
        + // wrapper. Production agrees: mijn-aanvragen.section.ts renders this block for concepten + // only, outside any list. + render: (args) => ({ props: args, template: `` }), }; export default meta; type Story = StoryObj; -// One story per status variant; the block renders its own body + actions. -// A Concept renders as a CIBG melding (block element), not a keuzelijst
      • — no
          wrapper. +// The whole template sits inside `@if (aanvraag().status.tag === 'Concept')`, so this is +// the only status that renders anything. Submitted/resolved aanvragen render through +// application-link, which has its own stories. export const Concept: Story = { args: { aanvraag: { ...base, status: { tag: 'Concept', stepIndex: 1, stepCount: 3 } } }, - render: (args) => ({ props: args, template: `` }), -}; -export const InBehandelingAuto: Story = { - args: { - aanvraag: { - ...base, - status: { tag: 'InBehandeling', referentie: 'BIG-2026-456789', manual: false }, - }, - }, -}; -export const InBehandelingManual: Story = { - args: { - aanvraag: { - ...base, - type: 'registratie', - status: { tag: 'InBehandeling', referentie: 'BIG-2026-456789', manual: true }, - }, - }, -}; -export const Goedgekeurd: Story = { - args: { aanvraag: { ...base, status: { tag: 'Goedgekeurd', referentie: 'BIG-2026-456789' } } }, -}; -export const Afgewezen: Story = { - args: { - aanvraag: { - ...base, - type: 'herregistratie', - status: { - tag: 'Afgewezen', - referentie: 'BIG-2026-456789', - reden: 'Aanvraag afgewezen: geen gewerkte uren geregistreerd.', - }, - }, - }, }; diff --git a/apps/ssp/src/app/registratie/ui/dashboard/mijn-aanvragen.section.stories.ts b/apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-aanvragen.section.stories.ts similarity index 100% rename from apps/ssp/src/app/registratie/ui/dashboard/mijn-aanvragen.section.stories.ts rename to apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-aanvragen.section.stories.ts diff --git a/apps/ssp/src/app/registratie/ui/dashboard/mijn-aanvragen.section.ts b/apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-aanvragen.section.ts similarity index 100% rename from apps/ssp/src/app/registratie/ui/dashboard/mijn-aanvragen.section.ts rename to apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-aanvragen.section.ts diff --git a/apps/ssp/src/app/registratie/ui/dashboard/mijn-registratie.section.stories.ts b/apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-registratie.section.stories.ts similarity index 100% rename from apps/ssp/src/app/registratie/ui/dashboard/mijn-registratie.section.stories.ts rename to apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-registratie.section.stories.ts diff --git a/apps/ssp/src/app/registratie/ui/dashboard/mijn-registratie.section.ts b/apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-registratie.section.ts similarity index 100% rename from apps/ssp/src/app/registratie/ui/dashboard/mijn-registratie.section.ts rename to apps/ssp/src/app/registratie/ui/overzicht-secties/mijn-registratie.section.ts diff --git a/apps/ssp/src/app/registratie/ui/dashboard/specialismen.section.stories.ts b/apps/ssp/src/app/registratie/ui/overzicht-secties/specialismen.section.stories.ts similarity index 100% rename from apps/ssp/src/app/registratie/ui/dashboard/specialismen.section.stories.ts rename to apps/ssp/src/app/registratie/ui/overzicht-secties/specialismen.section.stories.ts diff --git a/apps/ssp/src/app/registratie/ui/dashboard/specialismen.section.ts b/apps/ssp/src/app/registratie/ui/overzicht-secties/specialismen.section.ts similarity index 100% rename from apps/ssp/src/app/registratie/ui/dashboard/specialismen.section.ts rename to apps/ssp/src/app/registratie/ui/overzicht-secties/specialismen.section.ts diff --git a/apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.stories.ts b/apps/ssp/src/app/registratie/ui/overzicht-secties/wat-moet-ik-regelen.section.stories.ts similarity index 86% rename from apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.stories.ts rename to apps/ssp/src/app/registratie/ui/overzicht-secties/wat-moet-ik-regelen.section.stories.ts index 05fed6a..2bba22d 100644 --- a/apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.stories.ts +++ b/apps/ssp/src/app/registratie/ui/overzicht-secties/wat-moet-ik-regelen.section.stories.ts @@ -66,14 +66,6 @@ export const MetTaken: Story = { ], }), ], - parameters: { - // Structural: app-choice-link's host sits between the keuzelijst
            and its
          • - // — axe's list/listitem rule needs them adjacent regardless of `display:contents`. - // Same pre-existing gap as task-list.stories.ts and choice-list.stories.ts. WP-11 - // (CIBG markup fidelity) reworks this markup; see - // docs/project/backlog/WP-11-markup-fidelity.md. - a11y: { disable: true }, - }, }; export const NietsOpenstaand: Story = { decorators: [ diff --git a/apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.ts b/apps/ssp/src/app/registratie/ui/overzicht-secties/wat-moet-ik-regelen.section.ts similarity index 100% rename from apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.ts rename to apps/ssp/src/app/registratie/ui/overzicht-secties/wat-moet-ik-regelen.section.ts diff --git a/apps/ssp/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts b/apps/ssp/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts index 4f8241d..eb2a740 100644 --- a/apps/ssp/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts +++ b/apps/ssp/src/app/registratie/ui/registratie-wizard/registratie-wizard.component.ts @@ -233,10 +233,13 @@ export class RegistratieWizardComponent { constructor() { // An explicit seed (stories/tests) wins; otherwise resume from the backend draft // (`?aanvraag=`), or start fresh. Persistence is the draftSync controller's job. - const seeded = this.seed(); - queueMicrotask(() => - seeded !== initial ? this.dispatch({ tag: 'Seed', state: seeded }) : this.draftSync.resume(), - ); + // Read `seed()` INSIDE the microtask: Angular binds inputs after the constructor + // runs, so an eager read here always returns the `initial` default. + queueMicrotask(() => { + const seeded = this.seed(); + if (seeded !== initial) this.dispatch({ tag: 'Seed', state: seeded }); + else void this.draftSync.resume(); + }); // Prefill the address from the BRP lookup as it arrives. Track only the facade's // parsed prefill signal; untrack the dispatch (it reads the state signal, which // would otherwise make this effect loop on its own write). Don't clobber diff --git a/backend/README.md b/backend/README.md index 9923935..565937e 100644 --- a/backend/README.md +++ b/backend/README.md @@ -15,7 +15,7 @@ status codes and error envelope are production-shaped. covers it, see `docker-compose.yml`) does **not** lose data. Delete the file to reset demo data back to empty, the same state a fresh clone starts from. This is a deliberate, right-sized choice for a POC (SQLite, no external DB service) — see -`docs/project/backlog/WP-22-durable-persistence.md`. +`docs/project/archive/backlog/WP-22-durable-persistence.md`. ## Run diff --git a/backend/src/BigRegister.Api/Domain/Letters/LetterHtml.cs b/backend/src/BigRegister.Api/Domain/Letters/LetterHtml.cs index 9c3541d..6c489a3 100644 --- a/backend/src/BigRegister.Api/Domain/Letters/LetterHtml.cs +++ b/backend/src/BigRegister.Api/Domain/Letters/LetterHtml.cs @@ -152,7 +152,7 @@ public static class LetterHtml // Walks up from the running assembly's own directory (NOT the process cwd, which // varies by how `dotnet run`/docker/tests invoke it — see - // docs/project/backlog/WP-25-letter-preview-html.md) until it finds `public/letter.css`. docker-compose.yml bind-mounts `./public` under the + // docs/project/archive/backlog/WP-25-letter-preview-html.md) until it finds `public/letter.css`. docker-compose.yml bind-mounts `./public` under the // api container's `/src` for exactly this walk to resolve there too. private static string FindLetterCss() { diff --git a/docker-compose.yml b/docker-compose.yml index 2966c6d..4968a3a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,8 @@ services: command: dotnet run --project src/BigRegister.Api --urls http://+:5000 environment: - ASPNETCORE_ENVIRONMENT=Development + # ponytail: Server GC makes one heap per CPU (22 here); workstation GC makes one. + - DOTNET_gcServer=0 volumes: # ':z' relabels for SELinux (Fedora/RHEL); harmless on other hosts. # WP-22: no separate volume needed for the SQLite file — `dotnet run` sets @@ -41,6 +43,8 @@ services: # switcher actually switches. ponytail: `--no-fund --loglevel=error` silences npm 11 noise. command: sh -c "npm ci --no-fund --loglevel=error && npx ng build ssp --configuration development --localize && node scripts/serve-i18n.mjs" environment: + # ponytail: without a cgroup limit Node sizes its heap from host RAM (16 GB). + - NODE_OPTIONS=--max-old-space-size=2048 - PORT=4200 - API_PROXY_TARGET=http://api:5000 - APP_DIST_ROOT=dist/ssp/browser @@ -57,6 +61,8 @@ services: working_dir: /app command: sh -c "npm ci --no-fund --loglevel=error && npx ng build behandelportal --configuration development --localize && node scripts/serve-i18n.mjs" environment: + # ponytail: without a cgroup limit Node sizes its heap from host RAM (16 GB). + - NODE_OPTIONS=--max-old-space-size=2048 - PORT=4201 - API_PROXY_TARGET=http://api:5000 - APP_DIST_ROOT=dist/behandelportal/browser diff --git a/docs/project/archive/README.md b/docs/project/archive/README.md new file mode 100644 index 0000000..c0c87b8 --- /dev/null +++ b/docs/project/archive/README.md @@ -0,0 +1,11 @@ +# Archive — finished backlogs + +The trees in this directory are historical. Every ticket in `backlog/` and +`refactor-backlog-setup/` carries `Status: done`. `SHOWCASE-ROADMAP.md` was superseded before +either arc started. + +Git holds the rest — `git log --follow` on any file here shows its full history, including the +work that produced it. + +The live plan is `docs/project/readable-codebase/`. Product reference material is +`docs/project/prd/`. diff --git a/docs/project/SHOWCASE-ROADMAP.md b/docs/project/archive/SHOWCASE-ROADMAP.md similarity index 79% rename from docs/project/SHOWCASE-ROADMAP.md rename to docs/project/archive/SHOWCASE-ROADMAP.md index 023e1eb..9227ae3 100644 --- a/docs/project/SHOWCASE-ROADMAP.md +++ b/docs/project/archive/SHOWCASE-ROADMAP.md @@ -1,6 +1,6 @@ # Showcase roadmap — superseded -**This roadmap is superseded by [`docs/project/backlog/`](backlog/README.md)** (2026-07-02). +**This roadmap is superseded by [`docs/project/archive/backlog/`](backlog/README.md)** (2026-07-02). The backlog absorbs and corrects this document: its Storybook-as-curriculum track became WP-14/15 (+ per-invariant MDX pages in WP-05/07/08/13/17), its enforcement track became diff --git a/docs/project/backlog/README.md b/docs/project/archive/backlog/README.md similarity index 100% rename from docs/project/backlog/README.md rename to docs/project/archive/backlog/README.md diff --git a/docs/project/backlog/WP-01-axe-ci-gate.md b/docs/project/archive/backlog/WP-01-axe-ci-gate.md similarity index 100% rename from docs/project/backlog/WP-01-axe-ci-gate.md rename to docs/project/archive/backlog/WP-01-axe-ci-gate.md diff --git a/docs/project/backlog/WP-02-check-tokens.md b/docs/project/archive/backlog/WP-02-check-tokens.md similarity index 100% rename from docs/project/backlog/WP-02-check-tokens.md rename to docs/project/archive/backlog/WP-02-check-tokens.md diff --git a/docs/project/backlog/WP-03-contracts-purity.md b/docs/project/archive/backlog/WP-03-contracts-purity.md similarity index 100% rename from docs/project/backlog/WP-03-contracts-purity.md rename to docs/project/archive/backlog/WP-03-contracts-purity.md diff --git a/docs/project/backlog/WP-04-ui-not-infrastructure.md b/docs/project/archive/backlog/WP-04-ui-not-infrastructure.md similarity index 100% rename from docs/project/backlog/WP-04-ui-not-infrastructure.md rename to docs/project/archive/backlog/WP-04-ui-not-infrastructure.md diff --git a/docs/project/backlog/WP-05-parse-boundaries.md b/docs/project/archive/backlog/WP-05-parse-boundaries.md similarity index 100% rename from docs/project/backlog/WP-05-parse-boundaries.md rename to docs/project/archive/backlog/WP-05-parse-boundaries.md diff --git a/docs/project/backlog/WP-06-typed-async.md b/docs/project/archive/backlog/WP-06-typed-async.md similarity index 100% rename from docs/project/backlog/WP-06-typed-async.md rename to docs/project/archive/backlog/WP-06-typed-async.md diff --git a/docs/project/backlog/WP-07-brief-idioms.md b/docs/project/archive/backlog/WP-07-brief-idioms.md similarity index 100% rename from docs/project/backlog/WP-07-brief-idioms.md rename to docs/project/archive/backlog/WP-07-brief-idioms.md diff --git a/docs/project/backlog/WP-08-store-idiom.md b/docs/project/archive/backlog/WP-08-store-idiom.md similarity index 100% rename from docs/project/backlog/WP-08-store-idiom.md rename to docs/project/archive/backlog/WP-08-store-idiom.md diff --git a/docs/project/backlog/WP-09-pure-logic.md b/docs/project/archive/backlog/WP-09-pure-logic.md similarity index 100% rename from docs/project/backlog/WP-09-pure-logic.md rename to docs/project/archive/backlog/WP-09-pure-logic.md diff --git a/docs/project/backlog/WP-10-button-fidelity.md b/docs/project/archive/backlog/WP-10-button-fidelity.md similarity index 100% rename from docs/project/backlog/WP-10-button-fidelity.md rename to docs/project/archive/backlog/WP-10-button-fidelity.md diff --git a/docs/project/backlog/WP-11-markup-fidelity.md b/docs/project/archive/backlog/WP-11-markup-fidelity.md similarity index 100% rename from docs/project/backlog/WP-11-markup-fidelity.md rename to docs/project/archive/backlog/WP-11-markup-fidelity.md diff --git a/docs/project/backlog/WP-12-datablock.md b/docs/project/archive/backlog/WP-12-datablock.md similarity index 100% rename from docs/project/backlog/WP-12-datablock.md rename to docs/project/archive/backlog/WP-12-datablock.md diff --git a/docs/project/backlog/WP-13-cibg-gap-register.md b/docs/project/archive/backlog/WP-13-cibg-gap-register.md similarity index 100% rename from docs/project/backlog/WP-13-cibg-gap-register.md rename to docs/project/archive/backlog/WP-13-cibg-gap-register.md diff --git a/docs/project/backlog/WP-14-storybook-taxonomy.md b/docs/project/archive/backlog/WP-14-storybook-taxonomy.md similarity index 100% rename from docs/project/backlog/WP-14-storybook-taxonomy.md rename to docs/project/archive/backlog/WP-14-storybook-taxonomy.md diff --git a/docs/project/backlog/WP-15-missing-stories.md b/docs/project/archive/backlog/WP-15-missing-stories.md similarity index 100% rename from docs/project/backlog/WP-15-missing-stories.md rename to docs/project/archive/backlog/WP-15-missing-stories.md diff --git a/docs/project/backlog/WP-16-component-a11y.md b/docs/project/archive/backlog/WP-16-component-a11y.md similarity index 100% rename from docs/project/backlog/WP-16-component-a11y.md rename to docs/project/archive/backlog/WP-16-component-a11y.md diff --git a/docs/project/backlog/WP-17-app-a11y.md b/docs/project/archive/backlog/WP-17-app-a11y.md similarity index 100% rename from docs/project/backlog/WP-17-app-a11y.md rename to docs/project/archive/backlog/WP-17-app-a11y.md diff --git a/docs/project/backlog/WP-18-abac-capability-spine.md b/docs/project/archive/backlog/WP-18-abac-capability-spine.md similarity index 100% rename from docs/project/backlog/WP-18-abac-capability-spine.md rename to docs/project/archive/backlog/WP-18-abac-capability-spine.md diff --git a/docs/project/backlog/WP-19-e2e-smoke.md b/docs/project/archive/backlog/WP-19-e2e-smoke.md similarity index 100% rename from docs/project/backlog/WP-19-e2e-smoke.md rename to docs/project/archive/backlog/WP-19-e2e-smoke.md diff --git a/docs/project/backlog/WP-20-second-locale.md b/docs/project/archive/backlog/WP-20-second-locale.md similarity index 100% rename from docs/project/backlog/WP-20-second-locale.md rename to docs/project/archive/backlog/WP-20-second-locale.md diff --git a/docs/project/backlog/WP-21-resilience-seams.md b/docs/project/archive/backlog/WP-21-resilience-seams.md similarity index 100% rename from docs/project/backlog/WP-21-resilience-seams.md rename to docs/project/archive/backlog/WP-21-resilience-seams.md diff --git a/docs/project/backlog/WP-22-durable-persistence.md b/docs/project/archive/backlog/WP-22-durable-persistence.md similarity index 100% rename from docs/project/backlog/WP-22-durable-persistence.md rename to docs/project/archive/backlog/WP-22-durable-persistence.md diff --git a/docs/project/backlog/WP-23-org-template-backend.md b/docs/project/archive/backlog/WP-23-org-template-backend.md similarity index 100% rename from docs/project/backlog/WP-23-org-template-backend.md rename to docs/project/archive/backlog/WP-23-org-template-backend.md diff --git a/docs/project/backlog/WP-24-letter-canvas.md b/docs/project/archive/backlog/WP-24-letter-canvas.md similarity index 100% rename from docs/project/backlog/WP-24-letter-canvas.md rename to docs/project/archive/backlog/WP-24-letter-canvas.md diff --git a/docs/project/backlog/WP-25-letter-preview-html.md b/docs/project/archive/backlog/WP-25-letter-preview-html.md similarity index 100% rename from docs/project/backlog/WP-25-letter-preview-html.md rename to docs/project/archive/backlog/WP-25-letter-preview-html.md diff --git a/docs/project/backlog/WP-26-org-template-editor.md b/docs/project/archive/backlog/WP-26-org-template-editor.md similarity index 100% rename from docs/project/backlog/WP-26-org-template-editor.md rename to docs/project/archive/backlog/WP-26-org-template-editor.md diff --git a/docs/project/backlog/WP-27-brief-ux-layer.md b/docs/project/archive/backlog/WP-27-brief-ux-layer.md similarity index 100% rename from docs/project/backlog/WP-27-brief-ux-layer.md rename to docs/project/archive/backlog/WP-27-brief-ux-layer.md diff --git a/docs/project/backlog/WP-28-brief-v2-demo-polish.md b/docs/project/archive/backlog/WP-28-brief-v2-demo-polish.md similarity index 100% rename from docs/project/backlog/WP-28-brief-v2-demo-polish.md rename to docs/project/archive/backlog/WP-28-brief-v2-demo-polish.md diff --git a/docs/project/backlog/WP-29-stamdata-beheer-editor.md b/docs/project/archive/backlog/WP-29-stamdata-beheer-editor.md similarity index 100% rename from docs/project/backlog/WP-29-stamdata-beheer-editor.md rename to docs/project/archive/backlog/WP-29-stamdata-beheer-editor.md diff --git a/docs/project/backlog/WP-30-ci-perf-followups.md b/docs/project/archive/backlog/WP-30-ci-perf-followups.md similarity index 100% rename from docs/project/backlog/WP-30-ci-perf-followups.md rename to docs/project/archive/backlog/WP-30-ci-perf-followups.md diff --git a/docs/project/backlog/WP-31-shared-store-helpers.md b/docs/project/archive/backlog/WP-31-shared-store-helpers.md similarity index 100% rename from docs/project/backlog/WP-31-shared-store-helpers.md rename to docs/project/archive/backlog/WP-31-shared-store-helpers.md diff --git a/docs/project/backlog/WP-33-dev-switchers.md b/docs/project/archive/backlog/WP-33-dev-switchers.md similarity index 100% rename from docs/project/backlog/WP-33-dev-switchers.md rename to docs/project/archive/backlog/WP-33-dev-switchers.md diff --git a/docs/project/backlog/WP-34-adres-phone-brp-readonly.md b/docs/project/archive/backlog/WP-34-adres-phone-brp-readonly.md similarity index 100% rename from docs/project/backlog/WP-34-adres-phone-brp-readonly.md rename to docs/project/archive/backlog/WP-34-adres-phone-brp-readonly.md diff --git a/docs/project/backlog/WP-35-one-concept-per-type.md b/docs/project/archive/backlog/WP-35-one-concept-per-type.md similarity index 100% rename from docs/project/backlog/WP-35-one-concept-per-type.md rename to docs/project/archive/backlog/WP-35-one-concept-per-type.md diff --git a/docs/project/backlog/WP-36-admin-cases.md b/docs/project/archive/backlog/WP-36-admin-cases.md similarity index 100% rename from docs/project/backlog/WP-36-admin-cases.md rename to docs/project/archive/backlog/WP-36-admin-cases.md diff --git a/docs/project/backlog/WP-37-dev-switcher-reset.md b/docs/project/archive/backlog/WP-37-dev-switcher-reset.md similarity index 100% rename from docs/project/backlog/WP-37-dev-switcher-reset.md rename to docs/project/archive/backlog/WP-37-dev-switcher-reset.md diff --git a/docs/project/backlog/WP-38-dependency-graph-boundaries.md b/docs/project/archive/backlog/WP-38-dependency-graph-boundaries.md similarity index 100% rename from docs/project/backlog/WP-38-dependency-graph-boundaries.md rename to docs/project/archive/backlog/WP-38-dependency-graph-boundaries.md diff --git a/docs/project/backlog/WP-39-showcase-snippets-animations.md b/docs/project/archive/backlog/WP-39-showcase-snippets-animations.md similarity index 100% rename from docs/project/backlog/WP-39-showcase-snippets-animations.md rename to docs/project/archive/backlog/WP-39-showcase-snippets-animations.md diff --git a/docs/project/backlog/WP-40-pii-kernel.md b/docs/project/archive/backlog/WP-40-pii-kernel.md similarity index 100% rename from docs/project/backlog/WP-40-pii-kernel.md rename to docs/project/archive/backlog/WP-40-pii-kernel.md diff --git a/docs/project/backlog/WP-41-persisted-authz-audit.md b/docs/project/archive/backlog/WP-41-persisted-authz-audit.md similarity index 100% rename from docs/project/backlog/WP-41-persisted-authz-audit.md rename to docs/project/archive/backlog/WP-41-persisted-authz-audit.md diff --git a/docs/project/backlog/WP-42-privacy-security-showcase.md b/docs/project/archive/backlog/WP-42-privacy-security-showcase.md similarity index 100% rename from docs/project/backlog/WP-42-privacy-security-showcase.md rename to docs/project/archive/backlog/WP-42-privacy-security-showcase.md diff --git a/docs/project/backlog/WP-43-scaffold-generators.md b/docs/project/archive/backlog/WP-43-scaffold-generators.md similarity index 100% rename from docs/project/backlog/WP-43-scaffold-generators.md rename to docs/project/archive/backlog/WP-43-scaffold-generators.md diff --git a/docs/project/backlog/WP-44-context-generator.md b/docs/project/archive/backlog/WP-44-context-generator.md similarity index 100% rename from docs/project/backlog/WP-44-context-generator.md rename to docs/project/archive/backlog/WP-44-context-generator.md diff --git a/docs/project/backlog/WP-45-create-frontend-generator.md b/docs/project/archive/backlog/WP-45-create-frontend-generator.md similarity index 100% rename from docs/project/backlog/WP-45-create-frontend-generator.md rename to docs/project/archive/backlog/WP-45-create-frontend-generator.md diff --git a/docs/project/backlog/WP-46-vitest-coverage.md b/docs/project/archive/backlog/WP-46-vitest-coverage.md similarity index 100% rename from docs/project/backlog/WP-46-vitest-coverage.md rename to docs/project/archive/backlog/WP-46-vitest-coverage.md diff --git a/docs/project/backlog/WP-47-feature-flags.md b/docs/project/archive/backlog/WP-47-feature-flags.md similarity index 100% rename from docs/project/backlog/WP-47-feature-flags.md rename to docs/project/archive/backlog/WP-47-feature-flags.md diff --git a/docs/project/backlog/WP-48-stamdata-deletion-protection.md b/docs/project/archive/backlog/WP-48-stamdata-deletion-protection.md similarity index 100% rename from docs/project/backlog/WP-48-stamdata-deletion-protection.md rename to docs/project/archive/backlog/WP-48-stamdata-deletion-protection.md diff --git a/docs/project/backlog/WP-49-openzaak-zaken-read-seam.md b/docs/project/archive/backlog/WP-49-openzaak-zaken-read-seam.md similarity index 100% rename from docs/project/backlog/WP-49-openzaak-zaken-read-seam.md rename to docs/project/archive/backlog/WP-49-openzaak-zaken-read-seam.md diff --git a/docs/project/backlog/WP-50-openzaak-create-zaak.md b/docs/project/archive/backlog/WP-50-openzaak-create-zaak.md similarity index 100% rename from docs/project/backlog/WP-50-openzaak-create-zaak.md rename to docs/project/archive/backlog/WP-50-openzaak-create-zaak.md diff --git a/docs/project/backlog/WP-51-openzaak-documenten.md b/docs/project/archive/backlog/WP-51-openzaak-documenten.md similarity index 100% rename from docs/project/backlog/WP-51-openzaak-documenten.md rename to docs/project/archive/backlog/WP-51-openzaak-documenten.md diff --git a/docs/project/backlog/WP-52-openzaak-notificaties.md b/docs/project/archive/backlog/WP-52-openzaak-notificaties.md similarity index 100% rename from docs/project/backlog/WP-52-openzaak-notificaties.md rename to docs/project/archive/backlog/WP-52-openzaak-notificaties.md diff --git a/docs/project/backlog/WP-53-inbound-identity-and-citizen-scoping.md b/docs/project/archive/backlog/WP-53-inbound-identity-and-citizen-scoping.md similarity index 100% rename from docs/project/backlog/WP-53-inbound-identity-and-citizen-scoping.md rename to docs/project/archive/backlog/WP-53-inbound-identity-and-citizen-scoping.md diff --git a/docs/project/backlog/WP-54-openzaak-integration-harness.md b/docs/project/archive/backlog/WP-54-openzaak-integration-harness.md similarity index 100% rename from docs/project/backlog/WP-54-openzaak-integration-harness.md rename to docs/project/archive/backlog/WP-54-openzaak-integration-harness.md diff --git a/docs/project/backlog/WP-55-openzaak-secrets-tls.md b/docs/project/archive/backlog/WP-55-openzaak-secrets-tls.md similarity index 100% rename from docs/project/backlog/WP-55-openzaak-secrets-tls.md rename to docs/project/archive/backlog/WP-55-openzaak-secrets-tls.md diff --git a/docs/project/backlog/WP-56-openzaak-catalogus-provisioning.md b/docs/project/archive/backlog/WP-56-openzaak-catalogus-provisioning.md similarity index 100% rename from docs/project/backlog/WP-56-openzaak-catalogus-provisioning.md rename to docs/project/archive/backlog/WP-56-openzaak-catalogus-provisioning.md diff --git a/docs/project/backlog/WP-57-openzaak-least-privilege-scopes.md b/docs/project/archive/backlog/WP-57-openzaak-least-privilege-scopes.md similarity index 100% rename from docs/project/backlog/WP-57-openzaak-least-privilege-scopes.md rename to docs/project/archive/backlog/WP-57-openzaak-least-privilege-scopes.md diff --git a/docs/project/backlog/WP-58-openzaak-notifications.md b/docs/project/archive/backlog/WP-58-openzaak-notifications.md similarity index 100% rename from docs/project/backlog/WP-58-openzaak-notifications.md rename to docs/project/archive/backlog/WP-58-openzaak-notifications.md diff --git a/docs/project/backlog/WP-59-document-confidentialiteit-config.md b/docs/project/archive/backlog/WP-59-document-confidentialiteit-config.md similarity index 100% rename from docs/project/backlog/WP-59-document-confidentialiteit-config.md rename to docs/project/archive/backlog/WP-59-document-confidentialiteit-config.md diff --git a/docs/project/backlog/WP-60-write-divergence-resilience.md b/docs/project/archive/backlog/WP-60-write-divergence-resilience.md similarity index 100% rename from docs/project/backlog/WP-60-write-divergence-resilience.md rename to docs/project/archive/backlog/WP-60-write-divergence-resilience.md diff --git a/docs/project/backlog/WP-61-behandelportal-bootstrap.md b/docs/project/archive/backlog/WP-61-behandelportal-bootstrap.md similarity index 100% rename from docs/project/backlog/WP-61-behandelportal-bootstrap.md rename to docs/project/archive/backlog/WP-61-behandelportal-bootstrap.md diff --git a/docs/project/backlog/WP-62-medewerker-identity-authz.md b/docs/project/archive/backlog/WP-62-medewerker-identity-authz.md similarity index 100% rename from docs/project/backlog/WP-62-medewerker-identity-authz.md rename to docs/project/archive/backlog/WP-62-medewerker-identity-authz.md diff --git a/docs/project/backlog/WP-63-aanvraag-status-lifecycle.md b/docs/project/archive/backlog/WP-63-aanvraag-status-lifecycle.md similarity index 100% rename from docs/project/backlog/WP-63-aanvraag-status-lifecycle.md rename to docs/project/archive/backlog/WP-63-aanvraag-status-lifecycle.md diff --git a/docs/project/backlog/WP-64-behandelportal-werkvoorraad.md b/docs/project/archive/backlog/WP-64-behandelportal-werkvoorraad.md similarity index 100% rename from docs/project/backlog/WP-64-behandelportal-werkvoorraad.md rename to docs/project/archive/backlog/WP-64-behandelportal-werkvoorraad.md diff --git a/docs/project/backlog/WP-65-behandelportal-beoordeling.md b/docs/project/archive/backlog/WP-65-behandelportal-beoordeling.md similarity index 100% rename from docs/project/backlog/WP-65-behandelportal-beoordeling.md rename to docs/project/archive/backlog/WP-65-behandelportal-beoordeling.md diff --git a/docs/project/backlog/WP-66-behandelportal-openzaak-write.md b/docs/project/archive/backlog/WP-66-behandelportal-openzaak-write.md similarity index 100% rename from docs/project/backlog/WP-66-behandelportal-openzaak-write.md rename to docs/project/archive/backlog/WP-66-behandelportal-openzaak-write.md diff --git a/docs/project/backlog/WP-67-monorepo-behandelportal.md b/docs/project/archive/backlog/WP-67-monorepo-behandelportal.md similarity index 100% rename from docs/project/backlog/WP-67-monorepo-behandelportal.md rename to docs/project/archive/backlog/WP-67-monorepo-behandelportal.md diff --git a/docs/project/backlog/WP-68-ddd-aggregate-hardening.md b/docs/project/archive/backlog/WP-68-ddd-aggregate-hardening.md similarity index 99% rename from docs/project/backlog/WP-68-ddd-aggregate-hardening.md rename to docs/project/archive/backlog/WP-68-ddd-aggregate-hardening.md index b715093..8d39138 100644 --- a/docs/project/backlog/WP-68-ddd-aggregate-hardening.md +++ b/docs/project/archive/backlog/WP-68-ddd-aggregate-hardening.md @@ -59,7 +59,7 @@ The review's remaining findings are listed under "Follow-ups" and are **not** th ## Read first - `CLAUDE.md` §"The decisions" #3 (make illegal states unrepresentable) and #4 (BFF-lite) -- [ADR-0001 — BFF-lite + decision DTOs](../../reference/architecture/0001-bff-lite-decision-dtos.md) +- [ADR-0001 — BFF-lite + decision DTOs](../../../reference/architecture/0001-bff-lite-decision-dtos.md) - `backend/src/BigRegister.Api/Data/ApplicationStore.cs` (the `Aanvraag` entity, the store's lock discipline, `AanvraagStatusTag`, `RecordBesluit`) - `backend/src/BigRegister.Api/Contracts/Mappers.cs` (`ToStatusDto` — the logic to move) diff --git a/docs/project/backlog/WP-69-intake-scholing-threshold-enforcement.md b/docs/project/archive/backlog/WP-69-intake-scholing-threshold-enforcement.md similarity index 99% rename from docs/project/backlog/WP-69-intake-scholing-threshold-enforcement.md rename to docs/project/archive/backlog/WP-69-intake-scholing-threshold-enforcement.md index 282c1d5..211764c 100644 --- a/docs/project/backlog/WP-69-intake-scholing-threshold-enforcement.md +++ b/docs/project/archive/backlog/WP-69-intake-scholing-threshold-enforcement.md @@ -39,7 +39,7 @@ re-validates as authority) is unenforced for the one rule it was written to illu - `backend/src/BigRegister.Api/Domain/Intake/IntakePolicy.cs` (the corrected doc-comment, WP-68) -- [ADR-0001 — BFF-lite + decision DTOs](../../reference/architecture/0001-bff-lite-decision-dtos.md) +- [ADR-0001 — BFF-lite + decision DTOs](../../../reference/architecture/0001-bff-lite-decision-dtos.md) §"config value" - `apps/ssp/src/app/herregistratie/domain/intake.machine.ts` (`lageUren`, `scholingGevolgd`, `punten` — the wizard's existing FE-side rule and its answers) diff --git a/docs/project/backlog/WP-70-test-data-builders.md b/docs/project/archive/backlog/WP-70-test-data-builders.md similarity index 100% rename from docs/project/backlog/WP-70-test-data-builders.md rename to docs/project/archive/backlog/WP-70-test-data-builders.md diff --git a/docs/project/backlog/WP-71-test-framework-coherence.md b/docs/project/archive/backlog/WP-71-test-framework-coherence.md similarity index 100% rename from docs/project/backlog/WP-71-test-framework-coherence.md rename to docs/project/archive/backlog/WP-71-test-framework-coherence.md diff --git a/docs/project/backlog/WP-72-delete-legacy-submit-endpoints.md b/docs/project/archive/backlog/WP-72-delete-legacy-submit-endpoints.md similarity index 100% rename from docs/project/backlog/WP-72-delete-legacy-submit-endpoints.md rename to docs/project/archive/backlog/WP-72-delete-legacy-submit-endpoints.md diff --git a/docs/project/backlog/WP-73-domain-unions.md b/docs/project/archive/backlog/WP-73-domain-unions.md similarity index 100% rename from docs/project/backlog/WP-73-domain-unions.md rename to docs/project/archive/backlog/WP-73-domain-unions.md diff --git a/docs/project/backlog/WP-74-e2e-isolation.md b/docs/project/archive/backlog/WP-74-e2e-isolation.md similarity index 100% rename from docs/project/backlog/WP-74-e2e-isolation.md rename to docs/project/archive/backlog/WP-74-e2e-isolation.md diff --git a/docs/project/backlog/WP-75-fe-be-seam-closure.md b/docs/project/archive/backlog/WP-75-fe-be-seam-closure.md similarity index 100% rename from docs/project/backlog/WP-75-fe-be-seam-closure.md rename to docs/project/archive/backlog/WP-75-fe-be-seam-closure.md diff --git a/docs/project/refactor-backlog-setup/README.md b/docs/project/archive/refactor-backlog-setup/README.md similarity index 100% rename from docs/project/refactor-backlog-setup/README.md rename to docs/project/archive/refactor-backlog-setup/README.md diff --git a/docs/project/refactor-backlog-setup/agents/00-baseline.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/00-baseline.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/00-baseline.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/00-baseline.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/01-readability.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/01-readability.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/01-readability.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/01-readability.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/02-testability.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/02-testability.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/02-testability.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/02-testability.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/03-ddd-hexagonal.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/03-ddd-hexagonal.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/03-ddd-hexagonal.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/03-ddd-hexagonal.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/04-cqrs-light.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/04-cqrs-light.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/04-cqrs-light.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/04-cqrs-light.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/05-bdd.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/05-bdd.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/05-bdd.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/05-bdd.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/06-adr-conformance.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/06-adr-conformance.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/06-adr-conformance.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/06-adr-conformance.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/07-bio2-compliance.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/07-bio2-compliance.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/07-bio2-compliance.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/07-bio2-compliance.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/08-consolidation.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/08-consolidation.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/08-consolidation.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/08-consolidation.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/09-implementation.prompt.md b/docs/project/archive/refactor-backlog-setup/agents/09-implementation.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/09-implementation.prompt.md rename to docs/project/archive/refactor-backlog-setup/agents/09-implementation.prompt.md diff --git a/docs/project/refactor-backlog-setup/agents/_persistence-protocol.md b/docs/project/archive/refactor-backlog-setup/agents/_persistence-protocol.md similarity index 100% rename from docs/project/refactor-backlog-setup/agents/_persistence-protocol.md rename to docs/project/archive/refactor-backlog-setup/agents/_persistence-protocol.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/00-baseline.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/00-baseline.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/00-baseline.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/00-baseline.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/01-readability.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/01-readability.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/01-readability.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/01-readability.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/02-testability.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/02-testability.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/02-testability.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/02-testability.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/03-ddd-hexagonal.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/03-ddd-hexagonal.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/03-ddd-hexagonal.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/03-ddd-hexagonal.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/04-cqrs-light.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/04-cqrs-light.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/04-cqrs-light.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/04-cqrs-light.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/05-bdd.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/05-bdd.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/05-bdd.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/05-bdd.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/06-adr-conformance.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/06-adr-conformance.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/06-adr-conformance.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/06-adr-conformance.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/07-bio2-compliance.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/07-bio2-compliance.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/07-bio2-compliance.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/07-bio2-compliance.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/99-backlog.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/99-backlog.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/99-backlog.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/99-backlog.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/_status.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/_status.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/_status.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/_status.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/00-baseline.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/00-baseline.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/00-baseline.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/00-baseline.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/01-readability.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/01-readability.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/01-readability.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/01-readability.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/02-testability.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/02-testability.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/02-testability.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/02-testability.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/03-ddd-hexagonal.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/03-ddd-hexagonal.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/03-ddd-hexagonal.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/03-ddd-hexagonal.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/04-cqrs-light.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/04-cqrs-light.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/04-cqrs-light.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/04-cqrs-light.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/05-bdd.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/05-bdd.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/05-bdd.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/05-bdd.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/06-adr-conformance.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/06-adr-conformance.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/06-adr-conformance.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/06-adr-conformance.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/07-bio2-compliance.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/07-bio2-compliance.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/07-bio2-compliance.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/07-bio2-compliance.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/08-consolidation.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/08-consolidation.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/08-consolidation.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/08-consolidation.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/09-implementation.prompt.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/09-implementation.prompt.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/final-prompts/09-implementation.prompt.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/final-prompts/09-implementation.prompt.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-001.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-001.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-001.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-001.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-003.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-003.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-003.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-003.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-006.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-006.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-006.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-006.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-007.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-007.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-007.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-007.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-009.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-009.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/adr-c-009.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/adr-c-009.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-01.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-01.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-01.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-01.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-02.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-02.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-02.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-02.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-03.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-03.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-03.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-03.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-04.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-04.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-04.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-04.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-05.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-05.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-05.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-05.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-06.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-06.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-06.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-06.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-07.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-07.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-07.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-07.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-08.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-08.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-08.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-08.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-09.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-09.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-09.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-09.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-10.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-10.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-10.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-10.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-11.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-11.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-11.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-11.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-12.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-12.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-12.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-12.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-13.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-13.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-13.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-13.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-14.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-14.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-14.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-14.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-15.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-15.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-15.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-15.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-16.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-16.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-16.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-16.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-17.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-17.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-17.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-17.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-18.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-18.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-18.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-18.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-19.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-19.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-19.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-19.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-20.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-20.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-20.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-20.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-21.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-21.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-21.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-21.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-22.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-22.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-22.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-22.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-23.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-23.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-23.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-23.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-24.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-24.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-24.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-24.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-25.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-25.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-25.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-25.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-26.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-26.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-26.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-26.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-27.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-27.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-27.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-27.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-28.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-28.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-28.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-28.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-29.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-29.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-29.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-29.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-30.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-30.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-30.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-30.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-31.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-31.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-31.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-31.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-32.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-32.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-32.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-32.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-33.md b/docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-33.md similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/implementation/rb-33.md rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/implementation/rb-33.md diff --git a/docs/project/refactor-backlog-setup/refactor-backlog/tools/baseline-scan.mjs b/docs/project/archive/refactor-backlog-setup/refactor-backlog/tools/baseline-scan.mjs similarity index 100% rename from docs/project/refactor-backlog-setup/refactor-backlog/tools/baseline-scan.mjs rename to docs/project/archive/refactor-backlog-setup/refactor-backlog/tools/baseline-scan.mjs diff --git a/docs/project/refactor-backlog-setup/setup.sh b/docs/project/archive/refactor-backlog-setup/setup.sh similarity index 100% rename from docs/project/refactor-backlog-setup/setup.sh rename to docs/project/archive/refactor-backlog-setup/setup.sh diff --git a/docs/project/readable-codebase/PLAN.md b/docs/project/readable-codebase/PLAN.md index 5e9af3d..8ad361c 100644 --- a/docs/project/readable-codebase/PLAN.md +++ b/docs/project/readable-codebase/PLAN.md @@ -49,7 +49,7 @@ ticket converts it into the artifact this repo already uses for exactly this. ### Reuse the existing protocol, do not invent one -`docs/project/backlog/README.md` is a proven mechanism — 75 work packages driven to `done` +`docs/project/archive/backlog/README.md` is a proven mechanism — 75 work packages driven to `done` through it, and its own notes say the tickets are _"self-contained (each WP file carries its own current-state handoff) and sized for a fresh Sonnet session."_ Copy it wholesale: @@ -61,7 +61,7 @@ own current-state handoff) and sized for a fresh Sonnet session."_ Copy it whole - **A runnable GREEN one-liner** as the global definition of done. New home: **`docs/project/readable-codebase/`**, prefix **`RD-NN`**. It must not extend -`docs/project/backlog/`, because Phase 5 archives that directory — a finished arc gets +`docs/project/archive/backlog/`, because Phase 5 archives that directory — a finished arc gets archived, a new arc gets its own folder. `RD-` also avoids collision with the existing `WP-`/`RB-` prefixes, which matters because Phase 2 greps for those. diff --git a/docs/project/readable-codebase/RD-19-ticket-refs-backend.md b/docs/project/readable-codebase/RD-19-ticket-refs-backend.md index 5caba89..55aae1f 100644 --- a/docs/project/readable-codebase/RD-19-ticket-refs-backend.md +++ b/docs/project/readable-codebase/RD-19-ticket-refs-backend.md @@ -33,10 +33,10 @@ Strip the reference, keep the sentence. No behaviour changes. **Corrected after the ticket ran.** The original text said "nothing is exempt", and it was wrong. Two references are part of a path to a document that still exists: - | Site | Reference | - | ---------------------------------- | --------------------------------------------------- | - | `backend/README.md:18` | `docs/project/backlog/WP-22-durable-persistence.md` | - | `Domain/Letters/LetterHtml.cs:153` | `docs/project/backlog/WP-25-letter-preview-html.md` | + | Site | Reference | + | ---------------------------------- | ----------------------------------------------------------- | + | `backend/README.md:18` | `docs/project/archive/backlog/WP-22-durable-persistence.md` | + | `Domain/Letters/LetterHtml.cs:153` | `docs/project/archive/backlog/WP-25-letter-preview-html.md` | RD-18 exempted this same class of reference (`a11y.mdx:68`). A path that resolves is a pointer, not provenance. Stripping the number breaks the path, and describing the file in diff --git a/docs/project/readable-codebase/RD-30-archive-finished-backlogs.md b/docs/project/readable-codebase/RD-30-archive-finished-backlogs.md new file mode 100644 index 0000000..b391835 --- /dev/null +++ b/docs/project/readable-codebase/RD-30-archive-finished-backlogs.md @@ -0,0 +1,119 @@ +# RD-30 — Archive the finished backlogs + +Status: done +Phase: 5 — fix the docs that describe this flow + +## Why + +Two backlog trees are complete. `docs/project/backlog/` holds 74 work packages, and every one +reads `Status: done` (verified with `grep -L '^Status: done' docs/project/backlog/WP-*.md`, +which returns nothing). `docs/project/refactor-backlog-setup/` is the arc before it. + +Together they are 16,300 of the docs tree's 20,317 lines. A reader who opens `docs/project/` +to find the active plan meets two finished ones first. Move them out of the way. Git keeps the +history; the files stay readable at their new path. + +## Read first + +- `docs/project/readable-codebase/PLAN.md`, phase 5 item 1 (line 818). +- `docs/project/backlog/README.md` — the WP process and template. Two skills point at it, so it + survives the move as a live reference, not as dead paper. + +## Decisions (pre-made, do not relitigate) + +1. **`git mv`, not delete.** `docs/project/backlog/` → `docs/project/archive/backlog/`, and + `docs/project/refactor-backlog-setup/` → `docs/project/archive/refactor-backlog-setup/`. + Rename with `git mv` so `git log --follow` still works. +2. **`docs/project/SHOWCASE-ROADMAP.md` moves too.** Its whole body is a pointer at + `backlog/README.md`, through a **relative** link that this move breaks. It is superseded by + a document that is now archived, so it belongs beside it, at + `docs/project/archive/SHOWCASE-ROADMAP.md`. Fix its link to `backlog/README.md` in place. +3. **`docs/project/prd/` stays.** PRDs describe what the product does, not which tickets ran. + They are reference material, not a finished plan. +4. **Add `docs/project/archive/README.md`, about 15 lines.** State three facts: these trees are + historical, every ticket in them is done, and git holds the rest. Name what is still live — + `docs/project/readable-codebase/` and `docs/project/prd/`. Do not summarise 74 work packages. +5. **Repoint every inbound reference.** They are few and they are known (see Files). A link + into an archived document is fine; a link into a path that no longer exists is not. +6. **The `backlog/README.md` WP template stays the canonical template.** The + `document-feature` skill and `new-ssp` skill both cite it. Repoint them to the archive path; + do not copy the template to a second home. + +## Files + +The move: + +- `docs/project/backlog/` → `docs/project/archive/backlog/` (75 files). +- `docs/project/refactor-backlog-setup/` → `docs/project/archive/refactor-backlog-setup/`. +- `docs/project/SHOWCASE-ROADMAP.md` → `docs/project/archive/SHOWCASE-ROADMAP.md`. +- New: `docs/project/archive/README.md`. + +The inbound references, all of them: + +| File | Line | What it cites | +| ------------------------------------------------------------- | ---------- | ---------------------------------- | +| `CLAUDE.md` | 15, 75 | WP-22, and the WP session protocol | +| `README.md` | 69 | the backlog README, "pick up work" | +| `backend/README.md` | 18 | WP-22 | +| `backend/src/BigRegister.Api/Domain/Letters/LetterHtml.cs` | 155 | WP-25 | +| `libs/shared/docs/a11y.mdx` | 68 | WP-13's marker convention | +| `.claude/skills/document-feature/SKILL.md` | 23, 24, 27 | the WP path, template and index | +| `.claude/skills/new-ssp/SKILL.md` | 88, 89 | what to strip for a new portal | +| `docs/project/readable-codebase/PLAN.md` | 52, 64 | the backlog as a proven mechanism | +| `docs/project/readable-codebase/README.md` | 148 | the RD-37-before-RD-30 note | +| `docs/project/readable-codebase/RD-19-ticket-refs-backend.md` | 2 refs | a finished ticket's own record | + +`RD-19` is a shipped ticket record. Repoint it like the rest; do not rewrite its prose. + +RD-37 already removed the five story references that used to be in this list. Run the grep +again after the move to prove the set is empty: + +```bash +grep -rn "docs/project/backlog\|docs/project/refactor-backlog-setup" \ + --include='*.md' --include='*.mdx' --include='*.ts' --include='*.cs' . \ + | grep -v node_modules | grep -v docs/project/archive/ +``` + +## Steps + +1. `git mv` the two trees and `SHOWCASE-ROADMAP.md` under `docs/project/archive/`. +2. Write `docs/project/archive/README.md`. +3. Repoint every reference in the table. Add `archive/` to the path; change nothing else. +4. Fix the relative link inside `SHOWCASE-ROADMAP.md`. +5. Run the grep above. It must return nothing outside `docs/project/archive/`. +6. `npm run ci`. + +## Acceptance criteria + +- [x] `docs/project/` holds `archive/`, `prd/` and `readable-codebase/`, nothing else. +- [x] The grep above returns no hit outside `docs/project/archive/`, other than this ticket's + own prose and `PLAN.md:818` describing the pre-move path as the source of the `git mv` + that produced it — not a broken reference. +- [x] `docs/project/archive/README.md` exists and is 20 lines or fewer. +- [x] `git log --follow docs/project/archive/backlog/WP-01-axe-ci-gate.md` shows the history + from before the move. +- [x] `npm run ci` is green. + +## Verification + +1. `npm run ci` — the format check covers the moved Markdown. +2. Open `README.md`'s "pick up work" row and follow the link. It must resolve. +3. `grep -rn "](.*backlog" docs/project/archive/backlog/README.md | head` — the relative links + inside the moved tree still point at siblings, so they survive the move. Spot-check two. + +## Out of scope + +- Deleting anything. This ticket moves files. +- `docs/project/prd/`. +- Summarising or rewriting any archived document. + +## Risks + +1. **Relative links inside the moved trees.** A WP file that links to a sibling still works. A + WP file that links **upward** (`../../reference/...`) gains one level and breaks. Grep the + moved trees for `](../` and check the depth. +2. **`--full` is not needed, but the a11y MDX is touched.** `libs/shared/docs/a11y.mdx` is a + Storybook doc page. Editing one line of prose cannot break its imports, so plain + `npm run ci` is enough here. Do not skip it on that reasoning if you touch an import. +3. **The skills are agent-facing.** A wrong path in `.claude/skills/` misleads a future agent + silently, because nothing checks those files. Repoint them carefully. 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/RD-32-fp-tea-paths.md b/docs/project/readable-codebase/RD-32-fp-tea-paths.md new file mode 100644 index 0000000..09b6f22 --- /dev/null +++ b/docs/project/readable-codebase/RD-32-fp-tea-paths.md @@ -0,0 +1,106 @@ +# RD-32 — `fp-tea-atomic-design.md` cites the pre-monorepo tree + +Status: done +Phase: 5 — fix the docs that describe this flow + +## Why + +`docs/reference/fp-tea-atomic-design.md` is the learning guide. CLAUDE.md names it as one of +the three documents that hold the _why_. It still addresses the tree from before the monorepo +(WP-67): every path starts `src/app/`, which no directory has done since that work landed. + +A reader learning the codebase from this guide cannot open a single file it names. The prose is +correct; only the addresses are wrong. + +## Read first + +- `docs/project/readable-codebase/PLAN.md`, phase 5 item 3 (line 833). +- `docs/reference/fp-tea-atomic-design.md` — the whole file. + +## Decisions (pre-made, do not relitigate) + +1. **Two mapping rules cover all 11 paths.** A context path becomes + `apps/ssp/src/app//…`. A `shared` path becomes `libs/shared/src/…` — note that + `app/shared/` collapses to `libs/shared/src/`, it does not become `libs/shared/src/app/`. +2. **Follow the file's own precedent.** Line 338 already reads + `libs/shared/src/application/store.ts`. Line 223 names the same file the old way. Make 223 + match 338, not the reverse. +3. **Fix the broken anchor at line 435.** It reads + `#1-the-big-picture-three-contexts-four-layers`. The heading is now "1. The big picture: two + apps, cross-app libraries, "contexts", "layers"", so the anchor is + `#1-the-big-picture-two-apps-cross-app-libraries-contexts-layers`. +4. **Correct line 513's "Where" guidance.** It says `shared/ui/`. After RD-27 a shared block + lands in `libs/shared/src/ui//`. Name the layer folder; the whole + point of RD-27 is that the folder is the layer. +5. **Change addresses only.** Do not rewrite the teaching. This guide's prose survived the + refactor because it teaches ideas, not file layout. + +## The facts, measured against the current tree + +All 11 occurrences of `src/app/`, and where each file lives now: + +| Line | Cited | Actual | +| -------- | --------------------------------------------------------- | ------------------------------------------------------------------ | +| 72 | `src/app/registratie/domain/value-objects/uren.ts` | `apps/ssp/src/app/registratie/domain/value-objects/uren.ts` | +| 98, 255 | `src/app/herregistratie/domain/herregistratie.machine.ts` | `apps/ssp/src/app/herregistratie/domain/herregistratie.machine.ts` | +| 223 | `src/app/shared/application/store.ts` | `libs/shared/src/application/store.ts` | +| 299 | `src/app/shared/kernel/fp.ts` | `libs/shared/src/kernel/fp.ts` | +| 305 | `src/app/herregistratie/ui/herregistratie-wizard/…` | `apps/ssp/src/app/herregistratie/ui/herregistratie-wizard/…` | +| 381 | `src/app/showcase/concepts.page.ts` | `apps/ssp/src/app/showcase/concepts.page.ts` | +| 388 | `src/app/shared/infrastructure/scenario.ts` | `libs/shared/src/infrastructure/scenario.ts` | +| 414, 523 | `src/app/registratie/ui/address-fields/…` | `apps/ssp/src/app/registratie/ui/address-fields/…` | +| 588 | `src/app/herregistratie/domain/intake.machine.ts` | `apps/ssp/src/app/herregistratie/domain/intake.machine.ts` | + +Every target exists. This is a rename, not a hunt. + +**One correction to `PLAN.md`.** It says one path points at a deleted file, +`submit-herregistratie.ts`. That reference is no longer in the document — +`grep -n submit-herregistratie docs/reference/fp-tea-atomic-design.md` returns nothing. Do not +go looking for it. Record the correction in the ticket; leave `PLAN.md` itself alone, because +it is a design record of what was true when it was written. + +Line 523 sits inside a code comment, not prose. Update it anyway; a stale path in an example is +read as a real path. + +## Files + +- `docs/reference/fp-tea-atomic-design.md`. + +## Steps + +1. Rewrite the 11 paths per the table. +2. Fix the anchor at line 435. +3. Fix the "Where" guidance at line 513. +4. `grep -n "src/app/" docs/reference/fp-tea-atomic-design.md` — every remaining hit must start + `apps/ssp/src/app/`. +5. `npm run ci`. + +## Acceptance criteria + +- [x] No path in the file starts with a bare `src/app/`. +- [x] Every cited path resolves. Verify each with `ls`. +- [x] The §1 anchor matches the current heading. +- [x] `npm run ci` is green. + +## Verification + +1. `npm run ci` — the format check covers the file. +2. `grep -oE '\`[^\`]_src/[^\`]_\.ts\`' docs/reference/fp-tea-atomic-design.md | tr -d '\`' | + sort -u | xargs ls` — every path must resolve, with no error. +3. Open `ARCHITECTURE.md` and confirm the §1 heading text still produces the anchor you wrote. + The slug is the heading in lower case, with punctuation removed and spaces turned into + hyphens. + +## Out of scope + +- `ARCHITECTURE.md`. RD-31 owns it. +- CLAUDE.md and `atomic-design.mdx`. RD-33 owns them. +- The teaching content, the diagrams, and the code examples. + +## Risks + +1. **`app/shared/` is not `libs/shared/src/app/`.** The `app` segment disappears for the + library. Getting this wrong produces a path that looks right and resolves to nothing. +2. **The anchor is easy to half-fix.** GitHub drops the quotation marks around "contexts" and + "layers" and the colon, and turns each space into one hyphen. Verify by clicking, not by + reasoning. diff --git a/docs/project/readable-codebase/RD-33-claude-md-and-mdx.md b/docs/project/readable-codebase/RD-33-claude-md-and-mdx.md new file mode 100644 index 0000000..ff49f20 --- /dev/null +++ b/docs/project/readable-codebase/RD-33-claude-md-and-mdx.md @@ -0,0 +1,109 @@ +# RD-33 — CLAUDE.md, `atomic-design.mdx` and the `ui-component` skill + +Status: done +Phase: 5 — fix the docs that describe this flow + +## Why + +This arc added a context, a lint rule and a component contract. Three agent-facing documents +still describe the app as it was before. + +CLAUDE.md is the file every agent reads first. It does not name the `overzicht` context that +RD-03 created, and it does not name the `max-lines` budget that RD-02 enforces. An agent that +follows it writes a 400-line page into the wrong context and meets a red build it was never +warned about. + +`atomic-design.mdx` credits `eslint.config.mjs` with the layer rules. Dependency-cruiser +enforces them. Crediting the wrong tool sends the next reader to the wrong file. + +## Read first + +- `docs/project/readable-codebase/PLAN.md` §3c (line 604, the step contract), §4a (line 721, + the layer move) and phase 5 items 4 and 5 (line 837). +- `CLAUDE.md` — sections "1. DDD", "2. Atomic design", "5. Testing" and "Enforced, not just + hoped-for". +- `libs/shared/docs/atomic-design.mdx:60`, `libs/shared/docs/layers.mdx:41-45`. +- `.claude/skills/ui-component/SKILL.md`. + +## Decisions (pre-made, do not relitigate) + +1. **CLAUDE.md gains `overzicht` in three places.** The context list in section 1, the alias + list (`@overzicht/*`, which `apps/ssp/tsconfig.json:9` already declares), and the + cross-context arrow. The rule in `.dependency-cruiser.ssp.js:8` is `overzicht: ['registratie']`, + so the arrow is `overzicht → registratie → libs/shared|beheer`. +2. **CLAUDE.md gains the `max-lines` budget** under "Enforced, not just hoped-for", stated as + the rule states it: 250 lines, `skipBlankLines` and `skipComments`, over + `{apps,libs}/**/*.{page,component,section,step}.ts` (`eslint.config.mjs:64-68`). Say that + 250 is reachable, not a style-guide default — the dashboard page is 42 lines. +3. **CLAUDE.md gains the step-component contract**, in section 2 beside the atomic rules. Three + clauses, from PLAN §3c: inputs down, one narrow output up, and `dispatch` is never passed + down. Add the corollary: a step gets **no** story of its own, because the wizard's story + already mounts it by seeding the machine. +4. **The `libs/beheer` title rule is already in CLAUDE.md.** RD-28 landed it. Verify the + sentence is there and correct; do not write it a second time. +5. **`atomic-design.mdx:60` names the wrong tool.** The layer rules are dependency-cruiser + (`npm run dep:check`, `.dependency-cruiser.base.js` plus one file per app). ESLint owns the + `any` ban and `max-lines`. Name each tool for what it actually does. +6. **`atomic-design.mdx` gains the step contract and the layer table**, so the Storybook reader + and the CLAUDE.md reader get the same rule. The table is the shape RD-27 produced: + `libs/shared/src/ui/atoms|molecules|organisms/` and `libs/shared/src/layout/`, with the note + that `layout/` deliberately holds several layers. +7. **`layers.mdx` is missing the `overzicht` arrow.** Its list at lines 41-45 predates RD-03. + Add the same arrow as decision 1. This is one line, in the same commit, because the two + documents state the same rule and must not disagree. +8. **The `ui-component` skill's example paths are pre-monorepo.** Lines 44-46 read + `src/app/shared/ui/button/`, `src/app/shared/ui/async/` and `src/app/shared/layout/wizard-shell/`. + They are now `libs/shared/src/ui/atoms/button/`, `libs/shared/src/ui/molecules/async/` and + `libs/shared/src/layout/wizard-shell/`. Lines 8, 13 and 24 say `shared/ui/` where the folder + is now the layer — name the layer folder, because that is the whole point of RD-27. +9. **CLAUDE.md:153 and CLAUDE.md:259 carry the same stale-path defect.** Both cite + `libs/shared/src/ui/async`, which RD-27 moved to `libs/shared/src/ui/molecules/async`. Fix + both in this commit, alongside decision 8's identical fix in the skill file. + +## Files + +- `CLAUDE.md` +- `libs/shared/docs/atomic-design.mdx` +- `libs/shared/docs/layers.mdx` +- `.claude/skills/ui-component/SKILL.md` + +## Steps + +1. CLAUDE.md: decisions 1, 2, 3, and the check in decision 4. +2. `atomic-design.mdx`: decisions 5 and 6. +3. `layers.mdx`: decision 7. +4. `.claude/skills/ui-component/SKILL.md`: decision 8. +5. `npm run ci --full`. + +## Acceptance criteria + +- [x] `grep -n overzicht CLAUDE.md` returns the context, the alias and the arrow. +- [x] `grep -n max-lines CLAUDE.md` returns the budget, with the glob and the two skip options. +- [x] CLAUDE.md states the step contract and the "no story for a step" corollary. +- [x] No document credits `eslint.config.mjs` with the layer rules. +- [x] Every path in `.claude/skills/ui-component/SKILL.md` resolves. +- [x] `npm run ci --full` is green. + +## Verification + +1. `npm run ci --full`. This ticket edits two `.mdx` files, and only `build-storybook` catches + a broken MDX import. Plain `npm run ci` does not build Storybook. +2. `npm run storybook` — open Foundations, Atomic design and Layers. Both pages render, and the + new table is readable at a narrow width. +3. `grep -oE '\`[^\`]_(apps|libs)/[^\`]_\`' .claude/skills/ui-component/SKILL.md | tr -d '\`' | + xargs ls -d` — every path resolves. + +## Out of scope + +- `ARCHITECTURE.md` (RD-31) and `fp-tea-atomic-design.md` (RD-32). +- The other skills in `.claude/skills/`. Only `ui-component` carries stale layer paths. +- Renaming `ui/dashboard/`. RD-36 owns that, and it runs after this ticket. + +## Risks + +1. **A broken MDX import passes `npm run ci` and fails CI.** This is PLAN risk 7. Run `--full`. +2. **CLAUDE.md is long, and a rule added in the wrong section is a rule nobody finds.** Put + each addition in the section that already owns its subject: contexts in 1, the step contract + in 2, the lint budget in "Enforced, not just hoped-for". +3. **Two documents, one rule.** `layers.mdx` and CLAUDE.md both state the cross-context arrows. + Write the same arrow in both, or the next reader gets to choose which one to believe. diff --git a/docs/project/readable-codebase/RD-36-overzicht-secties.md b/docs/project/readable-codebase/RD-36-overzicht-secties.md new file mode 100644 index 0000000..759ac58 --- /dev/null +++ b/docs/project/readable-codebase/RD-36-overzicht-secties.md @@ -0,0 +1,114 @@ +# RD-36 — `ui/dashboard/` becomes `ui/overzicht-secties/` + +Status: done +Phase: 5 — fix the docs that describe this flow + +## Why + +RD-03 moved the dashboard page to `overzicht/ui/overzicht.page.ts` and left four data sections +in `registratie/ui/dashboard/`. The folder is now named after a page that lives somewhere else. +A reader who opens `registratie/ui/dashboard/` finds four sections that are not the dashboard, +and the page it is named for is in another context. + +RD-04 recorded the name as stale and left it. This ticket fixes it. + +## Read first + +- `docs/project/readable-codebase/PLAN.md:267-282` — the decision and its measured cost. +- `apps/ssp/src/app/overzicht/ui/overzicht.page.ts` — the only importer. + +## Decisions (pre-made, do not relitigate) + +1. **The new name is `overzicht-secties/`.** It says what the four files are: registratie's + sections for the overzicht page. It keeps the Dutch that CLAUDE.md requires of a domain + context. +2. **Flattening into `registratie/ui/` is rejected.** That directory holds one folder per + component. Eight loose files would break its shape. +3. **The alias does not change.** The four sections stay in the `registratie` context, so the + imports stay `@registratie/ui/…`. Only the folder segment changes. +4. **Story titles do not change.** They are `Domein/Registratie/`, which is a context + name, not a folder name. Both Storybook globs are recursive, so no config changes. +5. **Fold in the two stale `dashboard.page` paths named in PLAN.** `docs/reference/feature-flags.md:55` + and `.claude/skills/new-ssp/SKILL.md:65` both cite `registratie/ui/dashboard.page`, a file + that no longer exists. The flag logic they describe lives in + `apps/ssp/src/app/overzicht/ui/wat-wilt-u-doen.section.ts` now. +6. **Fix the other live citations of the deleted file too.** Same defect, same commit: + `docs/reference/architecture/ARCHITECTURE.md:55` (the pages node in the Mermaid diagram) and + `:79` (the `ui/` row of the layer table), and `libs/shared/docs/remote-data.mdx:64`. Each + names `dashboard.page.ts` as a live example. The current name is `overzicht.page.ts`. +7. **Leave `docs/project/archive/` and the shipped RD ticket records alone.** They describe the + tree as it was when they ran. A historical record that cites a path from its own time is + correct, not stale. + +## Files + +The move — 8 files, `git mv` the directory: + +`apps/ssp/src/app/registratie/ui/dashboard/` → `apps/ssp/src/app/registratie/ui/overzicht-secties/` + +``` +mijn-aanvragen.section.ts mijn-aanvragen.section.stories.ts +mijn-registratie.section.ts mijn-registratie.section.stories.ts +specialismen.section.ts specialismen.section.stories.ts +wat-moet-ik-regelen.section.ts wat-moet-ik-regelen.section.stories.ts +``` + +The importer — one file, four import lines plus one comment: + +- `apps/ssp/src/app/overzicht/ui/overzicht.page.ts:3-6`, and the comment at line 12 that says + "four sections stay in `registratie/ui/dashboard/`". + +**RD-31 added two more.** Its rewrite of `ARCHITECTURE.md` §6a links the read walkthrough to +`registratie/ui/dashboard/mijn-registratie.section.ts` and +`registratie/ui/dashboard/wat-moet-ik-regelen.section.ts` by full path. Both move here. Fix +them, or §6a's links break the day this ticket lands. + +The five doc citations: `docs/reference/feature-flags.md:55`, +`.claude/skills/new-ssp/SKILL.md:65`, `docs/reference/architecture/ARCHITECTURE.md:55` and `:79`, +`libs/shared/docs/remote-data.mdx:64`. + +## Steps + +1. `git mv` the directory. +2. Fix the four imports and the comment in `overzicht.page.ts`. +3. Fix the five doc citations per decisions 5 and 6. +4. `npm run ci --full`. + +## Acceptance criteria + +- [x] `apps/ssp/src/app/registratie/ui/dashboard/` no longer exists. +- [x] `grep -rn "ui/dashboard" apps libs docs/reference libs/shared/docs .claude` returns + nothing outside the `.xlf` extraction metadata named in Out of scope. +- [x] No live document cites `dashboard.page`. Historical records under + `docs/project/archive/` and the shipped `RD-*.md` files are exempt. +- [x] `git diff --stat -M` shows renames plus small edits, no rewritten files. +- [x] `npm run ci --full` is green. + +## Verification + +1. `npm run ci --full`. The four story files move, and only `build-storybook` proves that both + Storybook globs still pick them up. +2. `npm run storybook` — the four `Domein/Registratie/…` stories are still in the sidebar under + the same titles. +3. `npm start`, open `http://localhost:4200/dashboard`. All six sections render. + +## Out of scope + +- The `` metadata in `apps/*/src/locale/messages*.xlf`. + It still names `src/app/registratie/ui/dashboard.page.ts`, which RD-03 renamed. That + metadata comes from `ng extract-i18n` and no build reads it, so it is stale extraction + output from before RD-03, not a citation this ticket created. Regenerating it is its own + job. +- Renaming the `/dashboard` **route** to `/overzicht`. `PLAN.md` puts it under "Deliberately + out of scope": it needs a redirect and it is user-visible. +- Moving the four sections into the `overzicht` context. They read `BigProfileStore` and belong + to `registratie`; `overzicht` composes them. That is RD-03's decision and it stands. + +## Risks + +1. **A missed specifier fails the typecheck, not the build.** Run `npm run ci --full`, which + typechecks all four tsconfigs. +2. **`git mv` of a directory, then edits, can look like deletes and adds.** Commit the rename + and the edits together and check `git diff --stat -M` before you push. +3. **The route stays `/dashboard`.** Do not "tidy" it while renaming the folder. The folder name + and the URL are separate decisions, and only one of them is in this ticket. diff --git a/docs/project/readable-codebase/RD-37-a11y-suppressions.md b/docs/project/readable-codebase/RD-37-a11y-suppressions.md new file mode 100644 index 0000000..253e376 --- /dev/null +++ b/docs/project/readable-codebase/RD-37-a11y-suppressions.md @@ -0,0 +1,130 @@ +# RD-37 — Five a11y suppressions name a ticket that closed + +Status: done +Phase: 5 — fix the docs that describe this flow + +## Why + +Five stories carry `a11y: { disable: true }`. Four of the reasons say "WP-11 (CIBG markup +fidelity) reworks this markup". WP-11 is `Status: done`, and so is WP-13, the gap register that +WP-11 handed its remainder to. No open ticket owns the defect. The README rule — "no check +disabled without a reference to the ticket that removes it" — holds only in letter. + +RD-30 archives `docs/project/backlog/`. This ticket runs first, so the archive move does not +rewrite five paths that must disappear. + +The defect is shipped, not story-only. `app-choice-link` renders a component host between the +keuzelijst `
              ` and its `
            • `. This breaks the axe `list`/`listitem` rule for assistive +technology. `display: contents` does not repair it. + +## Read first + +- `docs/project/readable-codebase/PLAN.md`, phase 5 item 0 (line 790). +- `libs/shared/src/ui/molecules/choice-link/choice-link.component.ts` — the defect. +- `libs/shared/src/ui/molecules/application-link/application-link.component.ts:18` — the + precedent. WP-11 made the host **be** the `
            • `. That component is axe-clean today. +- `libs/shared/docs/atomic-design.mdx:113` — the convergence table row that calls the split + deliberate. + +## The question this ticket had to answer first + +Does an `li[…]` attribute host still match the vendored CIBG keuzelijst CSS? + +**Yes.** Verified against `public/cibg-huisstijl/css/huisstijl.css`. Every keuzelijst rule keys +off a bare class: + +``` +.keuzelijst__list{padding-left:0} +.keuzelijst__list-item{list-style:none;margin-bottom:1.5rem;position:relative} +.keuzelijst__link{…} +.keuzelijst__link:after{…} .keuzelijst__link:focus,.keuzelijst__link:hover{…} +``` + +There is no `ul > li` child combinator and no `li a` descendant chain. This is the difference +from the aanvragen pattern, whose vendored chain **is** `.dashboard-block.applications li a`. +An attribute host on the `
            • ` therefore keeps every keuzelijst selector matching, as long as +the class `keuzelijst__list-item` moves to the host element. + +## Decisions (pre-made, do not relitigate) + +1. **`choice-link` becomes `selector: 'li[app-choice-link]'`.** The host carries the class + through `host: { class: 'keuzelijst__list-item' }`. The template drops its outer `
            • `. + `:host { display: contents }` goes away, because the host is now the list item. +2. **Keep `position: relative` on `.keuzelijst__link`.** The title is a `.stretched-link`. Its + `::after` overlay must resolve against the card, not against the `
            • `. Do not move that + rule to the host. +3. **`aanvraag-block` needs no component change. Its suppression reason is wrong.** The + component renders a CIBG melding (`app-alert`), never an `
            • `. Only the story's meta + `render` wraps it in `
                `, and that wrapper is what axe rejects. + Production agrees: `mijn-aanvragen.section.ts:44` renders the block for `concepten_()` only, + outside any list. Delete the wrapper from the meta render. +4. **Delete the four non-Concept stories in `aanvraag-block.stories.ts`.** The whole template + sits inside `@if (aanvraag().status.tag === 'Concept')`, so `InBehandelingAuto`, + `InBehandelingManual`, `Goedgekeurd` and `Afgewezen` render nothing at all. Keep `Concept`, + and give it the meta render. Submitted and resolved aanvragen render through + `application-link`, which has its own stories. +5. **Correct `atomic-design.mdx:113`.** After this ticket both molecules **are** the `
              • `. + The pair stays separate because they bind different vendored patterns, not because of list + semantics. Rewrite that half of the cell; keep the verdict. +6. **All five suppressions go.** No suppression, no replacement ticket. If `ci --full` still + reports a violation, stop and report it. Do not re-add a disable. + +## Files + +- `libs/shared/src/ui/molecules/choice-link/choice-link.component.ts` — host, class, template, + the header comment. +- `libs/shared/src/ui/molecules/task-list/task-list.component.ts:25` — the one production call + site: `` becomes `
              • `. +- `libs/shared/src/ui/molecules/choice-link/choice-link.stories.ts` — call site + suppression. +- `libs/shared/src/ui/molecules/choice-list/choice-list.stories.ts` — call sites + suppression. +- `libs/shared/src/ui/molecules/task-list/task-list.stories.ts` — suppression. +- `apps/ssp/src/app/registratie/ui/dashboard/wat-moet-ik-regelen.section.stories.ts` — + suppression. +- `apps/ssp/src/app/registratie/ui/aanvraag-block/aanvraag-block.stories.ts` — wrapper, four + stories, suppression. +- `libs/shared/docs/atomic-design.mdx` — the convergence row. + +## Steps + +1. Convert `choice-link` to the `li[…]` host. +2. Update the one production call site and the two story templates. An attribute host needs a + closing tag: `
              • `, not a self-closing element. +3. Fix `aanvraag-block.stories.ts` per decisions 3 and 4. +4. Delete all five `a11y: { disable: true }` blocks and their comments. +5. Correct the `atomic-design.mdx` row. +6. Run `npm run ci --full`. + +## Acceptance criteria + +- [x] No `a11y: { disable: true }` remains in `apps/` or `libs/`. +- [x] `grep -rn "WP-11" apps libs` returns nothing that points at the archived backlog. +- [x] `npm run ci --full` is green, axe included. +- [x] The keuzelijst still looks unchanged: chevron, hover accent, focus accent, and the + non-interactive `--static` row. + +## Verification + +1. `npm run ci --full`. +2. `npm run storybook` — Choice Link, Choice List, Task List and Wat Moet Ik Regelen run with + the a11y addon on. Check the three Choice Link stories by eye: `Navigatie`, `Actie` and + `NietInteractief` must keep their current appearance. +3. `npm start`, open `http://localhost:4200/dashboard` — the "Wat moet ik regelen" list renders + as before, and each row is still clickable over its whole surface. + +## Out of scope + +- `application-link` and `application-list`. Both are already axe-clean. +- The `--static` modifier and the CIBG-gap register. This ticket moves a host element; it adds + no new hand-rolled surface. + +## Risks + +1. **A self-closing attribute host silently renders nothing.** Angular needs + `
              • `. The build does not fail; the row disappears. Check the + dashboard by eye, per Verification step 3. +2. **`stretched-link` covers the wrong box.** If `position: relative` lands on the host instead + of on `.keuzelijst__link`, the whole `
              • ` becomes the click target, including its + `margin-bottom`. Keep the rule where it is. +3. **The `choiceActions` slot must stay above the overlay.** It projects inside + `.keuzelijst__link` and relies on its own `position: relative; z-index: 2` at the call site. + The host move must not change the projection point. diff --git a/docs/project/readable-codebase/RD-39-seed-input-timing.md b/docs/project/readable-codebase/RD-39-seed-input-timing.md new file mode 100644 index 0000000..0f57bca --- /dev/null +++ b/docs/project/readable-codebase/RD-39-seed-input-timing.md @@ -0,0 +1,82 @@ +# RD-39 — The wizards' `seed` input never arrived + +Status: done +Source: found while planning the machine-wiring migration (ADR-0007 arc) + +## Why + +All three wizard containers read their `seed` input **in the constructor**: + +```ts +const seeded = this.seed(); // always the `initial` default +queueMicrotask(() => + seeded !== initial ? this.dispatch({ tag: 'Seed', state: seeded }) : this.draftSync.resume(), +); +``` + +Angular binds component inputs **after** the constructor runs. So `seeded` was +always the `initial` default, `seeded !== initial` was always false, and every +mount took the `draftSync.resume()` branch. The `seed` input was dead code. + +The two single-step forms built on the same idiom prove the diagnosis by +contrast. They read the input **inside** the microtask, and they work: + +``` +change-request-form.component.ts:191 queueMicrotask(() => this.dispatch({ tag: 'Seed', state: this.seed() })); +besluit-form.component.ts:176 queueMicrotask(() => this.dispatch({ tag: 'Seed', state: this.seed() })); +``` + +## Impact + +Every seeded wizard story rendered step 1 instead of the state it asked for — +21 stories across the three wizards. Storybook is this repo's UI test surface +(CLAUDE.md "Testing"), so the states that had no other coverage were exactly +the ones silently not rendering: `Submitting`, `Submitted`, `Failed`, +`Ingediend`, `Mislukt`. + +Nothing caught it. `.storybook-ssp/test-runner.ts` runs axe only — it checks +that whatever rendered is accessible, never that the right thing rendered. +`intake-wizard.component.spec.ts` had worked around it by calling +`componentInstance.dispatch(...)` instead of setting the input, which is the +shape of a test written against a broken input path. + +**Production was unaffected**: no route binds `seed`, so the resume branch was +always the correct one there. + +## Decisions + +1. **Read `seed()` inside the microtask**, matching the two forms. Six lines + across three files. The `if/else` replaces the ternary because the branches + are statements, not values. +2. **Keep the microtask.** It is what defers the dispatch past input binding. + The larger fix — `start(seed)` on an application store called from + `ngOnInit` — belongs to the ADR-0007 migration, not here. This ticket makes + the existing seam correct; it does not move it. +3. **Turn the workaround into the regression test.** + `intake-wizard.component.spec.ts` now mounts through + `componentRef.setInput('seed', …)` via a `mountSeeded` helper, and a new + `honours the seed input` case asserts the machine state directly. Both fail + on the old code, which is the point. +4. **Do not touch `draftSync.enabled`.** `enabled: () => this.seed() === +initial` reads the input lazily inside a lambda called from an effect, so it + was already correct. Changing the input to `| null` is part of ADR-0007. + +## Verification performed + +- `npx ng test ssp` with the intake fix reverted: **2 failed** (both new spec + cases). With the fix: **319 passed**. That differential is the proof. +- `npm run ci --full` green, including 112 storybook a11y tests. The newly + rendered markup (``, error alerts, ``) + produced **no** axe violations — the predicted a11y fallout did not happen. +- Browser check against the built Storybook, seven seeded stories across all + three wizards, each asserted to contain text only reachable from its seed + (`Netwerkfout` for `Failed`, `referentienummer` for `Ingediend`, `Documenten` + for step 3), plus a negative control that step 1 does **not** show step 3's + title. All seven pass. + +## Trap for the next person + +`Failed`, `Submitted`, `Ingediend` and `Mislukt` are unreachable without a +network submit, so they can only be produced by a seed. If a future change +breaks the input path again, those four stories silently fall back to step 1 +and axe still passes. The spec added here is the guard; keep it. diff --git a/docs/project/readable-codebase/README.md b/docs/project/readable-codebase/README.md index 773b4fd..57bac66 100644 --- a/docs/project/readable-codebase/README.md +++ b/docs/project/readable-codebase/README.md @@ -124,15 +124,16 @@ two. Note that RD-15 exists because 22 abandoned agent worktrees are still on di | RD-27 | **The layer move:** 33 `git mv` + 28 specifiers + 8 MDX imports | 21 | yes | done | | 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 | | todo | -| RD-31 | `ARCHITECTURE.md` section 6a: symbols not lines, 2 dead paths, new names | 03, 08, 16 | | todo | -| 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-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 | | done | +| RD-32 | `fp-tea-atomic-design.md`: 11 broken paths + the broken anchor | 27 | | done | +| RD-33 | CLAUDE.md + `atomic-design.mdx` + the `ui-component` skill | 03, 27, 29 | yes | done | | RD-34 | _(optional)_ `NO_SUBORGS`/`NO_TABLES` become `RemoteData.Empty` | 11 | | todo | | RD-35 | _(optional, last, alone)_ upload `type:` discriminant to `tag:` | 27 | | todo | -| RD-36 | `ui/dashboard/` → `ui/overzicht-secties/` + 2 stale `dashboard.page` paths | 04 | yes | todo | -| RD-37 | **a11y:** 5 suppressions name a closed ticket — decide the `li[…]` host | 01 | yes | todo | +| RD-36 | `ui/dashboard/` → `ui/overzicht-secties/` + 2 stale `dashboard.page` paths | 04 | yes | done | +| RD-37 | **a11y:** 5 suppressions name a closed ticket — decide the `li[…]` host | 01 | yes | done | | RD-38 | One member order for the 3 wizard containers + 2 pure extractions | 22, 23 | | done | +| RD-39 | **Bug:** the wizards' `seed` input never arrived (21 stories) | 38 | yes | done | The ID order already respects every dependency, so it is the recommended running order. @@ -144,7 +145,7 @@ four import lines, and it collides with nothing else in the table — RD-27's mo `libs/shared/src/ui/`. Pull it forward into any short session. It is numbered last only because it was added after RD-04 shipped. -**RD-37 must run before RD-30**, despite its number. RD-30 archives `docs/project/backlog/`, +**RD-37 must run before RD-30**, despite its number. RD-30 archives `docs/project/archive/backlog/`, and five of the paths it would have to rewrite point at `WP-11-markup-fidelity.md` from accessibility suppressions that RD-37 either deletes or re-aims. Doing RD-30 first means rewriting five paths that are about to change again — and enshrining a promise nobody owns. diff --git a/docs/reference/architecture/ARCHITECTURE.md b/docs/reference/architecture/ARCHITECTURE.md index e9186cb..be4ae91 100644 --- a/docs/reference/architecture/ARCHITECTURE.md +++ b/docs/reference/architecture/ARCHITECTURE.md @@ -52,7 +52,7 @@ ever uses the level(s) below it — so anything you build is reusable by everyth ```mermaid graph TD - P["Pages
                dashboard.page · login.page · intake.page"] + P["Pages
                overzicht.page · login.page · intake.page"] T["Templates
                page-shell · shell"] O["Organisms
                login-form · registration-table · intake-wizard"] M["Molecules
                form-field · data-row · async"] @@ -76,7 +76,7 @@ questions: | `application/` | How do we coordinate a task / state? | Yes (signals) | `big-profile.store.ts` | | `infrastructure/` | Where does data come from? | Yes (HTTP) | `big-register.adapter.ts`, `brp.adapter.ts` | | `contracts/` | What's the FE⇄BE wire shape? | **No** (pure DTOs) | `dashboard-view.dto.ts` | -| `ui/` | How does it look? | Yes (components) | `dashboard.page.ts` | +| `ui/` | How does it look? | Yes (components) | `overzicht.page.ts` | **The one rule that keeps it sane: dependencies only point _inward_.** UI may use application, application may use domain, everyone (in either app) may use `libs/shared` @@ -379,8 +379,8 @@ A common assumption is "the form saves on blur." It doesn't. **Blur only marks a _touched_** so validation can show; it never writes the value or hits the network. In the shared atoms, `(blur)="onTouched()"` is the `ControlValueAccessor` touched callback and nothing more; the value is pushed on `(input)`, every keystroke -([`text-input.component.ts`](../../../libs/shared/src/ui/text-input/text-input.component.ts): -`(input)` L29 → `onChange` L62, vs `(blur)="onTouched()"` L30). +([`text-input.component.ts`](../../../libs/shared/src/ui/atoms/text-input/text-input.component.ts): +`(input)="onInput($event)"` → `onInput` calls `onChange`, vs `(blur)="onTouched()"`). The real flow has two stages, neither keyed on focus: @@ -388,19 +388,20 @@ The real flow has two stages, neither keyed on focus: `{ tag: 'SetField', key, value }`. The pure reducer stores it immediately — so the Model is always current, on every keystroke, while editing. ([`herregistratie-wizard.component.ts`](../../../apps/ssp/src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts) - L78 → [`herregistratie.machine.ts`](../../../apps/ssp/src/app/herregistratie/domain/herregistratie.machine.ts) - L138-142, `setField`.) + (`(ngModelChange)="dispatch({ tag: 'SetField', … })"`) → + [`herregistratie.machine.ts`](../../../apps/ssp/src/app/herregistratie/domain/herregistratie.machine.ts), + `setField`.) 2. **Model → backend (600 ms debounce).** A signal `effect` tracks the machine `snapshot()`; each change resets a 600 ms timer whose callback does I/O **only** (it never dispatches, so it can't livelock the store). On the first save it lazily creates the application and stamps `?aanvraag=` into the URL, so a reload resumes the draft. ([`draft-sync.ts`](../../../apps/ssp/src/app/registratie/application/draft-sync.ts): - `DEBOUNCE_MS` L34, `effect` L102-108, `flush` L88-98 → `ApplicationsAdapter.syncDraft`.) + `DEBOUNCE_MS`, the `effect`, `flush` → `ApplicationsAdapter.syncDraft`.) The **brief** context uses the same 600 ms idiom in its own store: `edit()` applies the edit optimistically in the reducer and records an undo step, then `scheduleSave()` → `flushSave()` flips a `saveState` (Saving/Saved/Error) and calls `adapter.save` -([`brief.store.ts`](../../../apps/ssp/src/app/brief/application/brief.store.ts) L157-166, L192-209). +([`brief.store.ts`](../../../apps/ssp/src/app/brief/application/brief.store.ts): `scheduleSave`, `flushSave`). So it _feels_ like save-on-blur only because you usually stop typing when you leave a field, and the debounce fires ~600 ms later. The trigger is **"stopped changing," not @@ -571,27 +572,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/overzicht-secties/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/overzicht-secties/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 +611,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")`). --- diff --git a/docs/reference/feature-flags.md b/docs/reference/feature-flags.md index b8d521d..b721b29 100644 --- a/docs/reference/feature-flags.md +++ b/docs/reference/feature-flags.md @@ -52,7 +52,7 @@ Each UI consumer injects `FeatureFlagStore`, imports the flag-key constant, and its own gating predicate inline: - `shared/layout/site-header/site-header.component.ts` — filters the "Inschrijven" nav item. -- `registratie/ui/dashboard.page.ts` — hides the "Inschrijven" dashboard action. +- `overzicht/ui/wat-wilt-u-doen.section.ts` — hides the "Inschrijven" dashboard action. So a second flag with a second consumer **repeats the pattern by hand** — there's no shared "gate this thing by flag" abstraction. That's fine at one flag / two consumers (a helper for diff --git a/docs/reference/fp-tea-atomic-design.md b/docs/reference/fp-tea-atomic-design.md index 610e355..13214e5 100644 --- a/docs/reference/fp-tea-atomic-design.md +++ b/docs/reference/fp-tea-atomic-design.md @@ -69,7 +69,7 @@ add a b = a + b ``` In this app, the parsers and reducers are pure. For example -(`src/app/registratie/domain/value-objects/uren.ts`): +(`apps/ssp/src/app/registratie/domain/value-objects/uren.ts`): ```ts export function parseUren(raw: string): Result { @@ -95,7 +95,7 @@ copies the old fields and overrides one. ``` This app's reducers always return a fresh object — e.g. -`src/app/herregistratie/domain/herregistratie.machine.ts`: +`apps/ssp/src/app/herregistratie/domain/herregistratie.machine.ts`: ```ts export function setField(s: WizardState, key: keyof Draft, value: string): WizardState { @@ -220,7 +220,7 @@ store. Cross-page state that _must_ be shared lives in one root singleton ### 4a. The store — TEA's runtime in ~10 lines -`src/app/shared/application/store.ts`: +`libs/shared/src/application/store.ts`: ```ts export interface Store { @@ -252,7 +252,7 @@ to change it — it runs the pure `update` and `set`s the new value. ### 4b. Model + Msg + reduce Mapping the four TEA pieces to real code, using the herregistratie wizard (the smallest -machine) as the example — `src/app/herregistratie/domain/herregistratie.machine.ts`: +machine) as the example — `apps/ssp/src/app/herregistratie/domain/herregistratie.machine.ts`: - **Model** → `WizardState` (the discriminated union from §2d). - **Msg** → `WizardMsg`, every event as one union: @@ -296,13 +296,13 @@ export function reduce(s: WizardState, m: WizardMsg): WizardState { } ``` -`assertNever` (`src/app/shared/kernel/fp.ts`) makes the switch **exhaustive**: add a new +`assertNever` (`libs/shared/src/kernel/fp.ts`) makes the switch **exhaustive**: add a new `Msg` variant and forget to handle it, and the build fails. (`intake.machine.ts` and `registratie-wizard.machine.ts` have larger unions, same exact shape.) ### 4c. view → template + `computed()` + `dispatch` -The container component (`src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts`) +The container component (`apps/ssp/src/app/herregistratie/ui/herregistratie-wizard/herregistratie-wizard.component.ts`) creates the store and derives view values with `computed()`: ```ts @@ -378,14 +378,14 @@ doesn't loop on its own write — see the BRP prefill and policy-threshold effec Each wizard exposes `state` as a **read-only signal**, deliberately public so the teaching page can highlight the live state. See it on the in-app showcase -(`src/app/showcase/concepts.page.ts`, route `/concepts`): section 4 lights up the +(`apps/ssp/src/app/showcase/concepts.page.ts`, route `/concepts`): section 4 lights up the current `WizardState` among `Editing → Submitting → Submitted/Failed` as you drive the form, and section 5 shows the intake steps re-deriving as you type. > **Discrepancy with the PRD — open question.** The PRD refers to a dedicated "state > debug view" / inspector. **No such feature exists** in the code today. What exists is > the `/concepts` showcase (live state highlight) and the `?scenario=slow|loading|empty|error` -> interceptor (`src/app/shared/infrastructure/scenario.ts`) for exercising async states. +> interceptor (`libs/shared/src/infrastructure/scenario.ts`) for exercising async states. > A JSON state inspector _would be trivial here_ — single one-way state means you could > render `JSON.stringify(state())` in a panel and watch every transition — precisely > because of everything in Part 6. Treat building one as a future task, not documented @@ -411,7 +411,7 @@ In this codebase the form **atoms** (`text-input`, `radio-group`) are thin wrapp the design system. They take config via `input()` and — because they implement Angular's `ControlValueAccessor` — emit changes through `[ngModel]` / `(ngModelChange)`. The `form-field` **molecule** composes a label + projected control + error. The -`address-fields` **organism** (`src/app/registratie/ui/address-fields/address-fields.component.ts`) +`address-fields` **organism** (`apps/ssp/src/app/registratie/ui/address-fields/address-fields.component.ts`) composes three `form-field`s and emits with `output()`: ```ts @@ -432,7 +432,7 @@ Molecules compose atoms; organisms compose molecules — exactly like composing functions, where the composite is still pure. `address-fields` is pure because the `form-field` and `text-input` it's built from are pure. Each atomic level only uses the level(s) below it (see the hierarchy diagram in -[`ARCHITECTURE.md` §1](./architecture/ARCHITECTURE.md#1-the-big-picture-three-contexts-four-layers)). +[`ARCHITECTURE.md` §1](./architecture/ARCHITECTURE.md#1-the-big-picture-two-apps-cross-app-libraries-contexts-layers)). ### 5c. Pages / containers are the TEA runtime (the shell) @@ -510,9 +510,9 @@ Each recipe follows the existing pattern and naming, and ends with the same remi **When:** you genuinely need a new building block (not a one-off; reuse must earn it — see [CLAUDE.md §2](../../CLAUDE.md)). -**Where:** `shared/ui/` if generic; a context's `ui/` if domain-specific. Pick the level -by composition: composes nothing → **atom**; composes atoms → **molecule**; composes -molecules into a domain block → **organism**. +**Where:** `libs/shared/src/ui//` if generic; a context's `ui/` +if domain-specific. Pick the level by composition: composes nothing → **atom**; composes +atoms → **molecule**; composes molecules into a domain block → **organism**. **Steps:** build it **pure/presentational** — `input()`s for data/config, `output()`s for events, `computed()` for derived display; **no inject, no state, no effects**. Theme @@ -520,7 +520,7 @@ only with design tokens (no hardcoded hex — CI checks via `npm run check:token Add a co-located `*.stories.ts` titled `Layer/Name`. ```ts -// shape — see src/app/registratie/ui/address-fields/address-fields.component.ts +// shape — see apps/ssp/src/app/registratie/ui/address-fields/address-fields.component.ts export class AddressFieldsComponent { value = input.required(); errors = input({}); @@ -585,7 +585,7 @@ _This is the same loop, again — the rule is just another pure function._ **Steps:** compose A–C. Model the step's state in the Model; **derive** the visible steps rather than storing "next" — copy `visibleSteps(answers)` from -`src/app/herregistratie/domain/intake.machine.ts`: +`apps/ssp/src/app/herregistratie/domain/intake.machine.ts`: ```ts export function visibleSteps(a: Answers): StepId[] { diff --git a/libs/shared/docs/a11y.mdx b/libs/shared/docs/a11y.mdx index 80a4670..515420a 100644 --- a/libs/shared/docs/a11y.mdx +++ b/libs/shared/docs/a11y.mdx @@ -65,5 +65,5 @@ the same way (`withInMemoryScrolling`), both wired once in `app.config.ts` — n fails it on a real axe violation. Both can be locally disabled — the lint rule via a normal ESLint disable comment, axe via `parameters: { a11y: { disable: true } }` — but only with a comment naming _why_ and a cross-reference to the WP expected to remove the -skip (see `docs/project/backlog/WP-13-cibg-gap-register.md`'s marker convention, reused here). +skip (see `docs/project/archive/backlog/WP-13-cibg-gap-register.md`'s marker convention, reused here). Grep `a11y: { disable: true }` in `*.stories.ts` for the current list. diff --git a/libs/shared/docs/atomic-design.mdx b/libs/shared/docs/atomic-design.mdx index c37a72f..9a54dd9 100644 --- a/libs/shared/docs/atomic-design.mdx +++ b/libs/shared/docs/atomic-design.mdx @@ -57,9 +57,36 @@ atoms — that is the whole point: fewer things to understand, nothing bespoke p ## The rule, enforced **Each layer only uses layers below it, and dependencies point inward.** This is not a -convention you have to remember — `eslint.config.mjs` fails the build if `domain/` imports -Angular, or if a context imports "upward". See [the FP-in-the-UI primer](?path=/docs/foundations-fp-in-the-ui--docs) -for how the same discipline shapes state and effects. +convention you have to remember — `npm run dep:check` (dependency-cruiser) fails the build if +`domain/` imports Angular, or if a context imports "upward". `eslint.config.mjs` enforces a +different rule: the `any` ban, and a `max-lines` budget (250 lines, `skipBlankLines`, +`skipComments`) on every `{apps,libs}/**/*.{page,component,section,step}.ts` file — reachable, +not a style-guide default, since the dashboard page lands at 42 lines. See +[the FP-in-the-UI primer](?path=/docs/foundations-fp-in-the-ui--docs) for how the same +discipline shapes state and effects. + +## The layer folders + +| Layer | Where | +| --------- | --------------------------------------------------------------------------------------------------------------------------- | +| Atoms | `libs/shared/src/ui/atoms/` | +| Molecules | `libs/shared/src/ui/molecules/` | +| Organisms | `libs/shared/src/ui/organisms/` | +| Templates | `libs/shared/src/layout/` — deliberately holds several layers; its own organisms are chrome that only its own templates use | + +## The step-component contract + +A wizard step follows the same rule as `address-fields.component.ts`: values in, events +out, no internal state. + +1. **Inputs down.** A step reads its data only from `input()`s the container passes it. +2. **One narrow output up.** A step emits one specific event, not the container's whole + `dispatch`. +3. **`dispatch` is never passed down.** The container owns the Model and decides what a + step's event means; a step never calls `dispatch` itself. + +Corollary: a step gets **no** story of its own. The wizard's own story already mounts every +step, because it seeds the machine. ## A composition chain, live @@ -108,13 +135,13 @@ the next person doesn't spend an afternoon re-deciding. (Deliberate CIBG-specifi live in [CIBG gaps](?path=/docs/foundations-cibg-gap-register--docs); the FE⇄DS "same shape, different context" cases in [Domain-driven design](?path=/docs/foundations-domain-driven-design--docs).) -| Pair | Why kept separate | -| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `choice-link` vs `application-link` | Share the same `to`/`clickable`/`activate` navigation triad, but bind **different vendored patterns** — CIBG _Keuzelijst_ (`.keuzelijst__link`, `.stretched-link`) vs _Aanvragen_ (`.dashboard-block.applications li a`) — with different list/host semantics (`app-choice-link` renders an inner `
              • `; `application-link` **is** the `
              • `). Merging would fight the vendored CSS. Extract the shared triad into a mixin only if it grows. | -| `text-input` / `radio-group` / `checkbox` | Share only the standard Angular **ControlValueAccessor** boilerplate (the `writeValue`/`registerOn*`/`setDisabledState` block). They render genuinely different controls, so they stay three atoms. A base CVA class is the only DRY move — a refactor, not a component merge, and not worth it at three. | -| `button variant="subtle"` (`.btn-link`) vs `app-link` | A subtle button _looks_ like a link but is an **action** (`