New phase from the 5-item analysis: linked showcase snippets + animations, runnable scaffolding generators (pages/wizards/context/SSP), dependency graph + declarative boundaries, PII hardening (branded Bsn VO + masked-value atom + persisted no-PII audit) doubling as a privacy showcase, and Vitest coverage. Goal: both a teaching showcase and a production starter template. Sequenced with priorities + dependencies in the README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1.6 KiB
1.6 KiB
WP-40 — PII kernel: branded Bsn VO + masked-value atom
Status: todo Phase: 8 — platform/DX/showcase Priority: P2
Why
Masking is real but ad-hoc: pure helpers live in debug-state/mask.ts, the BSN is a bare string
in session.ts (no branded VO / checksum, unlike BigNummer/Postcode), and masked state is
detected by .includes('*') sniffing — no reusable atomic-design component. For a register this is
AVG art. 9 (BSN = special category) territory; the pieces should be first-class and reusable.
Decisions
Bsnbranded value object +parseBsnwith the elfproef (9 digits, weighted mod-11) checksum — parity with the other value objects. Replace the barestringinsession.ts.- Consolidate the pure maskers into
shared/kernel/pii.ts(functional core):maskBsn,maskTail,redactProfile, … Keep the backendMaskTailtwin in sync. <app-masked-value>atom (shared/ui) — masked by default, optional reveal affordance + a11y; replaces.includes('*')sniffing and composes into the behandel-scherm reveal.
Files
- New
src/app/shared/kernel/bsn.ts(+spec, elfproef cases) andshared/kernel/pii.ts(+spec). src/app/auth/domain/session.ts—bsn: Bsn.- New
src/app/shared/ui/masked-value/atom (+ story). src/app/shared/ui/debug-state/mask.ts— re-export/move to the kernel module.
Acceptance criteria
parseBsnaccepts valid elfproef numbers, rejects bad checksum/length (spec).<app-masked-value>renders masked by default with an accessible reveal; behandel-scherm uses it.- Pure maskers have specs (no TestBed); backend
MaskTailparity noted;npm run cigreen.