Land feature 57's controller work on its release branch

The controller plans config, templates and moved providers' provisions,
hands bus accounts to the vault and judges the new manifest words, on the
feature's SDK and node-engine validator (feature 57, config and provisioning).
This commit is contained in:
2026-10-15 21:27:33 +00:00
parent fcdecb4361
commit 97a2d841c7
349 changed files with 42440 additions and 786 deletions
+90
View File
@@ -0,0 +1,90 @@
package link
import (
"context"
"crypto/ed25519"
"encoding/json"
"sort"
"strings"
"testing"
"time"
"github.com/nats-io/nats.go"
"github.com/novox/mesh-controller/internal/broker"
"github.com/novox/mesh-controller/internal/testbus"
)
// The move's ask and answer keep the engine's field names (mesh-host internal/link,
// TestTheMovesAskKeepsItsFieldNamesAndContext): the row's fields beside a hand-over's, under a context of its own.
func TestTheMovesAskAndAnswerKeepTheirFieldNames(t *testing.T) {
keys := func(v any) string {
raw, _ := json.Marshal(v)
var m map[string]any
_ = json.Unmarshal(raw, &m)
var out []string
for k := range m {
out = append(out, k)
}
sort.Strings(out)
return strings.Join(out, " ")
}
ask := MoveSecretAsk{Module: "m", Name: "n", Provider: "p", Provision: "q", Consumer: "c", ConsumerModule: "cm",
Local: "l", Origin: "made", Generation: "g", MadeAt: time.Unix(1, 0).UTC(), Sealed: "s", SealedTo: "k"}
if got := keys(ask); got != "consumer consumer_module generation local made_at module name origin provider "+
"provision sealed sealed_to" {
t.Fatalf("the ask's fields are %q", got)
}
answer := MoveSecretAnswer{Said: "s", Refused: "r", Secret: "own/a/b/c", Generation: 1, Unchanged: true}
if got := keys(answer); got != "generation refused said secret unchanged" {
t.Fatalf("the answer's fields are %q", got)
}
if broker.AskMoveSecretSubject("laptop") != "mesh.node.laptop.ask.move-secret" ||
MoveSecretContext != "novox-mesh move-secret v1\n" {
t.Fatalf("the subject %q, the context %q", broker.AskMoveSecretSubject("laptop"), MoveSecretContext)
}
}
// A move is asked of the machine on its own subject, signed under its own context — never a hand-over's — naming
// no path and carrying the row beside the hand-over's fields; the engine's answer comes back whole.
func TestAMoveIsAskedOfTheMachineSignedUnderItsOwnContext(t *testing.T) {
conn, err := nats.Connect(testbus.URL(t))
if err != nil {
t.Fatal(err)
}
t.Cleanup(conn.Close)
signer, public := testSigner(t)
var heard HandOverAsk
var row MoveSecretAsk
engine, err := conn.Subscribe(broker.AskMoveSecretSubject("laptop"), func(msg *nats.Msg) {
var signed SignedHandOver
_ = json.Unmarshal(msg.Data, &signed)
if ed25519.Verify(public, append([]byte(HandOverContext), signed.Ask...), signed.Signature) ||
!ed25519.Verify(public, append([]byte(MoveSecretContext), signed.Ask...), signed.Signature) {
_ = msg.Respond([]byte(`{"refused":"not signed as a move"}`))
return
}
_ = json.Unmarshal(signed.Ask, &heard)
_ = json.Unmarshal(signed.Ask, &row)
body, _ := json.Marshal(MoveSecretAnswer{Said: "moved", Secret: "own/laptop/" + row.Module + "/" + row.Name,
Generation: 1})
_ = msg.Respond(body)
})
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = engine.Unsubscribe() })
a, err := AskMoveSecret(context.Background(), conn, signer, "laptop", "the move",
MoveSecretAsk{Module: "postgres", Name: "superuser-password", Origin: "made", Sealed: "c2Vh"}, 5*time.Second)
if err != nil || a.Secret != "own/laptop/postgres/superuser-password" || a.Generation != 1 {
t.Fatalf("answered %+v, %v", a, err)
}
if heard.Node != "laptop" || heard.Path != "" || heard.Nonce == "" || heard.Expires.IsZero() || heard.By != "the move" ||
row.Sealed != "c2Vh" || row.Origin != "made" {
t.Fatalf("the engine heard %+v %+v", heard, row)
}
if _, err := AskMoveSecret(context.Background(), conn, signer, "anchor", "the move", MoveSecretAsk{}, 2*time.Second); err == nil ||
!strings.Contains(err.Error(), "nothing was moved") {
t.Fatalf("a machine with no engine listening: %v", err)
}
}