From 335a64876e9bff5c09e7032f95160294a807e917 Mon Sep 17 00:00:00 2001 From: matthew-pilot Date: Thu, 28 May 2026 13:41:38 +0000 Subject: [PATCH 1/2] =?UTF-8?q?test:=20add=20TestLoadDuplicateNodeID=20?= =?UTF-8?q?=E2=80=94=20repro=20for=20PILOT-136?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a test that Load() must reject JSON with duplicate node_id entries. Current code silently overwrites (last entry wins), so this test FAILS until the fix lands. --- zz_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/zz_test.go b/zz_test.go index fadf207..9e38a94 100644 --- a/zz_test.go +++ b/zz_test.go @@ -112,6 +112,22 @@ func TestLoadEmptyHostnameSkipped(t *testing.T) { _ = Load(embeddedJSON) } +func TestLoadDuplicateNodeID(t *testing.T) { + t.Parallel() + err := Load([]byte(`{"agents":[ + {"hostname":"a","node_id":1}, + {"hostname":"b","node_id":1} + ]}`)) + if err == nil { + t.Fatal("Load with duplicate node_id must return an error") + } + // Also verify the list wasn't corrupted by the failed load. + if name, ok := IsTrusted(1); ok { + t.Fatalf("IsTrusted(1)=%q after failed Load — list must not be updated", name) + } + _ = Load(embeddedJSON) // restore +} + func TestAllReturnsCopy(t *testing.T) { t.Parallel() restore := SetForTest([]Agent{{Hostname: "a", NodeID: 1}}) From ed15d7aaf9c08db266bbf00e741007a39e9149ea Mon Sep 17 00:00:00 2001 From: matthew-pilot Date: Thu, 28 May 2026 13:41:45 +0000 Subject: [PATCH 2/2] fix(trustedagents): detect duplicate node_id in Load() and SetForTest (PILOT-136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Load() now returns a descriptive error when the JSON contains duplicate node_id entries (previously the last duplicate silently won). SetForTest panics on duplicates since test lists must be well-formed. Load protects the daemon's trusted-agents list from silently accepting the wrong agent when a maintainer accidentally duplicates a node_id. A bad refresh (network corruption, whatnot) that produces duplicate entries also fails safe — the previous known-good list is not replaced. Closes PILOT-136 --- data.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data.go b/data.go index 99ca2b8..578487b 100644 --- a/data.go +++ b/data.go @@ -87,6 +87,9 @@ func SetForTest(agents []Agent) (restore func()) { if a.Hostname == "" { continue } + if other, exists := idx[a.NodeID]; exists { + panic(fmt.Sprintf("SetForTest: duplicate node_id %d (hostnames %q and %q)", a.NodeID, other, a.Hostname)) + } idx[a.NodeID] = a.Hostname } mu.Lock() @@ -202,6 +205,9 @@ func Load(raw []byte) error { if a.Hostname == "" { continue // empty hostname: missing required field — drop } + if other, exists := idx[a.NodeID]; exists { + return fmt.Errorf("duplicate node_id %d in trusted-agents list: %q and %q", a.NodeID, other, a.Hostname) + } idx[a.NodeID] = a.Hostname } mu.Lock()