Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
# Capability Spec: data-masking
**Package**: `@suaveplan/data-masking`
**Version**: 0.0.0 (genesis)
**Status**: ADDED
---
## ADDED Requirements
### DM-01 — Strategy contract
Every `MaskingStrategy` MUST expose `{ name, mask(value, options?): MaskResult }`. Built-in strategies `hash`, `partial`, `redact`, `maskEmail`, `maskPhone`, `maskIp`, `maskCreditCard` MUST all implement this contract.
### DM-02 — Registry
`MaskingRegistry.register(name, strategy)` MUST reject duplicates unless `overwrite: true`. `MaskingRegistry.resolve(name)` MUST throw `DATA_MASKING.UNKNOWN_STRATEGY` when the name is absent.
### DM-03 — Idempotency
`DataMasker.mask` MUST be idempotent: `mask(mask(x)) === mask(x)` (structural equality) for every built-in strategy on PII inputs.
### DM-04 — Type detection
`TypeDetector.detect(value)` MUST return an array of `DetectionResult { type, start, end, confidence }`. Built-in `SensitiveDataType` values MUST include `email`, `phone`, `credit-card`, `ssn`, `ipv4`, `ipv6`, `jwt`, `api-key`.
### DM-05 — Conditional masking
`ConditionalMasker.apply(value, ctx)` MUST evaluate the `MaskingPolicy` with `MaskingContext { role, permissions: FieldPermission[] }`. Policies MUST either mask, allow, or redact per-field. Unknown policies MUST surface as `DATA_MASKING.INVALID_POLICY`.
### DM-06 — Audit trail
`MaskingAudit.record(entry)` MUST write `AuditEntry { at, actor?, field, strategy, outcome }` to every registered `AuditSink`. Sink failures MUST be captured and surfaced as `DATA_MASKING.AUDIT_SINK_FAILED` without aborting the mask itself.
### DM-07 — Credit-card mask
`maskCreditCard` MUST preserve the last 4 digits and validate Luhn; non-Luhn inputs MUST pass through unchanged (they're not actually credit cards) and record a lower-confidence detection result.
### DM-08 — Observability
Every mask call MUST record `data_masking.mask.duration_ms` histogram and `data_masking.masked.total{type}` counter. Masked values MUST NOT appear in OTel attributes.