# WP-05 — Parse-don't-validate closure + MDX Status: todo Phase: 1 — FP/DDD core ## Why Three adapters trust the wire, contradicting the repo's flagship "parse, don't validate" principle (every response through a hand-written `parse*` returning `Result`). ## Read first - `CLAUDE.md` §3 + §4; `docs/architecture/0001-bff-lite-decision-dtos.md` - `src/app/registratie/infrastructure/applications.adapter.ts` (+ its spec — the pattern to copy) - The three offenders below ## Decisions (pre-made, don't relitigate) - Unknown enum-ish values from the wire map to an explicit `Failure` (never a silent fallback); specs pin that behavior. - The MDX curriculum page ships in this WP (the WP that establishes an invariant teaches it). ## Files - `src/app/herregistratie/infrastructure/intake-policy.adapter.ts` — returns the raw DTO resource with no parse; add `parseIntakePolicy(raw: unknown): Result` and a domain-side type - `src/app/registratie/infrastructure/big-register.adapter.ts` (~line 25) — `n.type as AantekeningType` → validated parse - `src/app/brief/infrastructure/brief.adapter.ts` (~line 189) — `dto.scope as PassageScope` → validated parse (the file is otherwise parse-heavy; this one field skips) - New co-located specs: `intake-policy.adapter.spec.ts`, extend `big-register.adapter.spec.ts` / `brief.adapter.spec.ts` (create if missing) - New `src/docs/parse-dont-validate.mdx` — title `Foundations/Parse, don't validate` ## Steps 1. For each hole: write the small parser (pattern: `parseAanvraagStatus` in `applications.adapter.ts`), wire it in, delete the cast. 2. Spec each parser: valid shape, missing field, unknown tag/enum value → `err`. 3. MDX page: the principle, value objects (`registratie/domain/value-objects/`), boundary parsers, linking the three real call sites just fixed (before/after snippet). ## Acceptance criteria - [ ] No unvalidated `as ` casts in `**/infrastructure/**` (the sanctioned "narrow unknown to `Partial` then parse" entry-cast is fine). - [ ] Each new parser has a spec including a rejection case. - [ ] MDX renders under Foundations in Storybook. ## Verification GREEN + `npm run test-storybook:ci`. Smoke: intake wizard still loads its policy (`npm start` → /intake). ## Out of scope Runtime validation on *every* endpoint (explicitly out of scope for the POC per CLAUDE.md); `digid.adapter.ts` (faked auth, sanctioned). ## Risks Seeded backend data containing values the new parsers reject → surfaces as `Failure` in the UI; check the backend seed while writing the parsers and align the accepted set.