Grants part: compose a principal for every own bus account, a tools bundle's with what it may remove, so the bus tools remove the controller's dead-letter consumer and the engine's acts on their own account (issue 1952 S5)

Pins mesh-sdk 7000bd5.
This commit is contained in:
2026-10-29 21:56:13 +01:00
parent e1fd3eb0f6
commit 7dbf7a19a1
4 changed files with 23 additions and 14 deletions
+1 -1
View File
@@ -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
)
+2 -2
View File
@@ -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=
+12 -1
View File
@@ -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)
}
+8 -10
View File
@@ -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)
}
}