diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 42e74daabb..ad05614c18 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -95,29 +95,16 @@ jobs: run: pnpm check:query-options-erasure # Raw control-byte guard (#3127 / #4890 / #5157 / #5460). Scans every - # tracked TEXT file for a raw ASCII control byte — 0x00-0x08, 0x0b, 0x0c, - # 0x0e-0x1f and 0x7f, i.e. everything except tab/LF/CR. Two distinct - # harms, one gate: - # • A literal U+0000 makes grep/ripgrep treat the whole file as binary and - # silently return ZERO matches — the file drops out of code search and - # out of every grep-based lint, with no error saying so. Nothing else - # catches it: git sniffs only the first 8000 bytes to decide binary-ness, - # and protocol.ts carried its NUL at offset 147230, so it kept diffing as - # ordinary text through review. That blind spot let six files accumulate - # the same defect. - # • The other C0 controls still match in grep but RENDER AS NOTHING, so a - # load-bearing separator reads as an empty string in the diff and in - # review: `keyParts.join('<0x01>')` shows up as `keyParts.join('')`. - # Four tracked source files carried those past the NUL-only gate until - # #5157 widened the scan surface; PR #5140 is the case that found it, - # when a 0x01 sitting 14 bytes from a caught NUL went unfixed. - # • DEL (0x7f) is in the set for the same reason, added by #5460. It is - # not a C0 control — it sits alone past the printable range — so the - # C0-shaped set could not reach it, and two raw specimens survived in - # the CLI's password prompts nine lines below a 0x03 #5157 had just - # escaped, reading as `case ''`. The set is drawn by the accident - # source (a tool materialising an escape into its byte), and that - # source does not pick byte values. + # tracked TEXT file for a raw ASCII control byte and fails on any hit. + # WHICH bytes are in the set and WHY each is rejected are stated and argued + # once, in the gate script's header — `scripts/check-nul-bytes.mjs`. That + # header is authoritative and this comment cites it rather than restating it + # (#5579 established the footing, #5681 applied it here). The one-line + # summary, for whoever is reading this because the step just went red: the + # set is every ASCII control character except tab/LF/CR, drawn by the + # ACCIDENT SOURCE — an editing tool materialising an escape into its byte — + # and not by byte semantics, so "mine is not a NUL" is never a reason to read + # a hit as a false positive. # The command name stays `check:nul-bytes` for continuity — see the script's # header for why. Authors must write the unicode escape instead of the byte. - name: Raw control-byte guard diff --git a/scripts/check-nul-bytes.mjs b/scripts/check-nul-bytes.mjs index b527e8eb16..832a521bdb 100644 --- a/scripts/check-nul-bytes.mjs +++ b/scripts/check-nul-bytes.mjs @@ -3,9 +3,12 @@ // // check-nul-bytes -- rejects raw ASCII control bytes in every tracked TEXT file. // -// Scanned set (#5157, #5460): 0x00-0x08, 0x0b, 0x0c, 0x0e-0x1f and 0x7f -- every -// ASCII control character except the three bytes that ARE ordinary text -// structure: tab (0x09), LF (0x0a), CR (0x0d). Equivalently +// Scanned set (#5157, #5460): every ASCII control character except the three that +// ARE ordinary text structure -- tab, LF, CR. The `IS_SCANNED` table below is the +// authoritative statement of which bytes those are; this line deliberately no +// longer transcribes the list (#5681), and the pasteable class on the next line is +// DERIVED from that table rather than copied (see "The character class is written +// down once" below). Equivalently // `[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]`. // // #5157 drew that set as "C0 minus tab/LF/CR", matching the pattern #4890's own @@ -290,11 +293,12 @@ export function scannedCharClass() { * Those are HISTORICAL RECORDS of one widening each, and one of them states * the pre-DEL set correctly for the change it describes. Forcing them to * equal today's set would falsify the record. - * - The prose ENUMERATIONS of the same bytes -- this header's opening line and - * the `.github/workflows/lint.yml` step comment. Those are sentences, not - * pasteable classes; prose stays on the #5579 footing -- cite this header, - * do not restate it. (Which is why this list names them rather than quoting - * them: a ledger entry that spelled the bytes out would be one more copy.) + * - The prose STATEMENTS of the same set -- this header's opening line and the + * `.github/workflows/lint.yml` step comment. Those are sentences, not + * pasteable classes; prose stays on the #5579 footing -- cite this header, do + * not restate it -- and as of #5681 neither of them enumerates the bytes any + * more. (Which is why this list names them rather than quoting them: a ledger + * entry that spelled the bytes out would be one more copy.) * - The non-ASCII guard `[^\x00-\x7f]` quoted in the isLikelyEmail changeset * and the plugin-auth CHANGELOG: a different regex about input validation, * unrelated to this set.