Development record
2026-08-01 — iss-96 (item A6), a VERIFICATION milestone rather than an implementation: the transcript scanner's tracked coverage gaps re-checked against the network-identifier set A2 folded into `DefaultPatterns`, and the residue re-scoped in place. Two findings, both empirical rather than inspected. (1) A2 DID reach this path — every scanner consumer inherits the network set, so a non-reserved address or a LAN/device hostname in a captured transcript is now a finding (all five kinds — `net:ipv4`, `net:ipv6`, `net:mac`, `net:lan_hostname`, `net:device_hostname` — exercised on the transcript path itself in the same corpus, not inferred from their presence in the pattern set, and a flagged private address asserted REDACTED in the stored record at the store boundary); that class is therefore newly covered on this path since iss-96 was captured — it was never part of the entry's residue, which names unanchored secrets and home paths only, so this is coverage the re-check ESTABLISHES rather than a gap it closes. (2) The classes iss-96 actually names — a 40-character secret-key value with no prefix, a bare password, a prefix-less API token, and now a genuinely high-entropy 40-character value — still produce ZERO findings at the transcript path's own entry point, with or without a `password:`, `api_key =` or `Authorization: Bearer` key name beside them, because the TOKEN patterns are prefix-anchored APART FROM `rp_session_key`, which keys on the literal JSON field name `"sessionKey"` rather than on a generic key-name class, and no pattern measures entropy. The set as a WHOLE is not uniformly prefix-anchored and must not be described as such: the network kinds are an allowlist inversion, the identity kinds key on the probed identity, `token:pem_private_key` is a literal header, and `Pattern.SkipAt` already lets a pattern accept or reject a match by what SURROUNDS it — none of which reaches an unlabelled value, which is why the residue stands, and two of which (`rp_session_key`, `SkipAt`) are the shipped precedent remediation option (b) would generalise rather than introduce. Disposition: iss-96 stays OPEN with a dated verification section appended in place (the iss-24 precedent; a `capture resolve` would have had to state an action nobody took, and the ledger's resolution field is exactly that claim), re-scoped from "coverage may have moved" to a single unresolved DECISION between an entropy/charset detector with a length floor, key-name context matching, and the opt-in external-scanner adapter over this path only — three options that differ in REACH, not merely in false-positive cost, and saying otherwise would misdescribe them: (a) reads the value, so it is the only one that reaches an UNLABELLED value; (b) covers labelled values only and is structurally incapable of this entry's own first-named case, a bare secret-key value with no key name, because there is no key to match; (c) has whatever reach its ruleset delivers, and the measurement recorded in the entry corrects an earlier one that was wrong in both fixture and conclusion — re-run 2026-08-01 with pinned, sha256-verified gitleaks 8.24.3 default rules (`gitleaks dir`, no repo config) over a NAMED fixture, one specimen per line, comprising every case of `TestTranscriptPathMissesUnanchoredEntropy`'s table, every line of the transcript `TestCaptureStoresUnanchoredEntropyVerbatim` captures, and delimiter probes on the same values: 21 lines, 6 findings, all `generic-api-key`, whose condition is keyword + `=`/`:` DELIMITER + entropy at or above 3.5 bits per character, so `password: <passphrase>`, `--password=<passphrase>`, `api_key = <high-entropy>` (the branch's own corpus case), `session_token = <high-entropy>` and `session_token: <high-entropy>` are all CAUGHT, while bare values with no key name, key names separated from their value by prose rather than a delimiter (the store fixture's hand-built `session_token <high-entropy>` line, which the earlier measurement mis-read as a key-name failure when the cause is the absent delimiter), and every sub-floor repetitive specimen whatever key name precedes it, all pass — so (c) as shipped reaches LABELLED high-entropy values, subsuming much of (b) and adding an entropy floor on top of it rather than being the narrowest option, and (a) remains the only one that reaches an UNLABELLED value; the anchored `ghp_` control passing is a fixture artefact (36 repeated characters fall under gitleaks' own entropy filter — a realistic-entropy `ghp_` token in the same run IS caught by `github-pat`), not a coverage claim. False-positive cost is the SECOND axis and lands hardest on (a) — a redaction false positive corrupts the record redaction exists to preserve — so reach and cost together are the open question and the bar is the maintainer's to set: grill-then-implement, not autonomous. The verification is PINNED in the tree rather than asserted in prose: `TestTranscriptPathMissesUnanchoredEntropy` at the pattern-set boundary and `TestCaptureStoresUnanchoredEntropyVerbatim` at the store boundary (each specimen present verbatim in the written record, the anchored token absent AND its `fingerprintSpan` fingerprint present — the byte-level mirror of `maskSecret` that `sealLine` actually applies on the Capture path, not `maskSecret` itself — since absence alone would also be satisfied by a store that dropped the line). THE PINS' REACH IS THE PATTERN SET, and the earlier claim that they "fail by design, never a silent pass" was too broad on two counts, both now fixed: the original specimens all REPEAT and measure 3.12, 2.16 and 2.75 bits per character, below the ~3.5-bit floor an entropy detector conventionally uses, so an entropy detector could have landed with every pin green — a 5.32-bit specimen assembled at run time from a fixed-seed shuffle, with its entropy asserted in-test at or above 4.5 bits per character AND its exact value asserted against a golden constant on both sides (entropy alone cannot see the two duplicated generators diverging, since a changed stream would still measure ~5.32 bits; the golden also pins determinism, and is gitleaks-clean as a literal because a bare 40-character alnum run carries no keyword and no delimiter), now closes that hole; and option (c) never consults `DefaultPatterns` at all, so NO ScanText-level pin can alarm for it by construction, which is stated in the entry so a stale close cannot lean on the pins alone. Within the pattern set they do fail by design — a charset/length floor, key-name matching or any new `DefaultPatterns` entry THAT REACHES THESE SHAPES trips them (the qualification is the test file's own, and it matters: an entry reaching nothing in the corpus rightly leaves both pins green) — and that failure is the signal to re-point them and close the entry. Never close on assumption: the anchored controls in the same corpus are caught, and one of them sits INSIDE the negative test, which is what proves the specimens reached a working detector rather than a mis-wired or emptied one; the negative assertion is scoped to the token/secret kind family, so an unrelated widened pattern fails it under a DIFFERENT message rather than being credited as entropy coverage — and that message now names BOTH readings, because a secret or entropy detector shipping under a namespace the family list does not know (`secret:entropy`, say) arrives down the same branch, where telling the reader to adjust the specimen would hide the very coverage growth the pin exists to notice. Every credential-shaped specimen is assembled at run time — the discipline network_test.go already states for flagged network identifiers — so, beyond the one golden constant this entry discloses as measured clean, no literal of that shape enters this repo's history for a full-history secret scan to fire on.
2026-08-01 — iss-96 (item A6), a VERIFICATION milestone rather than an implementation: the transcript scanner's tracked coverage gaps re-checked against the network-identifier set A2 folded into DefaultPatterns, and the residue re-scoped in place. Two findings, both empirical rather than inspected. (1) A2 DID reach this path — every scanner consumer inherits the network set, so a non-reserved address or a LAN/device hostname in a captured transcript is now a finding (all five kinds — net:ipv4, net:ipv6, net:mac, net:lan_hostname, net:device_hostname — exercised on the transcript path itself in the same corpus, not inferred from their presence in the pattern set, and a flagged private address asserted REDACTED in the stored record at the store boundary); that class is therefore newly covered on this path since iss-96 was captured — it was never part of the entry's residue, which names unanchored secrets and home paths only, so this is coverage the re-check ESTABLISHES rather than a gap it closes. (2) The classes iss-96 actually names — a 40-character secret-key value with no prefix, a bare password, a prefix-less API token, and now a genuinely high-entropy 40-character value — still produce ZERO findings at the transcript path's own entry point, with or without a password:, api_key = or Authorization: Bearer key name beside them, because the TOKEN patterns are prefix-anchored APART FROM rp_session_key, which keys on the literal JSON field name "sessionKey" rather than on a generic key-name class, and no pattern measures entropy. The set as a WHOLE is not uniformly prefix-anchored and must not be described as such: the network kinds are an allowlist inversion, the identity kinds key on the probed identity, token:pem_private_key is a literal header, and Pattern.SkipAt already lets a pattern accept or reject a match by what SURROUNDS it — none of which reaches an unlabelled value, which is why the residue stands, and two of which (rp_session_key, SkipAt) are the shipped precedent remediation option (b) would generalise rather than introduce. Disposition: iss-96 stays OPEN with a dated verification section appended in place (the iss-24 precedent; a capture resolve would have had to state an action nobody took, and the ledger's resolution field is exactly that claim), re-scoped from "coverage may have moved" to a single unresolved DECISION between an entropy/charset detector with a length floor, key-name context matching, and the opt-in external-scanner adapter over this path only — three options that differ in REACH, not merely in false-positive cost, and saying otherwise would misdescribe them: (a) reads the value, so it is the only one that reaches an UNLABELLED value; (b) covers labelled values only and is structurally incapable of this entry's own first-named case, a bare secret-key value with no key name, because there is no key to match; (c) has whatever reach its ruleset delivers, and the measurement recorded in the entry corrects an earlier one that was wrong in both fixture and conclusion — re-run 2026-08-01 with pinned, sha256-verified gitleaks 8.24.3 default rules (gitleaks dir, no repo config) over a NAMED fixture, one specimen per line, comprising every case of TestTranscriptPathMissesUnanchoredEntropy's table, every line of the transcript TestCaptureStoresUnanchoredEntropyVerbatim captures, and delimiter probes on the same values: 21 lines, 6 findings, all generic-api-key, whose condition is keyword + =/: DELIMITER + entropy at or above 3.5 bits per character, so password: <passphrase>, --password=<passphrase>, api_key = <high-entropy> (the branch's own corpus case), session_token = <high-entropy> and session_token: <high-entropy> are all CAUGHT, while bare values with no key name, key names separated from their value by prose rather than a delimiter (the store fixture's hand-built session_token <high-entropy> line, which the earlier measurement mis-read as a key-name failure when the cause is the absent delimiter), and every sub-floor repetitive specimen whatever key name precedes it, all pass — so (c) as shipped reaches LABELLED high-entropy values, subsuming much of (b) and adding an entropy floor on top of it rather than being the narrowest option, and (a) remains the only one that reaches an UNLABELLED value; the anchored ghp_ control passing is a fixture artefact (36 repeated characters fall under gitleaks' own entropy filter — a realistic-entropy ghp_ token in the same run IS caught by github-pat), not a coverage claim. False-positive cost is the SECOND axis and lands hardest on (a) — a redaction false positive corrupts the record redaction exists to preserve — so reach and cost together are the open question and the bar is the maintainer's to set: grill-then-implement, not autonomous. The verification is PINNED in the tree rather than asserted in prose: TestTranscriptPathMissesUnanchoredEntropy at the pattern-set boundary and TestCaptureStoresUnanchoredEntropyVerbatim at the store boundary (each specimen present verbatim in the written record, the anchored token absent AND its fingerprintSpan fingerprint present — the byte-level mirror of maskSecret that sealLine actually applies on the Capture path, not maskSecret itself — since absence alone would also be satisfied by a store that dropped the line). THE PINS' REACH IS THE PATTERN SET, and the earlier claim that they "fail by design, never a silent pass" was too broad on two counts, both now fixed: the original specimens all REPEAT and measure 3.12, 2.16 and 2.75 bits per character, below the ~3.5-bit floor an entropy detector conventionally uses, so an entropy detector could have landed with every pin green — a 5.32-bit specimen assembled at run time from a fixed-seed shuffle, with its entropy asserted in-test at or above 4.5 bits per character AND its exact value asserted against a golden constant on both sides (entropy alone cannot see the two duplicated generators diverging, since a changed stream would still measure ~5.32 bits; the golden also pins determinism, and is gitleaks-clean as a literal because a bare 40-character alnum run carries no keyword and no delimiter), now closes that hole; and option (c) never consults DefaultPatterns at all, so NO ScanText-level pin can alarm for it by construction, which is stated in the entry so a stale close cannot lean on the pins alone. Within the pattern set they do fail by design — a charset/length floor, key-name matching or any new DefaultPatterns entry THAT REACHES THESE SHAPES trips them (the qualification is the test file's own, and it matters: an entry reaching nothing in the corpus rightly leaves both pins green) — and that failure is the signal to re-point them and close the entry. Never close on assumption: the anchored controls in the same corpus are caught, and one of them sits INSIDE the negative test, which is what proves the specimens reached a working detector rather than a mis-wired or emptied one; the negative assertion is scoped to the token/secret kind family, so an unrelated widened pattern fails it under a DIFFERENT message rather than being credited as entropy coverage — and that message now names BOTH readings, because a secret or entropy detector shipping under a namespace the family list does not know (secret:entropy, say) arrives down the same branch, where telling the reader to adjust the specimen would hide the very coverage growth the pin exists to notice. Every credential-shaped specimen is assembled at run time — the discipline network_test.go already states for flagged network identifiers — so, beyond the one golden constant this entry discloses as measured clean, no literal of that shape enters this repo's history for a full-history secret scan to fire on.
Frontmatter
| id | dcn-2608010000000001 |
|---|---|
| type | decision |
| date | 2026-08-01 |
.abcd/work/decisions/dcn-2608010000000001-iss-96-item-a6-a-verification-milestone.md
open on GitHub ↗ · commit history ↗
mentions2
- iss-24changelog fragments for abcd-managed repos: per-change entries land as files in a fragments directory (towncrier pattern) and are assembled into CHANGELOG.md at release, so concurrent PRs never conflict on the Unreleased block; candidate abcd verb/discipline — assembly could hook the release gate
- iss-96Now that transcripts are captured automatically on every session end, the scanner's secret-pattern coverage becomes load-bearing in a way it was not when capture was a manual verb nobody ran. Verified by live test: the bundled patterns DO catch anchored tokens (AKIA... access key IDs, ghp_/gho_/sk-ant- style prefixes) and absolute home paths, but they do NOT catch unanchored high-entropy values — an AWS SECRET access key (the 40-char base64 value, no prefix), a bare password, or a generic API token with no recognisable prefix all pass through into the store verbatim. This is the standard prefix-matching limitation and is pre-existing, not a regression; the point is that the blast radius changed. Consider entropy-based detection or the opt-in gitleaks adapter for the transcript path specifically, where the input is unstructured prose rather than curated source.