Commit 81dbf2d
fix(ci): confirm deny-list negatives too, and fix a cwd-relative shallow probe (#524)
Follow-up to #522, which merged before this landed. **#522 is live on
`main` now, so these two defects are live on ~300 consumers.**
Both were found by adding a test for the path production actually takes.
Cases 1–12 of the fixture suite run against a **complete** `git init`
repo; CI runs against a **partial** clone (`--filter=tree:0`). Nothing
tested the code that protects production, and it had two bugs.
## 1. The deny-list's *negative* still trusted local `merge-base` on a
partial clone
A treeless clone resolves every commit, so the API fallback was gated on
"commits do not resolve" — making it **dead code in CI**. Trace
`awesome-haskell` (pin `5a93d9d5`, which predates the Hypatia fix and
*must* be denied):
```
pin_is_known_bad -> local branch taken -> wrong negative -> continue -> NOT denied
classify_pin -> same mis-fire -> API says ahead=90 -> OUT_OF_WINDOW -> notice
-> PASS, while running the frozen scanner
```
That is the exact false green the deny-list exists to prevent, on the
very cohort that proved `merge-base` is unreliable there.
**Fix:** a local **positive** is still trusted (no false positives
observed, and a deny must not require the network), but a local
**negative** is accepted only from a *complete* clone — otherwise it is
confirmed server-side.
## 2. `clone_is_complete` used a cwd-relative git-dir
`rev-parse --git-dir` returns `.git`, and the check was `[ -e
"$gd/shallow" ]` — which resolves against the **CWD**, i.e. the
*consumer's* checkout, which `actions/checkout` makes shallow by
default. So `.git/shallow` would nearly always exist and **every**
standards clone would be classified incomplete, permanently masking the
complete-clone fast path.
Now uses `--absolute-git-dir`. Test 13c failed for exactly this reason,
which is how it was found.
## 3. `governance-reusable.yml` passes `GITHUB_TOKEN` to the staleness
step
The server-side confirmation is unauthenticated — 60/hr per runner IP —
and exhausting it degrades the gate to `::warning`. That fail-open is
deliberate and **loud** (two warnings naming the pin; never a silent
pass), and the common path never calls the API at all, since a genuine
deny is a local positive. A token removes the cliff.
This reaches a consumer only once it re-pins past this commit — the
script is read from `standards` HEAD, but the job definition comes from
the pinned SHA — so it lands naturally with the propagation the
deny-listed pins need anyway.
## Tests: 16 → 19, still hermetic
The API is pointed at a closed port (`http://127.0.0.1:1`), so these are
fast and offline:
```
PASS: partial clone: local positive still denies without the network
PASS: partial clone: unverifiable deny-list check is reported SKIPPED, not passed
PASS: complete clone: local negative is trusted silently (no SKIPPED warning)
```
`run_case_out` gained a leading-`!` inversion so a test can assert the
gate did **not** say something. Suite verified from two different
working directories, since defect (2) was cwd-dependent. 19/19 pass on
top of current `main`; `shellcheck -S warning` clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>1 parent d13ff9f commit 81dbf2d
4 files changed
Lines changed: 97 additions & 5 deletions
File tree
- .github/workflows
- docs/decisions
- scripts
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
47 | 57 | | |
48 | 58 | | |
49 | 59 | | |
| |||
Lines changed: 20 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
223 | 223 | | |
224 | 224 | | |
225 | 225 | | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
70 | 73 | | |
71 | 74 | | |
72 | 75 | | |
| |||
82 | 85 | | |
83 | 86 | | |
84 | 87 | | |
| 88 | + | |
85 | 89 | | |
86 | 90 | | |
87 | 91 | | |
| |||
213 | 217 | | |
214 | 218 | | |
215 | 219 | | |
216 | | - | |
217 | | - | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
218 | 226 | | |
219 | 227 | | |
220 | 228 | | |
| |||
235 | 243 | | |
236 | 244 | | |
237 | 245 | | |
238 | | - | |
| 246 | + | |
239 | 247 | | |
240 | 248 | | |
241 | 249 | | |
| |||
298 | 306 | | |
299 | 307 | | |
300 | 308 | | |
301 | | - | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
302 | 316 | | |
303 | 317 | | |
304 | 318 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
94 | | - | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
95 | 100 | | |
96 | 101 | | |
97 | 102 | | |
| |||
214 | 219 | | |
215 | 220 | | |
216 | 221 | | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
217 | 265 | | |
218 | 266 | | |
219 | 267 | | |
| |||
0 commit comments