From 20a6dc4920f80ed8c30508f8a2bcf95cdb5dcdaa Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 25 Oct 2026 20:50:51 +0100 Subject: [PATCH] A grant says whether it names a module's accounts on a node, for the assigner and the compose verb (ADR 0546) --- go/delivery/assigner_test.go | 16 ++++++++++++++++ go/delivery/grants.go | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/go/delivery/assigner_test.go b/go/delivery/assigner_test.go index 08ecca2..6b54e1d 100644 --- a/go/delivery/assigner_test.go +++ b/go/delivery/assigner_test.go @@ -298,4 +298,20 @@ func TestControllerGrant(t *testing.T) { if _, err := EncodeControllerGrant(ControllerGrant{Accounts: []string{""}}); err == nil { t.Errorf("a grant naming an empty account was accepted") } + g := ControllerGrant{Accounts: []string{"ace.mesh-build-go", "shanks.mesh-mail.reader"}} + for _, c := range []struct { + g ControllerGrant + node, module string + names bool + }{ + {g, "ace", "mesh-build-go", true}, + {g, "shanks", "mesh-mail", true}, + {g, "g14", "mesh-build-go", false}, + {g, "ace", "mesh-build", false}, + {ControllerGrant{}, "novox", "nats", true}, + } { + if got := c.g.NamesNode(c.node, c.module); got != c.names { + t.Errorf("%v names %s.%s: %v, want %v", c.g.Accounts, c.node, c.module, got, c.names) + } + } } diff --git a/go/delivery/grants.go b/go/delivery/grants.go index 39e602c..01d5655 100644 --- a/go/delivery/grants.go +++ b/go/delivery/grants.go @@ -73,3 +73,20 @@ func DecodeControllerGrant(data []byte) (ControllerGrant, error) { // SameControllerGrant says whether two grants are the same value. func SameControllerGrant(a, b ControllerGrant) bool { return reflect.DeepEqual(a, b) } + +// NamesNode says whether the grant names module's accounts on node: its own `.` or a process's +// `..`. A grant that names no account (a module that does not speak on the bus) names every +// node. The assigner wants a node only once the grant names its account (issue 1945), and the controller's compose +// verb answers it (ADR 0546 clause 4). +func (g ControllerGrant) NamesNode(node, module string) bool { + if len(g.Accounts) == 0 { + return true + } + own := node + "." + module + for _, a := range g.Accounts { + if a == own || strings.HasPrefix(a, own+".") { + return true + } + } + return false +}