mesh-mail's events must live on a stream of their own and reach only the modules the operator granted an account (ADR 0359 §2, §4). The controller now creates a module's declared stream, publishes its events on mesh.stream.<module>.event.<event>, and composes a consumer's durable consumer, filters and bus grants on a restricted stream only where its consumes asks and the provider's trusted value names it; a consumer that loses its grant has its consumer removed on the next assertion. Nothing changes while no manifest declares a stream.
40 lines
1.2 KiB
Go
40 lines
1.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
)
|
|
|
|
// A membership issued again for what it hears changes nothing else of it (novox/hq ADR 0363 §6).
|
|
func TestAMembershipIssuedAgainChangesOnlyWhatItHears(t *testing.T) {
|
|
issued := []byte(`{"node":"ace","module":"reader","receives":{"x":[1]},"emits":"mesh.mod.reader.event.{event}"}`)
|
|
hears := []broker.HeardIssued{{Stream: "MAIL", Consumer: "ace_reader"}}
|
|
body, changed, err := withHearing(issued, hears)
|
|
if err != nil || !changed {
|
|
t.Fatalf("changed %v, %v", changed, err)
|
|
}
|
|
var got map[string]any
|
|
if err := json.Unmarshal(body, &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got["receives"] == nil || got["emits"] != "mesh.mod.reader.event.{event}" || got["hears"] == nil {
|
|
t.Fatalf("issued again as %s", body)
|
|
}
|
|
if _, again, _ := withHearing(body, hears); again {
|
|
t.Fatal("the same hearing issued again counts as a change")
|
|
}
|
|
gone, changed, err := withHearing(body, nil)
|
|
if err != nil || !changed {
|
|
t.Fatalf("a withdrawal: %v, %v", changed, err)
|
|
}
|
|
got = nil
|
|
if err := json.Unmarshal(gone, &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, still := got["hears"]; still {
|
|
t.Fatalf("a withdrawn hearing is still issued: %s", gone)
|
|
}
|
|
}
|