diff --git a/internal/broker/states_agreement_test.go b/internal/broker/states_agreement_test.go index 5d64bc3..afd132f 100644 --- a/internal/broker/states_agreement_test.go +++ b/internal/broker/states_agreement_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/novox/mesh-controller/internal/broker" + "github.com/novox/mesh-controller/internal/catalogue" "github.com/novox/mesh-controller/internal/link" ) @@ -27,4 +28,17 @@ func TestTheFactsTheGrantPermitsAreTheFactsTheMeshStates(t *testing.T) { if len(broker.ControllerStates) != 3 { t.Errorf("the grant permits %v, which is more than the mesh states", broker.ControllerStates) } + // **And the seat says it.** A seat carries the protocol of its role (novox/hq ADR 0129), so the + // facts the control plane states are the seat's `emits` — which is what lets anything else declare + // that it consumes them, and what the subject-agreement check reads to know they have an owner. + var declared []string + for _, seat := range catalogue.SeatsWithAProtocol() { + if seat.Name == broker.ControllerSeat { + declared = seat.Emits + } + } + if !slices.Equal(declared, broker.ControllerStates) { + t.Errorf("the %s seat emits %v and the grant permits %v", broker.ControllerSeat, + declared, broker.ControllerStates) + } } diff --git a/internal/catalogue/seats.go b/internal/catalogue/seats.go index 8d6c873..b41b122 100644 --- a/internal/catalogue/seats.go +++ b/internal/catalogue/seats.go @@ -48,7 +48,11 @@ type Seat struct { // // In the order a person reads it: the mesh's own, then a node's. var defaultSeats = []Seat{ - {Name: "mesh-controller", Scope: ScopeMesh, Decision: "novox/hq ADR 0079"}, + // The control plane states what it did under the seat it holds (novox/hq ADR 0134): a role's + // events belong to the role, so they keep their address while the holder is replaced. No accepts, + // so no work queue is raised for it — only what its holder may say. + {Name: "mesh-controller", Scope: ScopeMesh, Decision: "novox/hq ADR 0079", + Emits: []string{"applied", "refused", "built-before"}}, {Name: "mesh-store", Scope: ScopeMesh, Delivers: "postgres-database", Decision: "novox/hq ADR 0079"}, // **Delivers the mesh's own bus, not `amqp`.** Those were the same word until // ADR 0127 separated them: `amqp` is a backing service a module may require, and this seat is