Skip to content

test(integration): fail when a pinned toolchain leaves upstream support (Go, Node, Debian) - #138

Merged
rappdw merged 1 commit into
mainfrom
test/go-support-freshness-check
Aug 12, 2026
Merged

test(integration): fail when a pinned toolchain leaves upstream support (Go, Node, Debian)#138
rappdw merged 1 commit into
mainfrom
test/go-support-freshness-check

Conversation

@rappdw

@rappdw rappdw commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Closes the gap that let the egress proxy's freshness mechanism go quiet for ~6 months with every test still green.

Rot vs regression — the distinction that cost real coverage

run-tests.sh asserts the base Go pin isn't an ancient minor, but that's a static floor: it keeps passing a pin that was supported when written and has since aged out. That is exactly what happened before 1.6.0.

golang:1.24-bookworm is a floating minor tag. It delivered 12 real patch releases while 1.24 was supported — then went silent once Go dropped it. The monthly --pull refresh kept running and kept refreshing the Debian layer, but no longer the Go stdlib implementing the proxy's TLS/HTTP/CONNECT I/O. Nothing errored. The pin never changed — the world did — so no static check could see it.

What's checked

Exactly the three rot-capable pins, against authoritative, self-updating sources (no hardcoded version list that could rot in its own right):

Pin Source
Go — proxy FROM golang:X.Y + base ARG GO_VERSION go.dev/dl/?mode=json (lists only supported majors)
Node — base setup_NN.x nodejs/Release schedule.json
Debian — base FROM debian:<suite>-slim endoflife.date

Python is deliberately not checked separately — sandy doesn't pin it, so Debian's clock is Python's clock. Rust (--default-toolchain stable), Bun, uv, the npm agent CLIs and the grok installer all resolve at build time and cannot rot.

Tiers: warn vs fail

Go is binary. Node and Debian degrade — Active LTS → Maintenance → EOL, and regular → LTS → EOL — and the middle tier still ships security fixes. So entering it warns ("plan the bump"); only EOL fails.

Validated against the pre-1.6.0 pins:

Node 22   → PASS + WARN "entered Maintenance LTS on 2025-10-21"
bookworm  → PASS + WARN "left REGULAR support on 2026-07-11"

Coverage note (the ironic part)

§49's proxy assertion is ^FROM golang:[0-9.]+-trixie — the version floats, so golang:1.24-trixie passes it today. The five guards from #131 protect the base image. So the proxy — the component parsing untrusted TLS ClientHello and HTTP Host bytes at the isolation boundary — was the one without a supported-minor guard. This closes that.

Verified live

Go     1.26   supported [1.25 1.26]           PASS
Node   24     Active LTS (EOL 2028-04-30)     PASS
Debian trixie regular support (EOL 2028-08-09) PASS

NEGATIVE CONTROL — simulated Go 1.24 pin:     FAIL

The negative control is the point: it proves the check detects the rot, rather than merely agreeing with today's state.

Two bugs caught by running the code rather than reading it

  1. This suite has no warn helper (only pass/fail/skip/info) — would have been a runtime "command not found".
  2. python3 - ARG <<HEREDOC takes the program from stdin, so the piped JSON was consumed by the heredoc and json.load(sys.stdin) saw nothing. Both parsers now use a single-quoted python3 -c, which leaves stdin free for the pipe and — unlike the double quotes behind the §68 corruption — performs no bash expansion.

Unreachable upstream skips rather than fails: a flaky fetch must not red a suite that's otherwise about sandy's behavior.

25 headers/guards/closers balanced; run-tests.sh §80(b) unaffected; zero new shellcheck warnings; bash -n clean.

🤖 Generated with Claude Code

Adds section 22: LIVE checks that every toolchain sandy PINS is still upstream-
supported — Go (proxy + base image), Node (base image), and Debian (base image).

This catches ROT, not regression, and the distinction cost real security
coverage. run-tests.sh asserts the base Go pin is not an *ancient* minor, but
that is a static floor: it keeps passing a pin that was supported when written
and has since aged out. Exactly what happened before 1.6.0 — the proxy pinned
golang:1.24-bookworm, a floating minor tag that delivered 12 patch releases
while 1.24 was supported, then went silent for ~6 months once Go dropped it.
The monthly --pull refresh kept running and kept refreshing the Debian layer,
but no longer the Go stdlib implementing the proxy's TLS/HTTP/CONNECT I/O.
Nothing failed; the mechanism went quiet and no test could see it.

Only a live check sees that, so it lives in the integration suite: this one has
network, run-tests.sh deliberately does not. Sources are authoritative and
self-updating, so there is no hardcoded version list to rot in its own right:
go.dev/dl (lists only supported majors), nodejs/Release schedule.json, and
endoflife.date for Debian.

Go is binary (supported or not). Node and Debian DEGRADE instead — Active LTS
-> Maintenance -> EOL, and regular -> LTS -> EOL — and the middle tier still
ships security fixes, so entering it WARNS (plan the bump) while only EOL
FAILS. Verified against the pre-1.6.0 pins: Node 22 warns 'entered Maintenance
2025-10-21' and bookworm warns 'left regular support 2026-07-11'.

Scope is exactly the three rot-capable pins. Python is deliberately not checked
separately: sandy does not pin it, so Debian's clock IS Python's clock.
Rust (--default-toolchain stable), Bun, uv, the npm agent CLIs and the grok
installer all resolve at build time and cannot rot.

Coverage note: §49's proxy assertion is '^FROM golang:[0-9.]+-trixie', whose
version part floats, so golang:1.24-trixie passes it today. The proxy — which
parses untrusted wire bytes at the isolation boundary — was the one WITHOUT a
supported-minor guard. This closes that.

Unreachable upstream skips rather than fails: a flaky fetch must not red a
suite that is otherwise about sandy's own behavior.

Two bugs caught by testing the code rather than reading it: this suite has no
'warn' helper (pass/fail/skip/info only), and 'python3 - ARG <<HEREDOC' takes
the PROGRAM from stdin, so a piped JSON payload was consumed by the heredoc and
json.load(sys.stdin) saw nothing. Both fixed; the parsers now use a SINGLE-
quoted python3 -c, which leaves stdin free for the pipe and (unlike the double
quotes behind the §68 corruption) performs no bash expansion.

Verified live: Go 1.26 supported [1.25 1.26]; Node 24 Active LTS (maint
2026-10-20, EOL 2028-04-30); Debian trixie in regular support (EOL 2028-08-09).
Negative control: a simulated Go 1.24 pin FAILS. 25 headers/guards/closers
balanced; run-tests.sh §80(b) unaffected; zero new shellcheck warnings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@rappdw
rappdw force-pushed the test/go-support-freshness-check branch from 82d1f1d to ec773d4 Compare August 12, 2026 13:31
@rappdw rappdw changed the title test(integration): fail when a pinned Go minor leaves upstream support test(integration): fail when a pinned toolchain leaves upstream support (Go, Node, Debian) Aug 12, 2026
@rappdw
rappdw merged commit 2d40593 into main Aug 12, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant