Skip to content

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 in id68-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 subdomain
regex:(?i)kh\.phew\.org\.uk==>kh.client.example
# R3 — bare client domain
regex:(?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-client

Every Inv 31 identity-set row is covered:

Denylist entry (class)RulesNotes
Client-name stem + derived identifiersR1, R2, R3, R5, R8Stem-bearing PATHS (branding, deleted scripts) are handled by the path-removal inventory, not this map; R8 catches residual content mentions.
Legal nameR4Also 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 literalR6
Real ICO numberR7Already 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.

--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).

  1. 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.
  2. 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).
  3. Migration-file treatment (interacts with OQ-G(b)): Branch A vs Branch B in id68-filter-repo-purge.md §4. R5/R4 behaviour inside supabase/migrations/** blobs depends on that ratification.

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.