diff --git a/modules/mesh-grants/internal/buscompose/buscompose_test.go b/modules/mesh-grants/internal/buscompose/buscompose_test.go index c6cc96e7..43644ab7 100644 --- a/modules/mesh-grants/internal/buscompose/buscompose_test.go +++ b/modules/mesh-grants/internal/buscompose/buscompose_test.go @@ -1337,3 +1337,46 @@ func TestAMachineEventNamesItsNodeWhereTheDefinitionSaysSo(t *testing.T) { t.Errorf("the engine does not hear every node's running: %v", sub) } } + +// Design 47 (W8.6): the events of a seat held once (`freed`, `pinned`, `owed`) are published by the account of the module that +// holds it alone, so the gate's is the one that says them and the checker's the one that says its own seat's `owed`; a module +// that holds neither, and one that only uses the seat, is granted neither. +func TestASeatsEventsArePublishedByItsHolderAlone(t *testing.T) { + gate := Seat{Name: "mesh-delivery", Scope: "mesh", Emits: []string{"freed", "pinned", "owed.*.*"}} + checker := Seat{Name: "mesh-delivery-checker", Scope: "mesh", Emits: []string{"owed.*.*"}} + records := Records{Nodes: []string{"one"}, Assigned: map[string][]Declared{"one": { + {Module: "gate", Holds: []Seat{gate}, Uses: []Seat{checker}}, + {Module: "checker", Holds: []Seat{checker}, Uses: []Seat{gate}}, + {Module: "forge", Uses: []Seat{gate, checker}}, + }}} + users, err := Users(records) + if err != nil { + t.Fatal(err) + } + perms := map[string]Permissions{} + for _, u := range users { + p, err := PermissionsFor(u) + if err != nil { + t.Fatal(err) + } + perms[u.Username()] = p + } + for _, row := range []struct { + who, subject string + may bool + }{ + {"one.gate", "mesh.seat.mesh-delivery.event.freed", true}, + {"one.gate", "mesh.seat.mesh-delivery.event.pinned", true}, + {"one.gate", "mesh.seat.mesh-delivery.event.owed.r.1", true}, + {"one.gate", "mesh.seat.mesh-delivery-checker.event.owed.r.1", false}, + {"one.checker", "mesh.seat.mesh-delivery-checker.event.owed.r.1", true}, + {"one.checker", "mesh.seat.mesh-delivery.event.owed.r.1", false}, + {"one.checker", "mesh.seat.mesh-delivery.event.freed", false}, + {"one.forge", "mesh.seat.mesh-delivery.event.freed", false}, + {"one.forge", "mesh.seat.mesh-delivery-checker.event.owed.r.1", false}, + } { + if got := MayPublish(perms[row.who], row.subject); got != row.may { + t.Errorf("%s may publish %s = %v, want %v", row.who, row.subject, got, row.may) + } + } +}