Repository navigation
feat: a confirmed endpoint is named on the port it answered on (ADR 0082) - #123
Merged
Merged
Conversation
A restored cache reported six SA5011 findings in files the branch did not
touch, twice, on a tree byte-identical to a passing main — the changed files
were behind `//go:build e2e`, which `.golangci.yml` sets no build tag for, so
the linter never read them. Deleting the cache entry and re-running gave 0
issues.
The findings were false: each site calls t.Fatal in the nil branch before
dereferencing, and t.Fatal calls runtime.Goexit. Seeing that takes knowing
testing.common.Fatalf does not return, which a partial analysis cache drops.
warm 15.6s, cold 39.2s — 24 seconds a run
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeZECJXTDHL6Nts95eKMJA
…082)
Three facts about a workload's debug surface already shipped. The binary
links net/http/pprof, per digest. The process listens on these ports, some
loopback, per workload. Six targets confirmed, per nobody — the prober's
answer left the cluster as four integers.
So the payloads could not say which port served the mux. In the golden,
shop/web links pprof and binds 8080 and loopback 6060; one of those serves
/debug/pprof/heap to anything that can reach the pod and the other serves it
to nothing, and the difference was unrecoverable. An inference from "links
pprof" and "has a routable port" is right most of the time and wrong
silently, which is the worst thing a report can be.
The answer is stamped onto the port, in the payload that already names the
workload: the prober's key is {digest, port} and a record carries both, so
the join is a lookup. Prober.Stamp does it — the package that owns an answer
writes it down — and the store stays a pure join of what nodes reported.
Empty is "not asked", never "not pprof". Candidates drops loopback ports
before the funnel, so no-answer is the common case; a boolean would have
collapsed the two claims this payload needs to keep apart.
inventory.Port is new and carries the node's observation plus the
controller's answer. nodescan.ListeningPort keeps carrying only what a node
can know, which is what crosses the channel — one field on the node's type
that the node never fills would be shorter and would blur that line.
No new request, no new read, no new connection: the probe ADR 0057
authorised already established this, and what changes is where it is written.
go test ./... pass
golangci-lint (pinned v2.11.4) 0 issues
make inventory-e2e PASS (726s)
listening_ports names the endpoint: map[6060:confirmed 9090:]
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeZECJXTDHL6Nts95eKMJA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two slices. The CI one-liner rides along because it is one line, and because the payload change below is exactly the kind of PR a false red costs the most on.
1.
listening_portsnames the port that served pprof (ADR 0082)Three facts about a workload's debug surface already shipped; the fourth did not.
net/http/pprofgo_build.pprof_endpointlistening_portscollection_coverage.pprofThe gap could not be closed by joining what shipped. In the golden payload
shop/weblinks pprof and binds 8080 and loopback 6060 — one of those serves/debug/pprof/heap, the contents of the process's memory, to anything that can reach the pod, and the other serves it to nothing. An inference from "links pprof" and "has a routable port" is right most of the time and wrong silently.The shape
The prober's key is
Target{ImageDigest, Port}and alistening_portsrecord carries both, so the join is a lookup and needs no new payload, no new kind, and no new identity — the workload is already named on that record.Prober.Stampwrites it: the package that owns the answer writes it down, and the store stays a pure join of what nodes reported.Empty is "not asked", never "not pprof."
Candidatesdrops loopback ports before the funnel, so no-answer is the common case. A boolean would have collapsed the two claims this payload has to keep apart.inventory.Portis new and carries the node's observation plus the controller's answer.nodescan.ListeningPortgoes on carrying only what a node can know, which is what crosses the channel. One field on the node's type that the node never fills would have been shorter and would have blurred that line.What the ADR argues, beyond the mechanism
Verification
The sample binds both: 6060 routable and serving the index, 9090 on loopback and never asked. One says so and the other stays silent.
Unit tests cover the stamp, including that an answer does not cross builds — the digest is half the key. The golden payload shows all three states plus the empty one.
2. The linter runs without its analysis cache
On 2026-09-16 a restored cache reported six
SA5011findings in files the branch did not touch, twice, on a tree byte-identical to a passingmain— the changed files were behind//go:build e2e, which.golangci.ymlsets no build tag for, so the linter never read them. Deleting the cache entry and re-running gave0 issues.The findings were false: each site calls
t.Fatalin the nil branch before dereferencing, andt.Fatalcallsruntime.Goexit(). Seeing that takes knowingtesting.common.Fatalfdoes not return, which a partial analysis cache drops.Measured: warm 15.6s, cold 39.2s. 24 seconds a run for the whole class of false red.
🤖 Generated with Claude Code
https://claude.ai/code/session_01KeZECJXTDHL6Nts95eKMJA