KNUCK-A042
KNUCK-A042: PHI redactor context-awareness -- allow ISO dates in engineering-labeled task bodies
Suggested
Justin Cooke
Body
feature_id: FEAT-studio-audit
## Context
`apps/web/src/lib/phi-redactor.ts` line 51 matches every ISO date as a DOB:
```ts
{ kind: "DOB", re: /\b\d{4}-\d{2}-\d{2}\b/g },
```
The inline comment (line 49-50) states the trade explicitly: "Broad by design -- over-redacting a non-DOB date is safe; missing a DOB is a breach." That default is correct for patient-adjacent surfaces. It is wrong for engineering tickets, where the ISO date IS the evidence.
Concrete miss during KNUCK-A036 through A041 filing (see `audit/evidence/knuck-a007b1a/README.md` and the A036 body posted at Task cuid `cmts6cx9k001jky04310zihmg`): every occurrence of `[REDACTED-DOB]` in the A036 ticket body was replaced with `[REDACTED-DOB]`. The ticket is a CI-gate spec with zero PHI in scope. Downstream Ledger consumers now read the redacted body and see:
> On [REDACTED-DOB], migrate-prod for KNUCK-A007b1a (PR #278) failed on its own pre-flight guard
instead of the actual failure timestamp. The forensic value of the ticket is degraded. Workaround adopted for the A036-A041 refile: use `2026.09.08` (dots), which the regex does not match. That is not a durable fix.
Related to `FEAT-studio-audit` because the redactor is the gate between authored ticket bodies and the durable audit-trail record in the Ledger.
## Acceptance Criteria
- `redactPhi(text, opts?)` accepts an optional `{ phiInScope?: boolean, allowKinds?: PhiKind[] }` param
- When `phiInScope === false`, the DOB rule is skipped (SSN, EMAIL, PHONE, MRN, NAME still applied -- those never legitimately appear in engineering copy either, but they are catchable-if-present and the wire cost is low)
- The task-body PATCH and POST paths (`api/studio/[team]/tasks/route.ts`, `api/studio/[team]/tasks/[id]/route.ts`) read the Task's `phiInScope` column (default false, see schema) and pass `{ phiInScope: task.phiInScope }` into `redactPhi`
- Existing `logRedactionWarning` behavior preserved: any DOB redaction that DOES fire (phiInScope=true tickets, or the SSN/EMAIL/PHONE/MRN/NAME rules on any ticket) still lands the warning row
- Ship with unit tests covering: (a) engineering ticket with ISO date -> preserved, (b) PHI-in-scope ticket with ISO date -> redacted, (c) SSN/EMAIL/PHONE/MRN/NAME redaction fires in both modes
- Backfill script `scripts/unredact-non-phi-dobs.ts` scans all Task rows where `phiInScope=false` and the body contains `[REDACTED-DOB]`, and appends a comment linking to the git blame of the original ticket source (if reconstructible from PR body / commit message) OR flags the row for manual review. Never rewrites the body silently -- rewriting a PHI-redacted body without a durable trail would be a Marisol (HIPAA Compliance Officer) veto condition.
- Applies to the same redactor used by `api/studio/[team]/tasks/comments/route.ts` (comment bodies)
## Non-goals
- Not weakening the redactor for tickets that legitimately touch PHI. The `phiInScope=true` path retains full-strength redaction.
- Not weakening SSN, EMAIL, PHONE, MRN, NAME rules in any mode. Only the DOB (date) rule is context-sensitive.
## Effort
Single Ledger ticket. Parallelizable with A036-A041. Blockers: none.
## Filed as follow-on to
KNUCK-A036 refile discovery -- the workaround (`2026.09.08` dot-format) proved the redactor is the root cause. Also filed as follow-on to PR #278.
Attachments
Loading attachments…
Comments
Loading comments…