From 748543c35f7f89a4a80ca762b06110d6d08f402d Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 31 Oct 2026 01:05:57 +0100 Subject: [PATCH] Grant a node's engine any verb and event of its node seat on its own node, so a verb added to the contract needs no grants release first (issue 774) The grants part composed the engine's subscriptions from catalogue.EngineVerbs at its own mesh-sdk pin, so mesh-host #184's optional verb composition was refused on every node and every engine reopened its link every four minutes. Quick fix: re-pin the grants part. Thorough fix (this): the seat's subjects on the engine's node, any verb, as a module answers mesh.mod..tool.>; callers stay granted per verb. --- go/buscompose/buscompose_test.go | 15 +++++++++++++++ go/buscompose/engine.go | 14 ++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/go/buscompose/buscompose_test.go b/go/buscompose/buscompose_test.go index c936737..0a76bcf 100644 --- a/go/buscompose/buscompose_test.go +++ b/go/buscompose/buscompose_test.go @@ -320,6 +320,21 @@ func TestTheCopiedComposerComposesAsTheControllers(t *testing.T) { !MaySubscribe(perms, "$SRV.INFO."+EngineSeat) || MaySubscribe(perms, "mesh.seat."+EngineSeat+".tool.hand-over.two") { t.Errorf("node one hears %v", perms.Subscribe) } + // A verb or an event the seat's contract gains later is its engine's on its own node without a release of + // the grants part (2026-10-31: mesh-host #184's optional verb composition was refused on every node, the + // grants part's mesh-sdk pin predating it): the seat's subjects on its node, any verb, any event. + for _, verb := range []string{"composition", "compose", "a-verb-added-later"} { + if !MaySubscribe(perms, "mesh.seat."+EngineSeat+".tool."+verb+".one") || + !MaySubscribe(perms, "mesh.seat."+EngineSeat+".call."+verb+".one.messenger~one") || + MaySubscribe(perms, "mesh.seat."+EngineSeat+".tool."+verb+".two") || + MaySubscribe(perms, "mesh.seat."+EngineSeat+".call."+verb+".two.messenger~one") { + t.Errorf("node one does not answer %s on its own node alone: %v", verb, perms.Subscribe) + } + } + if !MayPublish(perms, "mesh.seat."+EngineSeat+".event.an-event-added-later.one") || + MayPublish(perms, "mesh.seat."+EngineSeat+".event.an-event-added-later.two") { + t.Errorf("node one does not say a later event on its own node alone: %v", perms.Publish) + } case u.Kind == KindNodeTools || u.Module == "messenger": if !MayPublish(perms, "mesh.seat."+EngineSeat+".tool.root-free.one") { t.Errorf("%s cannot call one's root-free", u.Username()) diff --git a/go/buscompose/engine.go b/go/buscompose/engine.go index bc504f3..9ccb790 100644 --- a/go/buscompose/engine.go +++ b/go/buscompose/engine.go @@ -39,13 +39,15 @@ func EnginePackagesGrants(node string) []string { // seat's events about its node, answers discovery for the seat, asks who answers what (the login shell's execute, ADR // 0563 ยง6), and asks the operator under asks.EngineAsker(node) on the router's seat as its holder declares it, as any // user of that seat is granted. +// +// Its verbs and events are granted as any verb and any event of the seat on its own node, not as the contract's list: +// the list is compiled into whichever mesh-sdk the grants part pins, so a verb the engine gained before the grants part +// was released was refused on every node and the engine reopened its link every few minutes (2026-10-31, the optional +// verb composition of mesh-host #184). As a module answers `mesh.mod..tool.>`, nothing is given away: no other +// principal may subscribe this seat's subjects of this node, and a caller is still granted each verb by name. func engineGrants(p Principal) (pub, sub []string) { - for _, v := range catalogue.EngineVerbs() { - sub = append(sub, "mesh.seat."+EngineSeat+".tool."+v.Name+"."+p.Node) - } - for _, e := range catalogue.EngineEvents { - pub = append(pub, "mesh.seat."+EngineSeat+".event."+e+"."+p.Node) - } + sub = append(sub, "mesh.seat."+EngineSeat+".tool.*."+p.Node) + pub = append(pub, "mesh.seat."+EngineSeat+".event.*."+p.Node) sub = append(sub, announcing(EngineSeat)...) pub = append(pub, discovering()...) tp, ts := seatTrafficGrants(SeatTrafficOf(asks.EngineAsker(p.Node), nil, p.Uses, nil))