Files
mesh-catalog/modules/mesh-vault/cmd/mesh-vault/pair_test.go
T

494 lines
20 KiB
Go

package main
// ADR 0349's provider test, the vault's part (design 57 V5, issue 677), with a stand-in provider: a consumer binding
// to it remakes its one credential without the provider asking, and a consumer unbinding remakes it for the holders
// left; every holder gets it on request after `secret-changed`; an accepted or issued value is not remade; what the
// move brought in is adopted when its rows share a generation stamp, and otherwise waits for the provider's
// rotation; and no value is made that a holder still filled the old way would never get.
import (
"errors"
"sort"
"strings"
"testing"
"time"
"git.novox.be/novox/mesh-sdk/go/seal"
)
// keys is every key of a stand-in mirror.
func (a assignments) keys() ([]string, error) {
var out []string
for k := range a {
out = append(out, k)
}
sort.Strings(out)
return out, nil
}
// handedWith is an assignment handed to the provisioner, its plan naming each provision given as
// provision@provider/provider-module[#local][=name][+credential-form][~credential-tool] (the tool last).
func handedWith(node, module string, provisions ...string) string {
var entries []string
for _, p := range provisions {
form, tool := "", ""
if i := strings.Index(p, "~"); i >= 0 {
p, tool = p[:i], p[i+1:]
}
if i := strings.Index(p, "+"); i >= 0 {
p, form = p[:i], p[i+1:]
}
name := ""
if i := strings.Index(p, "="); i >= 0 {
p, name = p[:i], p[i+1:]
}
local := ""
if i := strings.Index(p, "#"); i >= 0 {
p, local = p[:i], p[i+1:]
}
provision, rest, _ := strings.Cut(p, "@")
provider, providerModule, _ := strings.Cut(rest, "/")
e := `{"provision":"` + provision + `","provider":"` + provider + `","provider-module":"` + providerModule + `"`
if local != "" {
e += `,"local":"` + local + `"`
}
if name != "" {
e += `,"name":"` + name + `","path":"/s/` + name + `"`
}
if form != "" {
e += `,"credential-form":"` + form + `"`
}
if tool != "" {
e += `,"credential-tool":"` + tool + `"`
}
entries = append(entries, e+"}")
}
return `{"node":"` + node + `","module":"` + module + `","provisioning":{"templates":{"source":"x","digest":"y"},` +
`"files":[],"provisions":[` + strings.Join(entries, ",") + `]}}`
}
// unmoved is an assignment the controller has not handed to the provisioner.
func unmoved(node, module string) string {
return `{"node":"` + node + `","module":"` + module + `"}`
}
const standIn = "provision/anchor/stand-in-api"
// pairVault is a vault reading mirror for its binds and its rule.
func pairVault(t *testing.T, mirror assignments) testVault {
t.Helper()
v := newVault(t, nil)
v.Askers = Declared{Read: mirror.read, Store: v.Store}
v.Assignments = Mirror{Keys: mirror.keys, Read: mirror.read}
return v
}
// pass runs one pass and is the outcome for name.
func pass(t *testing.T, v testVault, name string) PairOutcome {
t.Helper()
outcomes, err := v.PairPass()
if err != nil {
t.Fatal(err)
}
for _, o := range outcomes {
if o.Name == name {
return o
}
}
t.Fatalf("the pass said nothing of %s: %+v", name, outcomes)
return PairOutcome{}
}
// asks is what caller is handed for name, opened, or the refusal.
func asks(v testVault, caller, name string) (string, int, error) {
key, _ := seal.GenerateKeyPair()
a, err := v.Get(caller, name, key.PublicKey)
if err != nil {
return "", 0, err
}
got, err := seal.Open(a.Sealed, key.PrivateKey)
return got, a.Generation, err
}
// changedSaid is how many times `secret-changed` was said for name, and that none carried a value.
func changedSaid(t *testing.T, v testVault, name, value string) int {
t.Helper()
v.bus.mu.Lock()
defer v.bus.mu.Unlock()
n := 0
for i, e := range v.bus.events {
if value != "" && strings.Contains(v.bus.raw[i], value) {
t.Fatalf("the bus carried the value: %s", v.bus.raw[i])
}
if e["event"] == ChangedEvent && e["body"].(map[string]any)["name"] == name {
n++
}
}
return n
}
func TestAConsumerBindingOrUnbindingRemakesTheProvidersOneCredentialForEveryHolder(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
}
v := pairVault(t, mirror)
movedRow(t, v, "g14", "app", "shared-from-the-move", "stamp-1", OriginMade)
// The move's shared value is adopted, and said to have changed in the vault.
if o := pass(t, v, standIn); o.Outcome != PairAdopted || o.Generation != 1 {
t.Fatalf("the first pass: %+v", o)
}
first, _, err := asks(v, "provisioner.anchor", standIn)
if err != nil {
t.Fatalf("the provider's machine was refused its credential: %v", err)
}
if got, _, err := asks(v, "provisioner.g14", standIn); err != nil || got != first {
t.Fatalf("the consumer got %q (%v), the provider %q", got, err, first)
}
if first != "shared-from-the-move" || changedSaid(t, v, standIn, "") != 1 {
t.Fatal("the adopted value is not the move's, or secret-changed was not said once for it")
}
if _, _, err := asks(v, "provisioner.ace", standIn); err == nil {
t.Fatal("a machine holding nothing of it was handed the credential")
}
// Nothing changed: nothing is remade.
if o := pass(t, v, standIn); o.Outcome != PairUnchanged {
t.Fatalf("a pass with no bind or unbind: %+v", o)
}
// A second consumer binds: the vault remakes it without the provider asking, one new value for all three.
mirror["ace.other"] = handedWith("ace", "other", "stand-in-api@anchor/stand-in")
if o := pass(t, v, standIn); o.Outcome != PairRemade || o.Generation != 2 {
t.Fatalf("a consumer binding: %+v", o)
}
second, gen, _ := asks(v, "provisioner.anchor", standIn)
if second == first || gen != 2 {
t.Fatal("the value was not remade when a consumer bound")
}
for _, c := range []string{"provisioner.g14", "provisioner.ace"} {
if got, _, err := asks(v, c, standIn); err != nil || got != second {
t.Fatalf("%s got %q (%v) after the bind, not the one new value", c, got, err)
}
}
if changedSaid(t, v, standIn, "") != 2 {
t.Fatal("secret-changed was not said for the remade value")
}
// It unbinds (its plan no longer names it): remade for the holders left, and it is handed nothing more.
mirror["ace.other"] = handedWith("ace", "other")
if o := pass(t, v, standIn); o.Outcome != PairRemade || o.Generation != 3 {
t.Fatalf("a consumer unbinding: %+v", o)
}
third, _, _ := asks(v, "provisioner.anchor", standIn)
if got, _, _ := asks(v, "provisioner.g14", standIn); third == second || got != third {
t.Fatal("the holders left do not share one new value after the unbind")
}
if _, _, err := asks(v, "provisioner.ace", standIn); err == nil {
t.Fatal("a consumer that unbound was still handed the credential")
}
// Its assignment goes: an unbind too.
delete(mirror, "g14.app")
if o := pass(t, v, standIn); o.Outcome != PairRemade {
t.Fatalf("a consumer taken off its machine: %+v", o)
}
if _, _, err := asks(v, "provisioner.g14", standIn); err == nil {
t.Fatal("a machine whose consumer left was still handed the credential")
}
}
// Two local names of one provision on one consumer are two binds of the same value; a credential per holder (issue
// 757) has no one shared value.
func TestLocalNamesAreBindsAndAPerHolderCredentialIsNotShared(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in#reader"),
"novox.gitea": handedWith("novox", "gitea"),
"g14.claude-code": handedWith("g14", "claude-code", "gitea-read@novox/gitea=gitea-read"),
}
v := pairVault(t, mirror)
movedRow(t, v, "g14", "app", "shared", "stamp-1", OriginMade, "reader")
pass(t, v, standIn)
mirror["g14.app"] = handedWith("g14", "app", "stand-in-api@anchor/stand-in#reader",
"stand-in-api@anchor/stand-in#writer")
if o := pass(t, v, standIn); o.Outcome != PairRemade {
t.Fatalf("a second local name binding: %+v", o)
}
if o := pass(t, v, "provision/novox/gitea-read"); o.Outcome != PairPerHolder {
t.Fatalf("a credential per holder: %+v", o)
}
if _, held, _ := v.Store.Read("provision/novox/gitea-read"); held {
t.Fatal("a shared value was made for a credential issued per holder")
}
}
// An accepted value is opened by the vault alone and not remade (ADR 0158 §8), nor is one the provider's software
// issued (ADR 0305 §9): a bind records its holder, who gets the value as it is.
func TestAnAcceptedOrIssuedValueIsNotRemadeOnABind(t *testing.T) {
for _, origin := range []string{OriginAccepted, OriginIssued} {
t.Run(origin, func(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
}
v := pairVault(t, mirror)
if _, err := v.keep(standIn, "given-by-a-person", "person.jochen", ControllerCaller, origin); err != nil {
t.Fatal(err)
}
if o := pass(t, v, standIn); o.Outcome != PairRecorded || o.Generation != 1 {
t.Fatalf("the first pass: %+v", o)
}
mirror["ace.other"] = handedWith("ace", "other", "stand-in-api@anchor/stand-in")
if o := pass(t, v, standIn); o.Outcome != PairRecorded || o.Generation != 1 {
t.Fatalf("a bind to a value %s: %+v", origin, o)
}
for _, c := range []string{"provisioner.anchor", "provisioner.g14", "provisioner.ace"} {
if got, gen, err := asks(v, c, standIn); err != nil || got != "given-by-a-person" || gen != 1 {
t.Fatalf("%s got %q generation %d (%v)", c, got, gen, err)
}
}
})
}
}
// movedRow is a pair row as the move (V3) keeps it: its value, the controller's generation stamp and origin.
func movedRow(t *testing.T, v testVault, consumer, module, value, stamp, origin string, local ...string) {
t.Helper()
name, err := PairSecret("anchor", "stand-in-api", consumer, module, strings.Join(local, ""))
if err != nil {
t.Fatal(err)
}
if _, err := v.keepWith(name, value, "node."+consumer, "", origin, keepOptions{neverReplace: true,
madeAt: time.Date(2026, 9, 1, 0, 0, 0, 0, time.UTC),
movedFrom: &MovedFrom{By: "node." + consumer, Generation: stamp}}); err != nil {
t.Fatal(err)
}
}
// Rows a provider shares carry one generation stamp (ADR 0158): the vault adopts their value as the provision's one
// credential, keeps its origin and when it was made, and remakes nothing, so the move rotates no credential.
func TestPairRowsSharingAGenerationStampAreAdoptedAndNothingIsRemade(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
"ace.other": handedWith("ace", "other", "stand-in-api@anchor/stand-in"),
}
v := pairVault(t, mirror)
movedRow(t, v, "g14", "app", "the-value-they-share", "20260901T000000-1", OriginMade)
movedRow(t, v, "ace", "other", "the-value-they-share", "20260901T000000-1", OriginMade)
if o := pass(t, v, standIn); o.Outcome != PairAdopted || o.Generation != 1 {
t.Fatalf("stamped rows: %+v", o)
}
for _, c := range []string{"provisioner.anchor", "provisioner.g14", "provisioner.ace"} {
if got, _, err := asks(v, c, standIn); err != nil || got != "the-value-they-share" {
t.Fatalf("%s got %q (%v), not the value it had", c, got, err)
}
}
rec, _, _ := v.Store.Read(standIn)
if rec.Origin != OriginMade || !rec.MadeAt.Equal(time.Date(2026, 9, 1, 0, 0, 0, 0, time.UTC)) ||
rec.MovedFrom == nil || rec.MovedFrom.Generation != "20260901T000000-1" {
t.Fatalf("the adopted value does not say where it came from: %+v", rec)
}
if o := pass(t, v, standIn); o.Outcome != PairUnchanged {
t.Fatalf("the pass after the adoption: %+v", o)
}
if got, gen, _ := asks(v, "provisioner.g14", standIn); got != "the-value-they-share" || gen != 1 {
t.Fatal("the adopted value was remade with no bind or unbind")
}
}
// Rows of a provider with a login per consumer (ADR 0048) carry no stamp: each consumer keeps a value of its own
// for ever (ADR 0158 §11, issue 677's note 12). A bind makes no shared value, and nor does a rotation.
func TestUnstampedPairRowsAreNeverMadeOneSharedValue(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
"ace.other": handedWith("ace", "other", "stand-in-api@anchor/stand-in"),
}
v := pairVault(t, mirror)
movedRow(t, v, "g14", "app", "login-of-app", "", OriginMade)
movedRow(t, v, "ace", "other", "login-of-other", "", OriginMade)
for i := 0; i < 2; i++ {
if o := pass(t, v, standIn); o.Outcome != PairPerPair {
t.Fatalf("unstamped rows, pass %d: %+v", i, o)
}
}
mirror["novox.third"] = handedWith("novox", "third", "stand-in-api@anchor/stand-in")
if o := pass(t, v, standIn); o.Outcome != PairPerPair {
t.Fatalf("a bind to a provider with logins of their own: %+v", o)
}
if _, err := v.Rotate(ControllerCaller, standIn, "person.jochen", "its ordinary rotation"); err != nil {
t.Fatal(err)
}
if _, held, _ := v.Store.Read(standIn); held {
t.Fatal("a shared value was made for a provider whose consumers keep logins of their own")
}
if changedSaid(t, v, standIn, "") != 0 {
t.Fatal("secret-changed was said for a shared value")
}
}
// Two consumers of postgres-database (a login each, ADR 0048) hold different values after a rotation, each remade
// apart, and each consumer's machine is handed only its own; the provider's machine is handed both.
func TestARotationRemakesEachPostgresConsumersOwnLoginApart(t *testing.T) {
mirror := assignments{
"novox.postgres": handedWith("novox", "postgres"),
"g14.gitea": handedWith("g14", "gitea", "postgres-database@novox/postgres"),
"ace.umami": handedWith("ace", "umami", "postgres-database@novox/postgres"),
}
v := pairVault(t, mirror)
gitea, umami := "pair/novox/postgres-database/g14/gitea", "pair/novox/postgres-database/ace/umami"
for name, value := range map[string]string{gitea: "login-of-gitea", umami: "login-of-umami"} {
if _, err := v.keepWith(name, value, "node.novox", "", OriginMade, keepOptions{neverReplace: true,
movedFrom: &MovedFrom{By: "node.novox"}}); err != nil {
t.Fatal(err)
}
}
changed, err := v.Rotate(ControllerCaller, "provision/novox/postgres-database", "person.jochen", "yearly")
if err != nil || len(changed.Each) != 2 {
t.Fatalf("the rotation: %+v (%v)", changed, err)
}
ofGitea, _, err := asks(v, "provisioner.g14", gitea)
if err != nil {
t.Fatalf("gitea's machine was refused its own login: %v", err)
}
ofUmami, _, err := asks(v, "provisioner.ace", umami)
if err != nil {
t.Fatalf("umami's machine was refused its own login: %v", err)
}
if ofGitea == ofUmami || ofGitea == "login-of-gitea" || ofUmami == "login-of-umami" {
t.Fatalf("after the rotation gitea holds %q and umami %q: not two new values of their own", ofGitea, ofUmami)
}
if _, _, err := asks(v, "provisioner.g14", umami); err == nil {
t.Fatal("gitea's machine was handed umami's login")
}
if _, _, err := asks(v, "provisioner.ace", gitea); err == nil {
t.Fatal("umami's machine was handed gitea's login")
}
for name, want := range map[string]string{gitea: ofGitea, umami: ofUmami} {
if got, _, err := asks(v, "provisioner.novox", name); err != nil || got != want {
t.Fatalf("the provider's machine got %q for %s (%v)", got, name, err)
}
}
if _, held, _ := v.Store.Read("provision/novox/postgres-database"); held {
t.Fatal("a shared value was made for postgres-database")
}
}
// A provider and provision the vault holds no row of: whether its offer shares one credential or keeps a login per
// consumer is not said where the vault reads, so it makes nothing rather than guess.
func TestAProviderTheVaultHoldsNoRowOfIsNotGuessed(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
}
v := pairVault(t, mirror)
if o := pass(t, v, standIn); o.Outcome != PairHeld || !strings.Contains(o.Why, "no plan says whether") {
t.Fatalf("a provider with no row: %+v", o)
}
if _, err := v.Rotate(ControllerCaller, standIn, "person.jochen", "why not"); err == nil {
t.Fatal("a rotation guessed the form of a provider with no row")
}
if _, held, _ := v.Store.Read(standIn); held {
t.Fatal("a value was made for a provider whose form the vault does not know")
}
}
// The vault makes no value a holder would never get (the lead's rule on issue 677): a provider not handed to the
// provisioner, or a consumer the move brought in that is still filled the old way, holds every make and remake
// back, and a rotation too.
func TestNoValueIsMadeThatAHolderFilledTheOldWayWouldNeverGet(t *testing.T) {
t.Run("an unmoved provider", func(t *testing.T) {
mirror := assignments{
"anchor.stand-in": unmoved("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
}
v := pairVault(t, mirror)
if o := pass(t, v, standIn); o.Outcome != PairHeld || !strings.Contains(o.Why, "stand-in on anchor") {
t.Fatalf("an unmoved provider: %+v", o)
}
if _, held, _ := v.Store.Read(standIn); held {
t.Fatal("a value was made that the provider would never get")
}
if _, err := v.Rotate(ControllerCaller, standIn, "person.jochen", "why not"); err == nil {
t.Fatal("a rotation made a value the provider would never get")
}
})
t.Run("an unmoved consumer", func(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
"ace.old": unmoved("ace", "old"),
}
v := pairVault(t, mirror)
movedRow(t, v, "g14", "app", "shared", "stamp-1", OriginMade)
movedRow(t, v, "ace", "old", "shared", "stamp-1", OriginMade)
if o := pass(t, v, standIn); o.Outcome != PairAdopted {
t.Fatalf("adopting changes no value, so it is not held back: %+v", o)
}
mirror["novox.new"] = handedWith("novox", "new", "stand-in-api@anchor/stand-in")
o := pass(t, v, standIn)
if o.Outcome != PairHeld || !strings.Contains(o.Why, "old on ace") {
t.Fatalf("a bind while a consumer is filled the old way: %+v", o)
}
if got, gen, _ := asks(v, "provisioner.g14", standIn); got != "shared" || gen != 1 {
t.Fatal("the value was remade while a consumer filled the old way holds it")
}
if _, err := v.Rotate(ControllerCaller, standIn, "person.jochen", "why not"); err == nil ||
!strings.Contains(err.Error(), "old on ace") {
t.Fatalf("a rotation while a consumer is filled the old way: %v", err)
}
// Once it moves, the remake the bind asked for follows.
mirror["ace.old"] = handedWith("ace", "old", "stand-in-api@anchor/stand-in")
if o := pass(t, v, standIn); o.Outcome != PairRemade {
t.Fatalf("after the consumer moved: %+v", o)
}
})
}
// A pass that cannot read every assignment makes nothing: a bind it missed would read as an unbind.
func TestAPassThatCannotReadTheAssignmentsMakesNothing(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
}
v := pairVault(t, mirror)
movedRow(t, v, "g14", "app", "shared", "stamp-1", OriginMade)
pass(t, v, standIn)
mirror["g14.broken"] = "not json"
if _, err := v.PairPass(); err == nil {
t.Fatal("a pass over an unreadable assignment said nothing")
}
v.Assignments.Keys = func() ([]string, error) { return nil, errors.New("the bus is away") }
if _, err := v.PairPass(); err == nil {
t.Fatal("a pass that could not list the assignments said nothing")
}
if _, gen, _ := asks(v, "provisioner.g14", standIn); gen != 1 {
t.Fatal("a pass that could not read the assignments remade the value")
}
}
// A module only pulled in by another has a value of its own in the mirror (issue 765), naming what requires it: its
// plan binds like an assigned module's.
func TestAPulledInConsumerBindsLikeAnAssignedOne(t *testing.T) {
mirror := assignments{
"anchor.stand-in": handedWith("anchor", "stand-in"),
"g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"),
}
v := pairVault(t, mirror)
movedRow(t, v, "g14", "app", "shared", "stamp-1", OriginMade)
pass(t, v, standIn)
mirror["ace.helper"] = strings.Replace(handedWith("ace", "helper", "stand-in-api@anchor/stand-in"),
`"module":"helper",`, `"module":"helper","required-by":"desk",`, 1)
if o := pass(t, v, standIn); o.Outcome != PairRemade {
t.Fatalf("a pulled-in consumer binding: %+v", o)
}
if _, _, err := asks(v, "provisioner.ace", standIn); err != nil {
t.Fatalf("the pulled-in consumer's machine was refused: %v", err)
}
}