An independent cross-family review of the jq-1.6 fix found two further ways the
docs-only exemption can fire over an incomplete file list — both reachable with NO
transport error, so neither had anything to do with the original bug.
1. HIGH — a path containing a newline. `chunk` flattens paths into newline-delimited
text before the allow-list grep, so a filename of "safe.md\ndocs/Program.cs" splits
into two lines that BOTH match the allow-list, while the real single path ends in
.cs. Git permits newlines in filenames and the reviewer reproduced the bypass
against this hook. Now rejected outright at the row-schema guard, on both
`filename` and `previous_filename`: no docs path contains a control character, so
failing closed costs nothing.
2. HIGH — a short page read as the last page. `n < 50` assumed the server's page size
is the 50 we requested, but Gitea caps `limit` at the server-wide
MAX_RESPONSE_ITEMS (default 50, configurable) and may return fewer. A 30-row docs
page followed by a page of code completed the enumeration over a PARTIAL list.
Only a validated EMPTY page may now terminate it; the page<=40 cap still fails
closed, and the cost is one extra request.
3. MEDIUM — the enumeration was not bound to one head. Paging is several round-trips,
so a force-push between them assembles a list belonging to no single commit: page 1
from head A plus a short docs tail from head B, with B's code page never read. The
head sha is re-read after enumeration and the exemption refused if it moved.
All three mutation-verified: reverting each fix reddens exactly its own test and
nothing else. A positive control (short page then empty page) pins that the stricter
terminator still exempts a genuinely docs-only PR, so "never terminate early" cannot
be satisfied by never exempting anything. 118 passed under BOTH jq 1.8.2 and jq 1.6.
The record now states the generalisable lesson: every defect here was an
exhaustiveness failure in an enumeration whose completeness is load-bearing. When a
security decision depends on having seen ALL of something, the termination condition
must be positive and explicit, never inferred from a proxy.
Refs #643, #631