The copied composer grants the grants part reading every membership, and its memberships are held to the controller's too (ADR 0547 §5, review of mesh-grants)
mesh/delivery merged: source.main moved to novox/mesh-sdk@095d41fa3e81
mesh/delivery-group group fix/1945-memberships merged: every member is merged
mesh/check failed: integration: github.com/novox/mesh-controller/cmd/mesh-controller.TestTheDeclarationsStreamGoesOnceEveryNodeRunsTheNewEngine: with …
mesh/delivery merged: source.main moved to novox/mesh-sdk@095d41fa3e81
mesh/delivery-group group fix/1945-memberships merged: every member is merged
mesh/check failed: integration: github.com/novox/mesh-controller/cmd/mesh-controller.TestTheDeclarationsStreamGoesOnceEveryNodeRunsTheNewEngine: with …
The grants part reads each module's last membership before it publishes, so it needs the direct get on every membership subject, as the controller's composer now grants (fix/1945-mesh-grants-publishes-memberships). The equality test compares every membership the fixtures issue with the controller's MembershipFor, written by its own code.
This commit is contained in:
@@ -4,13 +4,14 @@ import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Defends issue 1377 and novox/hq ADR 0547 §5: this is the controller's bus composer copied, and it composes byte for
|
||||
// byte what the controller's composes. testdata/controller-user-lists.json was written by the controller's own
|
||||
// internal/broker (mesh-controller at f67d1553, branch fix/1945-mesh-grants-publishes-memberships) from fixtures_test.go compiled there unchanged; composed.conf is the
|
||||
// internal/broker (mesh-controller branch fix/1945-mesh-grants-publishes-memberships), lists and memberships, from fixtures_test.go compiled there unchanged; composed.conf is the
|
||||
// controller's golden of the whole server configuration. A row that differs is the copy drifting from the controller,
|
||||
// which is a fault while both compose (until the controller loses its lease, ADR 0547 §13).
|
||||
func TestTheCopiedComposerComposesAsTheControllers(t *testing.T) {
|
||||
@@ -19,9 +20,10 @@ func TestTheCopiedComposerComposesAsTheControllers(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var want []struct {
|
||||
Name, List string
|
||||
Missing []string
|
||||
Err string
|
||||
Name, List string
|
||||
Missing []string
|
||||
Err string
|
||||
Memberships json.RawMessage
|
||||
}
|
||||
if err := json.Unmarshal(raw, &want); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -49,6 +51,22 @@ func TestTheCopiedComposerComposesAsTheControllers(t *testing.T) {
|
||||
if list != want[i].List {
|
||||
t.Errorf("the list differs from the controller's:\n%s", list)
|
||||
}
|
||||
// And every membership the records issue, as the controller's MembershipFor makes it (ADR 0547 §5): the
|
||||
// grants part publishes them.
|
||||
raw, err := json.Marshal(MembershipsFor(f))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var gotM, wasM any
|
||||
if err := json.Unmarshal(raw, &gotM); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := json.Unmarshal(want[i].Memberships, &wasM); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(gotM, wasM) {
|
||||
t.Errorf("the memberships differ from the controller's:\n%s", raw)
|
||||
}
|
||||
})
|
||||
}
|
||||
t.Run("the controller's golden server configuration", func(t *testing.T) {
|
||||
|
||||
@@ -102,3 +102,15 @@ func ComposedFor(f UserListFixture) (string, []string, error) {
|
||||
list, err := ComposeAccounts(filled)
|
||||
return list, missing, err
|
||||
}
|
||||
|
||||
// MembershipsFor is every membership a fixture's records issue, by `<node>.<module>`, as the composer makes them.
|
||||
func MembershipsFor(f UserListFixture) map[string]Membership {
|
||||
where := PlacementsOf(f.Records, f.Records.Interchangeable)
|
||||
out := map[string]Membership{}
|
||||
for node, ds := range f.Records.Assigned {
|
||||
for _, d := range ds {
|
||||
out[node+"."+d.Module] = MembershipFor(node, d, where)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -915,9 +915,10 @@ func PermissionsFor(p Principal) (Permissions, error) {
|
||||
pub = append(pub, BusConnzSubject)
|
||||
}
|
||||
// The grants part alone publishes the modules' memberships into the assignments stream (novox/hq ADR 0547 §5;
|
||||
// the operator, 2026-10-25 22:31): one per subject, `mesh.assignment.<node>.<module>`, and no stream it defines.
|
||||
// the operator, 2026-10-25 22:31): one per subject, `mesh.assignment.<node>.<module>`, reading the last one of each
|
||||
// first so it publishes only what changed, and no stream it defines.
|
||||
if p.Module == GrantsModule {
|
||||
pub = append(pub, "mesh.assignment.*.*")
|
||||
pub = append(pub, "mesh.assignment.*.*", "$JS.API.DIRECT.GET."+AssignmentsStream+".mesh.assignment.*.*")
|
||||
}
|
||||
// The view alone reads the build seats' workers for the backlog of asks (issue 1887 A8a).
|
||||
if p.Module == ViewModule {
|
||||
|
||||
+238
-5
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user