fix(loader): one duplicate node_id should not disable the entire trusted-agents feed#33
Merged
TeoSlayer merged 2 commits intoJul 24, 2026
Conversation
Load() treated a single duplicate node_id as fatal — it returned before committing the parsed roster, so one bad row discarded the entire feed and every daemon fell back to its embedded snapshot (or, for a binary built from a colliding list, to an empty trust set). A live example: pilot-mom and pilot-director share node_id 243113, which took down the whole 438-entry list. New behavior: on a duplicate node_id, drop EVERY entry for that node_id and keep loading the rest. The security contract is preserved exactly — an ambiguous node_id stays untrusted (neither the first entry nor a later pin may silently win), which is what the two duplicate tests already asserted; only their "returns an error" expectation changes. This mirrors how the loop already skips node_id==0 and empty-hostname entries with continue. Scope: duplicate handling only. Malformed-JSON and bad-pin paths still return an error (unchanged). Verified: gofmt/vet/build clean; full suite green; drop-dup-keep-rest confirmed (triplicated id voided, unique neighbors survive); FuzzLoad ~1.2M execs, no failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142ryqVGEmJN66VZtCC7wFD
TeoSlayer
enabled auto-merge
July 24, 2026 10:34
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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.
Problem
Load()treats a single duplicatenode_idas fatal for the whole list — itreturns the error before the parsed roster is committed:So one bad row discards the entire feed on every hourly refresh, and each daemon falls back to its embedded snapshot. Worse, if the embedded list itself carries the duplicate (a binary built from a colliding feed),
init()hits the same error and setsbyNodeto an empty map — booting with zero trusted agents.TestEmbeddedListLoadsdoesn't catch that; it only checksbyNode != nil.This is not hypothetical — it is happening on
mainright now:pilot-momandpilot-directorsharenode_id 243113, which takes down the full 438-entry list. (The companion PR fixes that data; this PR makes the loader resilient to the next one.)Change
On a duplicate
node_id, drop every entry for that node_id and keep loading the rest of the list — instead of failing the whole load. Fourteen lines indata.go, mirroring how the loop alreadycontinues pastnode_id==0and empty-hostname entries.Why "drop all", not "keep first"
The repo's own tests document the security contract: an ambiguous
node_idmust not be trusted, and a colliding pin must not "silently win" (TestLoad_DuplicateWithPinsRejected,FuzzLoad's fail-closed invariant). "Keep the first entry" would violate that — it lets the first pin win on an ambiguous binding. Dropping all entries for the duplicated id preserves the exact property: the ambiguous node stays untrusted, while the other 437 good entries still load.That is why the two duplicate tests keep their security assertions unchanged — only their "returns an error" expectation flips:
TestLoadDuplicateNodeIDTestLoad_DuplicateWithPins…Scope
Duplicate handling only. Malformed-JSON and bad-pin paths still
returnan error (unchanged).SetForTest's panic-on-dup is unchanged.Verification
gofmt -lclean ·go vetclean ·go build ./...cleango test ./...green (full suite), includingTestLoad_BadPinRejected,TestLoad_ErrorBranch, zero/empty-hostname filtersFuzzLoad~1.2M executions over 12s — no panics, invariants hold🤖 Generated with Claude Code
https://claude.ai/code/session_0142ryqVGEmJN66VZtCC7wFD