Answer the controller's own verbs, root-free among them, from the serving controller alone (hq ADR 0259 §8)
The confirmation review asked who may answer root-free on the bus. Composed from the controller's own manifest, the module principal of the machine running the controller and that machine's runtime were granted the controller seat's tool subjects too: either could answer root-free, and the runtime's credential is one an agent on that machine may hold. The controller's seat is now served by the controller principal alone, in grants and memberships; TestOnlyTheServingControllerMayAnswerRootFree failed before (3 answerers) and passes. And a machine waiting for its first setuid search is not root-free, whatever ADR 0266's quiet window does to the self-check.
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/novox/mesh-controller/internal/catalogue"
|
||||
"github.com/novox/mesh-controller/internal/conditions"
|
||||
"github.com/novox/mesh-controller/internal/inventory"
|
||||
"github.com/novox/mesh-controller/internal/link"
|
||||
)
|
||||
|
||||
var rootNow = time.Date(2026, 10, 9, 12, 0, 0, 0, time.UTC)
|
||||
@@ -196,3 +197,31 @@ func TestRootFreeIsAnsweredOnlyByTheServingController(t *testing.T) {
|
||||
t.Error("a verb that takes no list took one")
|
||||
}
|
||||
}
|
||||
|
||||
// The confirmation review of 2026-10-09: ADR 0266's quiet window (#175) keeps the self-check from raising
|
||||
// agent-can-become-root while the node-engine's first setuid search runs. It must not make root-free answer free:
|
||||
// root-free needs a complete, fresh verdict. A verdict still waiting for the search is "not judged" to
|
||||
// agentConfined, so the machine is not root-free, whatever the quiet says — and the same statement, complete
|
||||
// and healthy, is the control.
|
||||
func TestAMachineWaitingForItsFirstSetuidSearchIsNotRootFree(t *testing.T) {
|
||||
now := rootNow
|
||||
statement := func(state, reason string) inventory.NodeHealth {
|
||||
return inventory.NodeHealth{Node: "anchor", Contract: link.RootContract, SaidAt: now, HeardAt: now,
|
||||
Resources: []inventory.ResourceHealth{{Module: "claude-code", Resource: "agent", Kind: link.KindAccount,
|
||||
Target: "agents", State: state, Reason: reason, Root: link.RootNever}}}
|
||||
}
|
||||
judged := func(h inventory.NodeHealth) rootVerdict {
|
||||
confined, why := judgedConfined("agents", h, true, now)
|
||||
return judgeRoot(rootFacts{Machine: "anchor", AgentNamed: true, Confined: confined, ConfinedWhy: why}, now)
|
||||
}
|
||||
if v := judged(statement(link.StateHealthy, "")); !v.Free {
|
||||
t.Fatalf("the control: a complete healthy verdict, fresh: %+v", v)
|
||||
}
|
||||
pending := statement(link.StateUnknown, link.ReasonRootPending+": the search runs")
|
||||
if rootVerdictKind("agents", pending, true, now) != verdictPending {
|
||||
t.Fatal("the statement is not one the quiet window counts as waiting for the search")
|
||||
}
|
||||
if v := judged(pending); v.Free {
|
||||
t.Errorf("a machine whose first setuid search is pending was judged root-free: %+v", v)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user