Phase (f) of secured data (spec §13, §14.3, §15), plus the move to QQQ RC.6.
RC.6. The pin moves to 4.1.0-RC.6, and every stand-in RC.6 provides is removed: DataClassification, client channels, table features, and the UI API extension point (the uiapi profile is folded into the main build). Two stand-ins remain until RC.7: fieldaccess for #1172 and the audit tokens for #1182, each marked STAND-IN(core=#…, removeBy=RC.7).
Tables:secured_data_retention_rule (in the nav), secured_data_wipe_marker, secured_data_legal_hold, secured_data_wipe_run and secured_data_audit_key.
secured_data_audit_key holds DEKs wrapped with AES-GCM under QQQ_SECURED_DATA_KEK, with table, field and pk bound as AAD.
Its wrapped_key field is HIDDEN to everyone behind a lock no one is ever granted. The table is system-written only and is never sent to ESB or WORM.
Wipe process secured_data_wipe: a standard streamed ETL, run daily as the system and available as the "Run wipe now" table action (secured_data.retention).
Actions: NULL_WITH_MARKER (the default), OVERWRITE_TEXT, KEYED_HASH (refused on low-entropy fields), DELETE_RECORD, and ARCHIVE_THEN_WIPE (through an ArchiveSinkInterface).
Each batch runs in one transaction, which nulls the fields, writes wiped:v1, deletes the record-field DEKs, writes shredded:v1, writes markers and wipe-run rows, and logs WIPE rows to the access log.
Legal holds pause wiping. Review/Result lines show counts only, never values.
Audit protector and key source: a field is shredded when it is under a SHREDDABLE rule, or when it is PII/PHI and low-entropy. CHANGED_ONLY rules write changed:v1 with no derivative.
Backups panel and home warning: shown when known backup retention exceeds a rule's age. The README documents the residual risk of keys kept in physical backups.
Fix: the key source used to zero each DEK after returning it, so callers received an all-zero key. It now returns a copy, covered by a regression test.
Tests
RC.6 (CI): 87 tests, 0 failures, 6 skipped. The skips are the core-hook integration, canary and wipe-proof tests.
Against the core branches (#1172 + #1182): 87 tests, 0 failures, 0 skipped.
Canary (§15):
Plant:CANARY-PHI-* in PHI fields.
Exercise: insert, update, a failing validation, a MASKED query and CSV export, an access-log flush and a wipe.
Scan: audit and auditDetail, the access log, wipe runs and markers, the key and policy tables, the export, error messages and captured logs.
Result: no marker and no substring of 5 or more characters anywhere. A positive control proves the scan works.
Wipe-proof (§15):
Setup: 191 audited systolic readings (60–250) under a SHREDDABLE rule.
Before the wipe: each token verifies its true value only.
After the wipe: 0 matches for every value 60–250 against the instance HMAC key, the KEK, the remaining DEK, and an all-zero key. shred: tokens no longer verify, and the key rows are gone.
Known core issue
Core's integer conversion error echoes the raw value. A string inserted into an INTEGER PHI field produces Value [...] could not be converted. This is being fixed in core #1182.
## Summary
Phase (f) of secured data (spec §13, §14.3, §15), plus the move to QQQ RC.6.
- **RC.6.** The pin moves to `4.1.0-RC.6`, and every stand-in RC.6 provides is removed: DataClassification, client channels, table features, and the UI API extension point (the `uiapi` profile is folded into the main build). Two stand-ins remain until RC.7: fieldaccess for #1172 and the audit tokens for #1182, each marked `STAND-IN(core=#…, removeBy=RC.7)`.
- **Tables:** `secured_data_retention_rule` (in the nav), `secured_data_wipe_marker`, `secured_data_legal_hold`, `secured_data_wipe_run` and `secured_data_audit_key`.
- `secured_data_audit_key` holds DEKs wrapped with AES-GCM under `QQQ_SECURED_DATA_KEK`, with table, field and pk bound as AAD.
- Its `wrapped_key` field is HIDDEN to everyone behind a lock no one is ever granted. The table is system-written only and is never sent to ESB or WORM.
- **Wipe process `secured_data_wipe`:** a standard streamed ETL, run daily as the system and available as the "Run wipe now" table action (`secured_data.retention`).
- Actions: NULL_WITH_MARKER (the default), OVERWRITE_TEXT, KEYED_HASH (refused on low-entropy fields), DELETE_RECORD, and ARCHIVE_THEN_WIPE (through an `ArchiveSinkInterface`).
- Each batch runs in one transaction, which nulls the fields, writes `wiped:v1`, deletes the record-field DEKs, writes `shredded:v1`, writes markers and wipe-run rows, and logs WIPE rows to the access log.
- Legal holds pause wiping. Review/Result lines show counts only, never values.
- **Audit protector and key source:** a field is shredded when it is under a SHREDDABLE rule, or when it is PII/PHI and low-entropy. CHANGED_ONLY rules write `changed:v1` with no derivative.
- **Backups panel and home warning:** shown when known backup retention exceeds a rule's age. The README documents the residual risk of keys kept in physical backups.
- **Fix:** the key source used to zero each DEK after returning it, so callers received an all-zero key. It now returns a copy, covered by a regression test.
## Tests
- **RC.6 (CI):** 87 tests, 0 failures, 6 skipped. The skips are the core-hook integration, canary and wipe-proof tests.
- **Against the core branches (#1172 + #1182):** 87 tests, 0 failures, 0 skipped.
- **Canary (§15):**
- **Plant:** `CANARY-PHI-*` in PHI fields.
- **Exercise:** insert, update, a failing validation, a MASKED query and CSV export, an access-log flush and a wipe.
- **Scan:** audit and auditDetail, the access log, wipe runs and markers, the key and policy tables, the export, error messages and captured logs.
- **Result:** no marker and no substring of 5 or more characters anywhere. A positive control proves the scan works.
- **Wipe-proof (§15):**
- **Setup:** 191 audited systolic readings (60–250) under a SHREDDABLE rule.
- **Before the wipe:** each token verifies its true value only.
- **After the wipe:** 0 matches for every value 60–250 against the instance HMAC key, the KEK, the remaining DEK, and an all-zero key. `shred:` tokens no longer verify, and the key rows are gone.
## Known core issue
Core's integer conversion error echoes the raw value. A string inserted into an INTEGER PHI field produces `Value [...] could not be converted`. This is being fixed in core #1182.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Phase (f) of secured data (spec §13, §14.3, §15), plus the move to QQQ RC.6.
4.1.0-RC.6, and every stand-in RC.6 provides is removed: DataClassification, client channels, table features, and the UI API extension point (theuiapiprofile is folded into the main build). Two stand-ins remain until RC.7: fieldaccess for #1172 and the audit tokens for #1182, each markedSTAND-IN(core=#…, removeBy=RC.7).secured_data_retention_rule(in the nav),secured_data_wipe_marker,secured_data_legal_hold,secured_data_wipe_runandsecured_data_audit_key.secured_data_audit_keyholds DEKs wrapped with AES-GCM underQQQ_SECURED_DATA_KEK, with table, field and pk bound as AAD.wrapped_keyfield is HIDDEN to everyone behind a lock no one is ever granted. The table is system-written only and is never sent to ESB or WORM.secured_data_wipe: a standard streamed ETL, run daily as the system and available as the "Run wipe now" table action (secured_data.retention).ArchiveSinkInterface).wiped:v1, deletes the record-field DEKs, writesshredded:v1, writes markers and wipe-run rows, and logs WIPE rows to the access log.changed:v1with no derivative.Tests
CANARY-PHI-*in PHI fields.shred:tokens no longer verify, and the key rows are gone.Known core issue
Core's integer conversion error echoes the raw value. A string inserted into an INTEGER PHI field produces
Value [...] could not be converted. This is being fixed in core #1182.🤖 Generated with Claude Code