feat(privacy): WP-40 — PII kernel (Bsn value object + masked-value atom)
Branded Bsn value object with the elfproef (11-test) checksum in shared/kernel/bsn.ts,
wired into the DigiD login boundary so login does real BSN validation (hint + e2e BSNs
updated to a valid 123456782). Consolidate the pure maskers into shared/kernel/pii.ts
(maskBsn/maskTail/REDACTED); debug-state keeps redactProfile (needs the registratie
BigProfile — boundary). New <app-masked-value> atom (+story) centralises the masked
`.includes('*')` detection + reveal affordance; behandel-scherm refactored onto it.
Session.bsn stays string (persistence boundary drops it for privacy). +specs for bsn/pii.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import { Component, ElementRef, computed, input, output, viewChild } from '@angu
|
||||
import { PlaceholderOption } from '@shared/ui/rich-text-editor/rich-text-editor.component';
|
||||
import { ButtonComponent } from '@shared/ui/button/button.component';
|
||||
import { HeadingComponent } from '@shared/ui/heading/heading.component';
|
||||
import { MaskedValueComponent } from '@shared/ui/masked-value/masked-value.component';
|
||||
import { StepperComponent } from '@shared/ui/stepper/stepper.component';
|
||||
import { Besluit, Brief, CaseContext, LibraryPassage } from '@brief/domain/brief';
|
||||
import { inferSelection } from '@brief/domain/besluit';
|
||||
@@ -25,6 +26,7 @@ import { BesluitPanelComponent } from '@brief/ui/besluit-panel/besluit-panel.com
|
||||
imports: [
|
||||
ButtonComponent,
|
||||
HeadingComponent,
|
||||
MaskedValueComponent,
|
||||
StepperComponent,
|
||||
LetterCanvasComponent,
|
||||
DiagnosticsPanelComponent,
|
||||
@@ -92,10 +94,13 @@ import { BesluitPanelComponent } from '@brief/ui/besluit-panel/besluit-panel.com
|
||||
<span>{{ caseContext().aanvraagReferentie }}</span>
|
||||
<span>{{ caseContext().zorgverlenerNaam }}</span>
|
||||
<span>
|
||||
{{ bigLabel() }} {{ caseContext().bigNummer }}
|
||||
@if (canRevealBigNummer() && isMasked()) {
|
||||
<app-button variant="subtle" (click)="onReveal()">{{ revealLabel() }}</app-button>
|
||||
}
|
||||
{{ bigLabel() }}
|
||||
<app-masked-value
|
||||
[value]="caseContext().bigNummer"
|
||||
[canReveal]="canRevealBigNummer()"
|
||||
[revealLabel]="revealLabel()"
|
||||
(reveal)="onReveal()"
|
||||
/>
|
||||
</span>
|
||||
<span>{{ caseContext().beroep }}</span>
|
||||
</div>
|
||||
@@ -172,10 +177,6 @@ export class BehandelSchermComponent {
|
||||
locate = output<Diagnostic>();
|
||||
revealBigNummer = output<void>();
|
||||
|
||||
/** The BIG-nummer arrives masked (contains `*`); once revealed the swapped value has
|
||||
no `*`, so the reveal action hides itself — no separate "revealed" flag needed. */
|
||||
protected isMasked = computed(() => this.caseContext().bigNummer.includes('*'));
|
||||
|
||||
/** Step-up (PRD-0002 §5d) stubbed as a native confirm — the extra verification gesture
|
||||
before an audited PII reveal. ponytail: real systems prompt MFA / recent re-auth. */
|
||||
protected onReveal() {
|
||||
|
||||
Reference in New Issue
Block a user