diff --git a/modules/mesh-grants/go.mod b/modules/mesh-grants/go.mod index 8eac37d..17483ea 100644 --- a/modules/mesh-grants/go.mod +++ b/modules/mesh-grants/go.mod @@ -3,7 +3,7 @@ module mesh-grants go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029204453-69fcb6c1c1ba + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029205252-7000bd5049ec github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-grants/go.sum b/modules/mesh-grants/go.sum index ce421f4..6dce500 100644 --- a/modules/mesh-grants/go.sum +++ b/modules/mesh-grants/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029204453-69fcb6c1c1ba h1:uXwkcQWgbu/UthizGHFaKPiA4NBVJgqL9q2jJnnGR1o= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029204453-69fcb6c1c1ba/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029205252-7000bd5049ec h1:OLXHSQkAHnf03hzJTxRrUsl7vMfMhOx43M5yJpi5L5Y= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261029205252-7000bd5049ec/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= diff --git a/modules/mesh-grants/grants_test.go b/modules/mesh-grants/grants_test.go index 44cf7c9..c6d9ec7 100644 --- a/modules/mesh-grants/grants_test.go +++ b/modules/mesh-grants/grants_test.go @@ -1077,7 +1077,9 @@ func TestGrants(t *testing.T) { file("node-tools-novox-licence-subjects.json", &live) licence, _ := os.ReadFile(filepath.Join("testdata", "claude-licence-manager.json")) n := newFakeBus() - n.manifestOf("nats", natsManifest) + // 1952/S5 (ADR 0564 Limits 4): the bus module's tools bundle declares its own account and what it may remove. + n.manifestOf("nats", strings.TrimSuffix(natsManifest, "}")+`,"build":{"artifacts":[{"name":"tools","kind":"bundle","language":"go",`+ + `"system":"arch","from":"cmd/nats-tools","binary":"nats-tools","loads":["nats-tools"],"bus":{"removes":["DEAD_LETTER_NOTICES.controller","mesh-host_acts"]}}]}}`) n.manifestOf("claude-licence-manager", string(licence)) n.assign("novox", "nats") n.assign("novox", "claude-licence-manager") @@ -1087,6 +1089,15 @@ func TestGrants(t *testing.T) { pl, _ = delivery.EncodePlacement(seed) n.states[grants.ReadPlacement] = map[string][]byte{"placement.novox": pl} recs, _ := grants.Records(grants.ReadInputs(n, &grants.Manifests{})) + var tools []buscompose.ProcessPrincipal + for _, d := range recs.Assigned["novox"] { + if d.Module == "nats" { + tools = d.Processes + } + } + if len(tools) != 1 || tools[0].Process != "nats-tools" || !slices.Equal(tools[0].Removes, []string{"DEAD_LETTER_NOTICES.controller", "mesh-host_acts"}) { + t.Errorf("the bus module's principals = %+v, want nats-tools carrying both removals", tools) + } if m := grants.Memberships(recs)["novox.claude-licence-manager"]; len(m.Membership.Seats) == 0 { t.Errorf("the licence manager's membership under the seeded placement carries no seats: %+v", m.Membership) } diff --git a/modules/mesh-grants/internal/grants/records.go b/modules/mesh-grants/internal/grants/records.go index a0e575f..6194d3f 100644 --- a/modules/mesh-grants/internal/grants/records.go +++ b/modules/mesh-grants/internal/grants/records.go @@ -294,21 +294,19 @@ func queueOwnersOf(m catalogue.Manifest) []buscompose.QueueOwner { } func processesOf(m catalogue.Manifest) []buscompose.ProcessPrincipal { - buses := m.ProcessBuses() - if len(buses) == 0 { + accounts := m.BusAccounts() + if len(accounts) == 0 { return nil } queues := queueOwnersOf(m) var out []buscompose.ProcessPrincipal - for _, r := range m.Resources { - id := fmt.Sprint(r["id"]) - b, declared := buses[id] - if !declared { - continue - } - pr := buscompose.ProcessPrincipal{Process: id, Emits: b.Emits, State: b.State, Asks: b.Asks, Invokes: b.Invokes} + // Every own bus account, processes first and then tools bundles (catalogue.BusAccounts): a tools bundle's account carries + // what it may remove from the bus (ADR 0564 Limits 4, issue 1952 S5). + for _, a := range accounts { + pr := buscompose.ProcessPrincipal{Process: a.ID, Emits: a.Bus.Emits, State: a.Bus.State, Asks: a.Bus.Asks, + Invokes: a.Bus.Invokes, Removes: a.Bus.Removes} for _, q := range queues { - if q.Process == id { + if q.Process == a.ID { pr.Queues = append(pr.Queues, q) } }