package provisions import ( "strings" "testing" "time" "git.novox.be/novox/mesh-sdk/go/catalogue" ) // ADR 0570 clauses 1, 2 and 5 (issue 1954 L6-P2): a provision's key is its consumer's node and module, the provision and // its local name, the provider's entry's key; its value round-trips, names its state and why, and refuses any field the // layout does not name, so no value rides in it; a plan's key is its node and module. func TestAProvisionIsAReferenceUnderItsConsumersKey(t *testing.T) { at := time.Date(2026, 10, 29, 22, 0, 0, 0, time.UTC) db := Provision{Provision: "postgres-database", Consumer: End{Module: "keycloak", Node: "novox"}, Provider: End{Module: "postgres", Node: "novox"}, DependsOn: []string{"novox.keycloak.secret.db"}, State: Asked, Reference: &Reference{ID: "provision/postgres/postgres-database", Generation: 2}, At: at} for _, c := range []struct { name string edit func(*Provision) key string refused string }{ {name: "asked, depending on the vault's", key: "novox.keycloak.postgres-database"}, {name: "under a local name", edit: func(p *Provision) { p.Local = "replica" }, key: "novox.keycloak.postgres-database.replica"}, {name: "retiring with the operator's warrant", edit: func(p *Provision) { p.State, p.Why, p.Ask = Retiring, "keycloak left novox", "a-1" p.Warrant = &Warrant{Ask: "a-1", Option: "yes", By: "the operator", At: at} }, key: "novox.keycloak.postgres-database"}, {name: "an unknown state", edit: func(p *Provision) { p.State = "done" }, refused: "one of"}, {name: "failed without why", edit: func(p *Provision) { p.State = Failed }, refused: "says why"}, {name: "a warrant on a provided one", edit: func(p *Provision) { p.State, p.Warrant = Provided, &Warrant{Ask: "a"} }, refused: "only a retiring"}, {name: "no provider", edit: func(p *Provision) { p.Provider = End{} }, refused: "no provider"}, {name: "a dotted consumer", edit: func(p *Provision) { p.Consumer.Module = "a.b" }, refused: "cannot be part"}, {name: "a dependency that is no key", edit: func(p *Provision) { p.DependsOn = []string{"x"} }, refused: "is not"}, } { p := db if c.edit != nil { c.edit(&p) } raw, err := Encode(p) if c.refused != "" { if err == nil || !strings.Contains(err.Error(), c.refused) { t.Errorf("%s: %v, want refused saying %q", c.name, err, c.refused) } continue } back, err := Decode(raw) key, kerr := back.Key() if err != nil || kerr != nil || key != c.key || back.V != Version || back.Reference.Generation != 2 { t.Errorf("%s: read back as %+v under %q, %v %v", c.name, back, key, err, kerr) } if node, consumer, provision, local, err := ParseKey(key); err != nil || node != "novox" || consumer != "keycloak" || provision != "postgres-database" || local != p.Local { t.Errorf("%s: %s parses as %s %s %s %s, %v", c.name, key, node, consumer, provision, local, err) } } // A value never rides in a provision: a field the layout does not name is refused. if _, err := Decode([]byte(`{"v":1,"provision":"p","consumer":{"module":"c","node":"n"},"provider":{"module":"p","node":"n"},` + `"state":"provided","at":"2026-10-29T22:00:00Z","password":"hunter2"}`)); err == nil { t.Error("a provision carrying a password was read") } plan := Plan{Node: "novox", Module: "restic", Plan: catalogue.Plan{}} raw, err := EncodePlan(plan) if err != nil { t.Fatal(err) } if back, err := DecodePlan(raw); err != nil || back.Node != "novox" || back.Module != "restic" { t.Errorf("a plan read back as %+v, %v", back, err) } if k, err := PlanKey("novox", "restic"); k != "novox.restic" || err != nil { t.Errorf("a plan's key is %q, %v", k, err) } // A reference's id is the vault's name as its verb own names it, in each form (the host agent, 2026-10-29). for form, want := range map[string]string{FormPair: "pair/novox/postgres-database/novox/keycloak", FormShared: "provision/novox/postgres-database", FormIssued: "provision/novox/postgres-database/novox/keycloak", "none": ""} { if got := VaultName(form, db); got != want { t.Errorf("the %s name is %q", form, got) } } if got := VaultName(FormPair, Provision{Provision: "p", Local: "r", Provider: End{Node: "a"}, Consumer: End{Node: "b", Module: "m"}}); got != "pair/a/p/b/m/r" { t.Errorf("a local name's pair is %q", got) } if ProvisionsBucket != "mesh-provisioner_provisions" || PlansRead != "mesh-provisioner.plans" { t.Errorf("the states are %s and %s", ProvisionsBucket, PlansRead) } }