S3: the seat-list verbs answer a proved operator's session

seat-list-again answered person.<name> and the healers, but every call through
the mesh MCP server is proved as its machine's tool runner (issue 627), so no
operator's session could make a node read its seat list again. node-tools now
stands for that session; the read seat-list is open to every proved caller, as
ADR 0636 §7 limits only the read again. The verb names come from the contract.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-10 00:32:44 +01:00
parent 81bc0cc388
commit 7bf7e29a32
2 changed files with 16 additions and 9 deletions
+10 -8
View File
@@ -52,17 +52,19 @@ const (
// ActManifestReads reads the reader capabilities this engine states (novox/hq ADR 0618 §3).
ActManifestReads = nodeengine.VerbManifestReads
// ActSeatList reads the seat list this engine holds and what it waits for; ActSeatListAgain makes it read the list now
// (novox/hq ADR 0636 §7). The node-engine seat's definition carries both verbs, which answer only the operator and the
// healers.
ActSeatList = "seat-list"
ActSeatListAgain = "seat-list-again"
// (novox/hq ADR 0636 §7). The node-engine seat's definition carries both verbs.
ActSeatList = nodeengine.VerbSeatList
ActSeatListAgain = nodeengine.VerbSeatListAgain
)
// SeatListCallers are who may call the engine's two seat-list verbs: every operator's session and the healers (novox/hq
// ADR 0636 §7, the node-engine seat's definition: the operator and the healers).
// SeatListCallers are who may call the engine's two seat-list verbs (novox/hq ADR 0636 §7). The read is open to every
// proved caller: the record limits only the read again, and the list holds nothing secret. The read again answers the
// operator's sessions and the healers. A call through the mesh MCP server, and nox, is proved only as its machine's tool
// runner (<node>.node-tools, issue 627), so node-tools stands for an operator's session until a session is proved; without
// it the verb answered nobody but the healers, and no healer calls it (issue 1966).
var SeatListCallers = stdio.VerbCallers{
ActSeatList: {stdio.AnyPerson, "mesh-healers"},
ActSeatListAgain: {stdio.AnyPerson, "mesh-healers"},
ActSeatList: {stdio.AnyCaller},
ActSeatListAgain: {stdio.AnyPerson, "node-tools", "mesh-healers"},
}
// The states of an act: asked, done and refused are also the seat's events.
+6 -1
View File
@@ -301,8 +301,13 @@ func TestALinkThatHearsHandOversIsGivenTheQueues(t *testing.T) {
{"packages", EngineToolSubject("packages", "n1") + " " + `{"write":true}`, `"key":null,"wrote":true`},
{"packages", EngineToolSubject("packages", "n1") + " " + `{"write":"true"}`, `"note":"the engine has written no key for this node yet`},
{"manifest-reads", EngineToolSubject("manifest-reads", "n1"), `"manifest-reads":["form:a","seat:b"],"node":"n1","stated-at":"2026-11-04T10:00:00Z","v":1`},
// ADR 0636 §7: the seat-list verbs answer every operator's session and the healers, no other module.
// ADR 0636 §7: the read seat-list answers every proved caller; seat-list-again every operator's session, proved
// as a person or, through the mesh MCP server, as its machine's tool runner (issue 627, issue 1966), and the
// healers, no other module.
{"seat-list", "mesh.seat.node-engine.call.seat-list.n1.person~jochen", `"held":true`},
{"seat-list", "mesh.seat.node-engine.call.seat-list.n1.shanks~node-tools", `"held":true`},
{"seat-list", "mesh.seat.node-engine.call.seat-list.n1.ace~messenger", `"held":true`},
{"seat-list-again", "mesh.seat.node-engine.call.seat-list-again.n1.shanks~node-tools", `"read":true`},
{"seat-list-again", "mesh.seat.node-engine.call.seat-list-again.n1.person~jochen", `"read":true`},
{"seat-list-again", "mesh.seat.node-engine.call.seat-list-again.n1.ace~mesh-healers", `"read":true`},
{"seat-list-again", "mesh.seat.node-engine.call.seat-list-again.n1.ace~messenger", `not on the holder's caller list for seat-list-again`},