Initial Commit
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# OpenSpec Change: enterprise-data-masking
|
||||
|
||||
- **Change ID**: enterprise-data-masking
|
||||
- **Package**: `@suaveplan/data-masking`
|
||||
- **Category**: universal
|
||||
- **Target path**: `universal/data/data-masking`
|
||||
- **Status**: PROPOSED
|
||||
- **Date**: 2026-04-19
|
||||
- **Reference spec**: `/mnt/s/web/suaveplan/enterprise/data-masking.md`
|
||||
|
||||
## Summary
|
||||
|
||||
Greenfield rebuild of `@suaveplan/data-masking` — structured PII masking with type detection, pattern-based redaction, conditional role/field-permission masking, strategy library (`hash`, `partial`, `redact`, `maskEmail`, `maskPhone`, `maskIp`, `maskCreditCard`), pluggable `MaskingRegistry`, and an `AuditEntry` trail.
|
||||
|
||||
## Current-state audit (genesis)
|
||||
|
||||
Package does not exist yet — fresh build.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Workspace: `@suaveplan/error`, `@suaveplan/events`, `@suaveplan/types`
|
||||
- External (via catalog): `zod`, `tslib`, `@opentelemetry/api`
|
||||
- Dev (via catalog): `vitest`, `@vitest/coverage-istanbul`, `fast-check`, `mitata`
|
||||
|
||||
## Preserved public surface
|
||||
|
||||
### Masker / registry
|
||||
|
||||
- `DataMasker`, `MaskingRegistry`, `RegistryErrorCode`
|
||||
- Strategies: `hash`, `maskCreditCard`, `maskEmail`, `maskIp`, `maskPhone`, `partial`, `redact`
|
||||
|
||||
### Patterns
|
||||
|
||||
- `PatternMasker`, `PatternMaskerOptions`, `PatternMatch`, `PatternRule`
|
||||
|
||||
### Detection
|
||||
|
||||
- `TypeDetector`, `DetectionOptions`, `DetectionResult`, `SensitiveDataType`
|
||||
|
||||
### Rules
|
||||
|
||||
- `ConditionalMasker`, `ConditionalMaskResult`, `FieldPermission`, `MaskingContext`, `MaskingPolicy`, `MaskingRole`
|
||||
|
||||
### Audit
|
||||
|
||||
- `MaskingAudit`, `AuditEntry`, `AuditFilter`, `AuditOptions`, `AuditSink`
|
||||
|
||||
### Error codes
|
||||
|
||||
- `DataMaskingErrorCode`, `DATA_MASKING_ERROR_METADATA`, `registerDataMaskingErrorCodes`
|
||||
|
||||
### Hooks / types
|
||||
|
||||
- `DataMaskingHandler`, `MaskingHookData`, `MaskingHookMap`
|
||||
- `MaskingConfig`, `MaskingOptions`, `MaskingRule`, `MaskingStrategy`, `MaskResult`
|
||||
|
||||
## New genesis additions
|
||||
|
||||
- Additional codes: `DATA_MASKING.INVALID_POLICY`, `DATA_MASKING.UNKNOWN_STRATEGY`, `DATA_MASKING.AUDIT_SINK_FAILED`.
|
||||
- Zod schemas for every config type.
|
||||
- OTel counter `data_masking.masked.total{type}`, histogram `data_masking.mask.duration_ms`.
|
||||
- Property tests: idempotency (mask twice = mask once), never-leak property on PII patterns.
|
||||
|
||||
## Impact
|
||||
|
||||
- Adds one new package: `universal/data/data-masking`
|
||||
- Adds one new spec capability: `data-masking`
|
||||
@@ -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.
|
||||
49
openspec/archive/2026-04-19-enterprise-data-masking/tasks.md
Normal file
49
openspec/archive/2026-04-19-enterprise-data-masking/tasks.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Tasks: enterprise-data-masking
|
||||
|
||||
## 1. Scaffold
|
||||
|
||||
- [x] 1.1 `universal/data/data-masking/`; 100/100/100/100; guard tests; CLAUDE/README/FOLDERS.
|
||||
|
||||
## 2. Errors + schemas
|
||||
|
||||
- [x] 2.1 `src/error-codes.ts` + side-effect register.
|
||||
- [x] 2.2 Zod schemas for `MaskingConfig`, `MaskingRule`, `MaskingPolicy`, `AuditEntry`.
|
||||
|
||||
## 3. Strategies
|
||||
|
||||
- [x] 3.1 `src/strategies/strategies.ts` — `hash` (HMAC-SHA256), `partial`, `redact`, `maskEmail`, `maskPhone`, `maskIp`, `maskCreditCard` (Luhn-aware).
|
||||
|
||||
## 4. Detection
|
||||
|
||||
- [x] 4.1 `src/detection/type-detector.ts` — `TypeDetector` with built-in `SensitiveDataType` patterns.
|
||||
|
||||
## 5. Patterns
|
||||
|
||||
- [x] 5.1 `src/patterns/pattern-masker.ts`.
|
||||
|
||||
## 6. Registry
|
||||
|
||||
- [x] 6.1 `src/registry/registry.ts` — `MaskingRegistry` + registry error codes.
|
||||
|
||||
## 7. Conditional rules
|
||||
|
||||
- [x] 7.1 `src/rules/conditional-masker.ts` — role + field permissions.
|
||||
|
||||
## 8. Masker façade
|
||||
|
||||
- [x] 8.1 `src/masker/masker.ts` — `DataMasker` orchestrator; OTel instrumentation.
|
||||
- [x] 8.2 `src/types/masking-hooks.ts` — hook surface.
|
||||
|
||||
## 9. Audit
|
||||
|
||||
- [x] 9.1 `src/audit/masking-audit.ts` — `MaskingAudit`, `AuditSink` interface, filter helpers.
|
||||
|
||||
## 10. Docs / barrel / subpath exports / README
|
||||
|
||||
## 11. Benchmarks
|
||||
|
||||
- [x] 11.1 `mask.bench.ts` on 10 k-record JSON trees.
|
||||
|
||||
## 12. Ship gate
|
||||
|
||||
- [x] 12.1 Verification sequence; fold + archive.
|
||||
Reference in New Issue
Block a user