Files
mesh-sdk/go/catalogue/vault_seat_test.go
T
jschoubben 0bb3a2c392 SDK-1: the runtime sends a file to a registry seat in parts and goes on from what the holder holds (ADR 0611, design 51)
publish.Publish opens the transfer naming every part's digest and sends only the parts the holder answers it lacks, in
chunks of at most 760 KiB (a message under the bus's 1 MiB once base64), in sequence with the last marked; a part
whose bytes are not its digest is refused before any of it travels. The seat's messages are mesh-contracts'; the call
is the caller's own. Its test takes the place of the vault's get test, merged into the vault's table.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 12:27:15 +01:00

120 lines
5.4 KiB
Go

package catalogue
import (
"slices"
"testing"
)
// The vault's provision is one the controller itself dereferences — every minted credential is
// sealed with it — so it is delivered by a seat of the mesh's own, and a second provider is a second
// claimant refused by name rather than a candidate for a pin (novox/hq ADR 0161, issue 106).
func TestTheVaultsSeatDeliversSecret(t *testing.T) {
seat, known := SeatNamed("mesh-vault")
if !known {
t.Fatal("mesh-vault is not in the mesh's own set")
}
if seat.Scope != ScopeMesh || seat.Delivers != "secret" {
t.Fatalf("mesh-vault is %s-scoped and delivers %q; one per mesh, delivering secret", seat.Scope, seat.Delivers)
}
vault := Manifest{Module: "mesh-vault", Provides: []Offer{{Name: "secret", Scope: ScopeMesh}},
Claims: []Claim{{Name: "mesh-vault", Scope: ScopeMesh}}}
if err := CanHold(vault, seat); err != nil {
t.Fatalf("the vault, claiming its seat and providing secret, was refused: %v", err)
}
another := Manifest{Module: "other-vault", Provides: []Offer{{Name: "secret", Scope: ScopeMesh}}}
if err := CanHold(another, seat); err == nil {
t.Fatal("a provider of secret that does not claim the seat was allowed to hold it")
}
}
// The vault takes values in and rotates them (novox/hq ADR 0349 clauses 8 to 10, issue 675): the seat promises
// secret-ask, issued and rotate, each with the arguments of its steps; a holder serving them is accepted, and,
// optional while the vault that runs does not, so is one that does not yet. And the move of the controller's secrets
// (design 57's V3, issue 676): move-in, asked in two steps, never a value in the clear. accept and move-asks, which no
// holder served and nothing called, are not the seat's (ADR 0620 §3); retire is, optional (design 32).
func TestTheVaultsSeatPromisesItsIntakeVerbs(t *testing.T) {
seat, _ := SeatNamed("mesh-vault")
want := map[string][]string{
// get, on request and reply (ADR 0349 §11, issue 674); a vault not serving it yet still holds the seat
// (TestTheVaultsSeatDeliversSecret).
"get": {"name", "public_key"},
"secret-ask": {"node", "module", "name", "desk", "asked_by", "outcome", "call", "sealed"},
"issued": {"provision", "provider", "module", "call", "sealed", "holders"},
"rotate": {"node", "module", "name", "provider", "provision", "by"},
// 774/S37/AC1: the enrolment verbs mesh-enrolment asks (ADR 0587 §3, §5).
"enrolment-token": {"node", "expires", "sealed", "drop", "tunnel"},
"node-account": {"node", "sealing_key", "keys_digest", "retire"},
"sign": {"kind", "node", "serving_key", "reply"},
// 774/S38: the rotation verbs (ADR 0583 §2, §3, §5).
"rotate-node": {"node", "why", "act"},
"node-account-confirm": {},
"abandon": {"node"},
"move-in": {"node", "module", "name", "provider", "provision", "consumer", "consumer_module", "local", "origin",
"generation", "made_at", "call", "sealed", "read_back_to"},
// And own (issue 1126): a machine's node-engine asks its own machine's secrets, sealed to its stated key.
"own": {"credentials"},
"retire": {"node", "module", "name", "warrant"},
// Issue 786: node-key, optional while the vault that runs does not serve it.
"node-key": {"key"},
}
for _, gone := range []string{"accept", "move-asks"} {
for _, v := range seat.Serves {
if v.Name == gone {
t.Errorf("the vault's seat still promises %s, which no holder serves (ADR 0620 §3)", gone)
}
}
}
for name, args := range want {
var verb *Verb
for i := range seat.Serves {
if seat.Serves[i].Name == name {
verb = &seat.Serves[i]
}
}
if verb == nil {
t.Errorf("the vault's seat does not promise %s", name)
continue
}
if !verb.Optional {
t.Errorf("%s is not optional while the vault that runs does not serve it", name)
}
props, _ := verb.Input["properties"].(map[string]any)
for _, arg := range args {
if props[arg] == nil {
t.Errorf("%s takes no %s", name, arg)
}
}
if props["value"] != nil {
t.Errorf("%s takes a value in the clear", name)
}
// The first tunnel the token carries (ADR 0587 §3, insight of 2026-11-02): an object of the hub's key, its endpoint
// and the node's address.
if name == "enrolment-token" {
tunnel, _ := props["tunnel"].(map[string]any)
if tunnel["type"] != "object" || !slices.Equal(tunnel["required"].([]string), []string{"address", "hub_endpoint", "hub_key", "key", "range"}) {
t.Errorf("enrolment-token's tunnel is %v", tunnel)
}
}
}
// The holders `issued` names (issue 749) are a list of {node, module}.
for _, verb := range seat.Serves {
if verb.Name != "issued" {
continue
}
props, _ := verb.Input["properties"].(map[string]any)
holders, _ := props["holders"].(map[string]any)
items, _ := holders["items"].(map[string]any)
each, _ := items["properties"].(map[string]any)
if holders["type"] != "array" || each["node"] == nil || each["module"] == nil {
t.Errorf("issued's holders are %v", holders)
}
}
serving := Manifest{Module: "mesh-vault", Provides: []Offer{{Name: "secret", Scope: ScopeMesh}},
Claims: []Claim{{Name: "mesh-vault", Scope: ScopeMesh,
Serves: []string{"get", "secret-ask", "issued", "rotate", "sign", "enrolment-token", "node-account",
"rotate-node", "node-account-confirm", "abandon", "move-in", "node-key", "own"}}}}
if err := CanHold(serving, seat); err != nil {
t.Fatalf("the vault serving its verbs was refused: %v", err)
}
}