The node-engine owns the composition it alone runs (H1, H2)

ADR 0593 §1 and §7: compose, its bus reader and runtime reader, takein,
validate, the overlay generator, the composer's run and mesh-compose, and
the judgement of a move leave mesh-sdk for the node-engine's internal
packages, so no other module composes and a change to them rebuilds only
the node-engine. The shapes others read (the composer's request and
verdict, the overlay's names, compositions and answers) stay in mesh-sdk.
The node's grant is now a golden file of what the grants part composes,
since the composer of the bus's user list leaves mesh-sdk too.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-02 18:24:05 +01:00
parent 98fbc490a4
commit 9a12f2851f
218 changed files with 33022 additions and 54 deletions
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"time"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/compose"
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
"github.com/novox/mesh-host/internal/compose"
"github.com/novox/mesh-host/internal/compose/frombus"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"time"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
"github.com/novox/mesh-host/internal/compose/frombus"
"git.novox.be/novox/mesh-sdk/go/delivery"
"github.com/novox/mesh-host/internal/agent"
+2 -2
View File
@@ -29,8 +29,8 @@ import (
"time"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/compose"
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
"github.com/novox/mesh-host/internal/compose"
"github.com/novox/mesh-host/internal/compose/frombus"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-sdk/go/overlay"
+6 -12
View File
@@ -18,12 +18,12 @@ import (
"testing"
"time"
"git.novox.be/novox/mesh-sdk/go/buscompose"
"git.novox.be/novox/mesh-sdk/go/compose"
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-sdk/go/overlay"
"github.com/nats-io/nats.go"
"github.com/novox/mesh-host/internal/compose"
"github.com/novox/mesh-host/internal/compose/frombus"
"github.com/novox/mesh-host/internal/nodegrant"
"github.com/novox/mesh-host/internal/agent"
)
@@ -81,15 +81,12 @@ func (b *fakeBus) put(t *testing.T, bucket, key string, value []byte) {
b.send(bucket, agent.Update{Key: key, Value: value})
}
// grantAllows says whether the node's grant (buscompose.PermissionsFor, KindNode) lets it watch or read pattern of
// grantAllows says whether the node's grant (the grants part's, nodegrant.For) lets it watch or read pattern of
// bucket: the consumer a watch or a get makes (`$JS.API.CONSUMER.CREATE.KV_<bucket>.<name>.$KV.<bucket>.<pattern>`)
// and the stream's information, matched as the bus matches a permission against a subject.
func grantAllows(t *testing.T, node, bucket, pattern string) bool {
t.Helper()
perms, err := buscompose.PermissionsFor(buscompose.Principal{Kind: buscompose.KindNode, Node: node})
if err != nil {
t.Fatal(err)
}
perms := nodegrant.For(node)
allowed := func(subject string) bool {
for _, deny := range perms.PublishDeny {
if subjectMatches(deny, subject) {
@@ -1455,10 +1452,7 @@ func TestTheNodeComposesItsWantsFromTheBus(t *testing.T) {
if got, err := r.Served(ctx, "n2", "mailer", []string{"domain"}); err != nil || fmt.Sprint(got) != "map[domain:example.org]" {
t.Errorf("what n2's mailer serves: %v, %v", got, err)
}
served, err := buscompose.PermissionsFor(buscompose.Principal{Kind: buscompose.KindNode, Node: "n1", ServedReads: []string{"n2.mailer.domain"}})
if err != nil {
t.Fatal(err)
}
served := nodegrant.For("n1", "n2.mailer.domain")
b.mu.Lock()
for _, read := range b.reads {
ok := grantAllows(t, "n1", read[0], read[1])
+3 -2
View File
@@ -9,8 +9,9 @@ import (
"sync"
"time"
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
"git.novox.be/novox/mesh-sdk/go/delivery"
"github.com/novox/mesh-host/internal/compose/frombus"
"github.com/novox/mesh-host/internal/judge"
"github.com/novox/mesh-host/internal/agent"
)
@@ -459,7 +460,7 @@ func (s *Shadow) answerAll(ctx context.Context) {
}
}
if ok {
a = delivery.FitAnswer(a, delivery.MaxAnswerBytes)
a = judge.FitAnswer(a, delivery.MaxAnswerBytes)
next[proposal] = a
c.env.Say(fmt.Sprintf("answered placement candidate %s in %s: %s", proposal, took.Round(time.Millisecond), a.Verdict))
} else {