diff --git a/modules/mesh-grants/grants_test.go b/modules/mesh-grants/grants_test.go index 257c4b1..b3ba2e3 100644 --- a/modules/mesh-grants/grants_test.go +++ b/modules/mesh-grants/grants_test.go @@ -1783,6 +1783,31 @@ func TestGrants(t *testing.T) { } }) + // 774 (ADR 0563 §2, §3): the node-engine's manifest (mesh-host) is placed on every node though no node is assigned it, + // so its declared state acts is created as a placed module's, and composed for the user list's create right. + t.Run("assertions: the node-engine's declared state is created though no node is assigned it", func(t *testing.T) { + b := fixture() + b.manifestOf(buscompose.EngineModule, `{"module":"mesh-host","version":"1","state":[{"name":"acts"}]}`) + b.loaded = shadowOf(t, b) + p := partOn(b) + p.Create = b + p.Compose() + if !slices.Contains(b.creates, "KV_"+buscompose.EngineActsBucket) { + t.Fatalf("the node-engine's acts were not created: %v", b.creates) + } + recs, _ := grants.Records(grants.ReadInputs(b, &grants.Manifests{})) + if recs.Engine == nil || len(recs.Engine.State) != 1 || recs.Engine.State[0].Bucket() != buscompose.EngineActsBucket { + t.Fatalf("the records carry the node-engine as %+v", recs.Engine) + } + for node, mods := range recs.Assigned { + for _, d := range mods { + if d.Module == buscompose.EngineModule { + t.Errorf("the node-engine is a module of %s, which would give it a module's account", node) + } + } + } + }) + t.Run("assertions: a refused create is said, never stops it, and is tried at the next event", func(t *testing.T) { b := fixture() b.loaded = shadowOf(t, b) diff --git a/modules/mesh-grants/internal/grants/part.go b/modules/mesh-grants/internal/grants/part.go index 29c5291..11deb15 100644 --- a/modules/mesh-grants/internal/grants/part.go +++ b/modules/mesh-grants/internal/grants/part.go @@ -13,6 +13,7 @@ import ( "time" "git.novox.be/novox/mesh-sdk/go/asks" + "git.novox.be/novox/mesh-sdk/go/buscompose" "git.novox.be/novox/mesh-sdk/go/delivery" "git.novox.be/novox/mesh-sdk/go/membership" ) @@ -364,6 +365,11 @@ func (p *Part) Last() Result { } func assigned(in Inputs, module string) bool { + // The node-engine runs on every node though no node is assigned it (novox/hq ADR 0563 §2, §3): its manifest is + // placed everywhere, so its declared state is asserted and created as a placed module's. + if module == buscompose.EngineModule { + return true + } for _, ms := range in.Assigned { for _, m := range ms { if m == module { diff --git a/modules/mesh-grants/internal/grants/records.go b/modules/mesh-grants/internal/grants/records.go index bf479b2..d07c7ae 100644 --- a/modules/mesh-grants/internal/grants/records.go +++ b/modules/mesh-grants/internal/grants/records.go @@ -78,6 +78,11 @@ func Records(in Inputs) (buscompose.Records, []Gap) { } } } + // The node-engine's own manifest, placed on every node (ADR 0563): its state, logs and streams alone, created by this + // part; it adds no principal, since each node's engine speaks as the node's account. + if m, ok := in.Manifests[buscompose.EngineModule]; ok { + out.Engine = &buscompose.Declared{Module: m.Module, State: bucketsOf(m), Logs: logsOf(m), Streams: streamsOf(m)} + } return out, gaps }