ID-68 purge redaction map — DRAFT (OQ-H OPEN)
ID-68 {68.10} purge redaction map — DRAFT
Section titled “ID-68 {68.10} purge redaction map — DRAFT”STATUS: DRAFT — OQ-H RATIFICATION GATE IS OPEN (Liam). This map is the PC-35 step-3 draft rendered from the PC-31 canonical denylist (
ops/identity-denylist.json, version 1, updated 07/06/2026). It is not ratified. Two decisions remain with Liam before the{68.10}purge may consume it: (1) final map contents (including whether the broad bare-stem rule R8 is included), and (2) whether HEAD-scrub-only is acceptable for low-sensitivity strings (PRE-FLIP §2 E) — see the Branch A / Branch B treatment inid68-filter-repo-purge.md.PRIVACY: this file lives in the PRIVATE docs-site repo and must NEVER be copied into the public knowledge-hub repo — the map IS the leak (PC-31 placement constraint). Prepared by ID-68.29; execution owner is record
{68.10}(HELD).
Machine-readable rules (git-filter-repo --replace-text format)
Section titled “Machine-readable rules (git-filter-repo --replace-text format)”Rules apply in file order — git-filter-repo applies replacement rules
sequentially per blob, so most-specific entries come first (otherwise the bare
rules would consume the structured forms and leak shape, e.g. R8 before R3
would yield example-client.org.uk). literal: matches are case-sensitive in
filter-repo; every token the denylist marks case_insensitive therefore uses
a regex:(?i) form.
# id68-redaction-map (DRAFT v1 — OQ-H OPEN; rendered from ops/identity-denylist.json v1)# R1 — support email (denylist class: client-name stem, covers_examples)regex:(?i)support@phew\.org\.uk==>support@client.example# R2 — production subdomainregex:(?i)kh\.phew\.org\.uk==>kh.client.example# R3 — bare client domainregex:(?i)phew\.org\.uk==>client.example# R4 — legal name (denylist class: legal name)regex:(?i)phew\s+design\s+limited==>Example Client Ltd# R5 — old auth-hook name (superseded at HEAD by the generic migration, PC-33-B)regex:(?i)capture_phew_domain_hook==>capture_signup_domain_hook# R6 — datacentre literal (denylist class: datacentre literal)regex:(?i)telehouse==>example-datacentre# R7 — historical ICO registration number (denylist class: real ICO registration# number; case-sensitive literal). Placeholder aligns with the existing# HEAD convention (ZA123456 — knowledge-hub 83525b84 lineage / test fixtures).Z8143724==>ZA123456# R8 — bare client-name stem (BROAD; ordered last so R1-R5 have already# consumed the structured forms). OQ-H DECISION POINT: include or drop —# see "Open decision points" below.regex:(?i)phew==>example-clientRule provenance (denylist coverage)
Section titled “Rule provenance (denylist coverage)”Every Inv 31 identity-set row is covered:
| Denylist entry (class) | Rules | Notes |
|---|---|---|
| Client-name stem + derived identifiers | R1, R2, R3, R5, R8 | Stem-bearing PATHS (branding, deleted scripts) are handled by the path-removal inventory, not this map; R8 catches residual content mentions. |
| Legal name | R4 | Also redacts the migration 20260419212103_*.sql:48 seeded row in history — the live-DB row itself is OQ-G(b), out of this map’s scope. |
| Verbatim client bid prose (non-token class) | — (path removal) | Not token-greppable (denylist non_token_classes). Covered by the path inventory: the 4 legacy gold-standards, the classification prompt’s relocation (PC-33-C), and the relocated docs/** set. |
| Datacentre literal | R6 | |
| Real ICO number | R7 | Already placeholder’d at public HEAD (S301a); this rule cleans history. |
Carve-out (denylist exclusion_patterns) does not apply to --replace-text
rules — filter-repo has no per-rule exclusion mechanism. Consequence: R8 (if
ratified in) also rewrites the carve-out sites in history (e.g. the
.env.example:14 slug example becomes example-client). This is harmless
(history-only; HEAD carve-outs are re-asserted by guard-CI) but is recorded
here so the AC-E2 verification expects zero matches without carve-out
exceptions in history.
Commit-message coverage
Section titled “Commit-message coverage”--replace-text rewrites blob contents only. Commit MESSAGES also carry
identity strings (e.g. historical commits naming the deleted client-named
scripts). PRODUCT Inv 36 requires no reachable commit to contain
identity-set matches — the runbook therefore passes this same file to
--replace-message in the same filter-repo invocation. Verification adds
git log --all -i --grep=<token> per token (see runbook step 5).
Open decision points (OQ-H — Liam)
Section titled “Open decision points (OQ-H — Liam)”- R8 bare-stem rule in or out. In: strongest guarantee (zero stem matches anywhere in history, AC-E2 trivially verifiable). Out: smaller diff, structured rules R1-R5 still cover every known occurrence shape, but any unanticipated occurrence survives. Draft recommendation: in.
- HEAD-scrub-only for low-sensitivity strings (PRE-FLIP §2 E). If accepted for a given token, its rule is dropped from the ratified map and the history occurrences are accepted as residual (private-history risk only — but note Inv 36 requires clean history at flip, so HEAD-scrub-only acceptance must be recorded as an explicit Inv 36 carve-out in the ledger). Candidate low-sensitivity strings: R5 (hook name — already superseded at HEAD), R6 (datacentre literal — factual third-party reference).
- Migration-file treatment (interacts with OQ-G(b)): Branch A vs Branch B
in
id68-filter-repo-purge.md§4. R5/R4 behaviour insidesupabase/migrations/**blobs depends on that ratification.
Consumption
Section titled “Consumption”At purge time (after OQ-H closes): extract the fenced block above to a plain
file outside any repo tree (e.g. ~/id68-redaction-map.txt), delete the
lines for any rule ratified OUT, and pass it to both --replace-text and
--replace-message (runbook step 4). Do not commit the extracted file
anywhere.