The node seat node-engine served on the engine's link: its verbs with their proven caller, its acts kept in its own state, a hand-over or access act asked of the operator as node-engine-<node> and performed only on the warrant (issue 774, ADR 0563 §1-§3)

This commit is contained in:
2026-10-28 20:35:33 +01:00
parent 479ac71050
commit aaffc19232
9 changed files with 1195 additions and 7 deletions
+44
View File
@@ -199,6 +199,30 @@ func TestALinkThatHearsHandOversIsGivenTheQueues(t *testing.T) {
}
stop()
<-served
// 774 (ADR 0563 §1): a call of the node seat reaches its verb with its caller as the subject proves it, unproven on
// the subject that names none; a verb the seat does not serve is refused, and the answer is a tool's envelope.
t.Run("a call of the node seat reaches its verb with its proven caller", func(t *testing.T) {
h := &HandActs{Node: "n1", State: &FileState{Path: t.TempDir() + "/" + HandActsFile},
RootFree: func() RootVerdict { return RootVerdict{Machine: "n1", Free: true, Why: "judged"} },
JudgeDirectories: func(by string) (string, error) { return "judged for " + by, nil }}
for _, row := range []struct{ verb, subject, want string }{
{"judge-directories", "mesh.seat.node-engine.call.judge-directories.n1.shanks~node-tools", `"said":"judged for shanks.node-tools"`},
{"judge-directories", EngineToolSubject("judge-directories", "n1"), `"said":"judged for unproven"`},
{"judge-directories", "mesh.seat.node-engine.call.judge-directories.n2.shanks~node-tools", `"said":"judged for unproven"`},
{"root-free", "mesh.seat.node-engine.call.root-free.n1.ace~messenger", `"free":true`},
{"unserved", "mesh.seat.node-engine.call.unserved.n1.x", `"error":"the node seat node-engine serves no verb \"unserved\""`},
} {
if got := string(AnswerEngineCall(h.Call, row.verb, "n1", row.subject, []byte(`{}`))); !strings.Contains(got, row.want) ||
!strings.Contains(got, `"node":"n1"`) {
t.Errorf("%s on %s: %s", row.verb, row.subject, got)
}
}
acts, _ := h.Acts(0)
if got := acts.(map[string]any)["acts"].([]HandAct); len(got) != 3 || got[0].Caller != "unproven" ||
got[2].Caller != "shanks.node-tools" || got[2].Act != ActJudgeDirectories {
t.Errorf("the judgements are recorded as %+v", got)
}
})
}
// **Against a real server**: a signed request on the node's own subject is answered; one on another node's is
@@ -237,4 +261,24 @@ func TestNatsAHandOverIsAskedOfTheNode(t *testing.T) {
if len(handled) != 1 {
t.Fatalf("handled %d asks; want only the one with a reply", len(handled))
}
// 774 (ADR 0563 §1): the node seat is served on this node's subjects alone, naming its caller, and said to discovery.
t.Run("the node seat is served on this node and discovered", func(t *testing.T) {
l.ServeEngineSeat(func(c EngineCall) (any, error) { return c.Verb + " for " + c.Caller, nil })
reply, err := conn.Request("mesh.seat.node-engine.call.acts."+m.Node+".shanks~node-tools", []byte(`{}`), 5*time.Second)
if err != nil || !strings.Contains(string(reply.Data), `"result":"acts for shanks.node-tools"`) {
t.Fatalf("the call answered %v, %v", reply, err)
}
if _, err := conn.Request(EngineToolSubject("acts", "another"), []byte(`{}`), 300*time.Millisecond); err == nil {
t.Fatal("another node's verb was answered here")
}
for seat, want := range map[string]bool{EngineSeat: true, "node-login-shell": false} {
verb := "acts"
if !want {
verb = "execute"
}
if heard, err := l.HeardServed(seat, verb); err != nil || heard != want {
t.Errorf("discovery hears %s.%s here: %v, %v", seat, verb, heard, err)
}
}
})
}