Keep one list of credential forms in the catalogue, so no reader of a plan refuses a form another writes (issue 774)
mesh/delivery merged: source.main moved to novox/mesh-sdk@d0625eea3d11
mesh/delivery-group group fix/credential-forms-one-list merged: every member is merged
mesh/check checking 9379e9a96ad4 on d0625eea3d11 | novox/mesh-sdk#135 in group fix/credential-forms-one-list

Second meeting of the credential-form list kind: the provisioner client's
own copy lacked "none" and refused every plan naming it, as the
controller's had before. Thorough: one list in mesh-sdk,
catalogue.CredentialForms and IsCredentialForm; provisions' forms are now
the catalogue's constants.
This commit is contained in:
2026-10-30 16:03:14 +01:00
parent 0c99e847a2
commit 9379e9a96a
3 changed files with 26 additions and 6 deletions
+7
View File
@@ -153,6 +153,13 @@ func TestAHandedModulesPlanNamesTheCredentialFormOfItsProvidersOffer(t *testing.
if len(got) != 1 || got[0].CredentialForm != want {
t.Errorf("an offer with %q: the plan names %+v, want the form %q", credential, got, want)
}
// Every form a plan names is in the one list each reader checks (issue 774); an undeclared one is not.
if IsCredentialForm(want) != (want != "") {
t.Errorf("the form %q of an offer with %q: in CredentialForms %v", want, credential, IsCredentialForm(want))
}
}
if forms := strings.Join(CredentialForms(), ","); forms != "shared,pair,issued,given,none" || IsCredentialForm("maybe") {
t.Errorf("the credential forms are %s, and maybe is one: %v", forms, IsCredentialForm("maybe"))
}
if got := (Manifest{Module: "x"}).CredentialFormOf("postgres-database"); got != "" {
t.Errorf("a module offering nothing has the credential form %q", got)
+12
View File
@@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"regexp"
"slices"
"sort"
"strconv"
"strings"
@@ -371,6 +372,17 @@ const (
CredentialFormNone = "none"
)
// CredentialForms is the one list of the credential forms a plan's entry may name (issue 774): every part that reads
// a plan checks a form here, so a form added above reaches each of them at once. Each part kept its own copy before,
// and a copy left without "none" refused every plan naming it.
func CredentialForms() []string {
return []string{CredentialFormShared, CredentialFormPair, CredentialFormIssued, CredentialFormGiven,
CredentialFormNone}
}
// IsCredentialForm is whether form is one of CredentialForms.
func IsCredentialForm(form string) bool { return slices.Contains(CredentialForms(), form) }
// CredentialFormOf is the credential form this module's offer of a provision declares, read from the offer's
// `credential` alone (issue 768): no new manifest field, since that field already says whether the provider shares
// one of its own secrets, its software issues it, or a person gives it, and saying none is a login per consumer.
+7 -6
View File
@@ -93,15 +93,16 @@ func PlanKey(node, module string) (string, error) {
return node + "." + module, nil
}
// The forms of a provision's credential, as a plan's entry names them (catalogue.PlanProvision.CredentialForm).
// The forms of a provision's credential, as a plan's entry names them (catalogue.PlanProvision.CredentialForm): the
// catalogue's one list (catalogue.CredentialForms, issue 774), under the names this package has used.
const (
FormPair = "pair"
FormShared = "shared"
FormIssued = "issued"
FormGiven = "given"
FormPair = catalogue.CredentialFormPair
FormShared = catalogue.CredentialFormShared
FormIssued = catalogue.CredentialFormIssued
FormGiven = catalogue.CredentialFormGiven
// FormNone is an offer whose consumers present no credential (catalogue.CredentialFormNone): the vault mints nothing,
// and the provision depends on no credential.
FormNone = "none"
FormNone = catalogue.CredentialFormNone
)
// VaultName is the vault's name of a provision's credential in form, as its verb `own` names it and the provider asks