Carry the plan entry only on a key no plan names

A reader on an older mesh-sdk refuses a provision field it does not know,
so a key a plan names carries no entry: such readers skip only a key ahead
of its consumer's want, which they could never bind (issue 1126 review 1).

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-02 12:29:56 +01:00
parent fda81c129e
commit 9a3ead8fcd
2 changed files with 11 additions and 8 deletions
@@ -203,21 +203,23 @@ func (h *Holder) ComposeNode(ctx context.Context, node string) (out Composed, er
for _, p := range plan.Provisions {
consumer := provisions.End{Module: module, Node: node}
provider := provisions.End{Module: p.ProviderModule, Node: p.Provider}
// The key carries the plan entry it is composed from (issue 1126): the wanted build's where its plan names
// it, the newest's otherwise, so its provider binds it whichever plan the seat keeps.
entry := p
pv := provisions.Provision{Provision: p.Provision, Local: p.Local, Consumer: consumer, Provider: provider,
DependsOn: provisions.DependsOn(consumer, p, h.providerPlan(p, node, atWants)), Plan: &entry}
DependsOn: provisions.DependsOn(consumer, p, h.providerPlan(p, node, atWants))}
key, err := pv.Key()
if err != nil {
out.Problems = append(out.Problems, err.Error())
continue
}
if _, seen := needed[key]; !seen {
needed[key] = pv
if i == 1 {
// A key no plan names carries the newest build's entry, so its provider binds it (issue 1126). Only
// it: a reader on an older mesh-sdk refuses a field it does not know, and skips then only a key it
// could never bind anyway.
entry := p
pv.Plan = &entry
ahead[key] = module
}
needed[key] = pv
}
// Its credential is a provision of its own, the vault's (clause 6): on the consumer's node for a value of the
// consumer's own, on the provider's for the provider's one shared value.
@@ -544,7 +544,7 @@ func TestAProvidersOutcomeIsReadPerOffer(t *testing.T) {
// Issue 1126 review 1 (mcp-endpoint asked on ace and shanks, 2026-11-02 11:56): a requirement the consumer's newest build
// adds is keyed before its want, and the plan the seat keeps is its wanted build's, which names it not; the key carries
// the plan entry it was composed from, so the provider binds it, and its why says no plan names it yet. A key its
// wanted plan names carries that plan's entry.
// wanted plan names carries none.
func TestAKeyAheadOfItsWantCarriesItsPlanEntryAndSaysWhy(t *testing.T) {
m := newMesh()
m.atWant["g14"] = map[string]catalogue.Plan{"gitea": planOf(pgDB)}
@@ -559,8 +559,9 @@ func TestAKeyAheadOfItsWantCarriesItsPlanEntryAndSaysWhy(t *testing.T) {
if kc.State != provisions.Asked || !strings.Contains(kc.Why, "no plan names it") {
t.Errorf("the key ahead of its want: %s %q", kc.State, kc.Why)
}
if pg := m.state(t, "g14.gitea.postgres-database"); pg.Plan == nil || pg.Plan.ProviderModule != "postgres" ||
strings.Contains(pg.Why, "no plan names it") {
// A key a plan names carries no entry: a reader on an older mesh-sdk, which refused a field it did not know, reads it
// still, and skips only a key ahead of its want, which it could never bind (review 1).
if pg := m.state(t, "g14.gitea.postgres-database"); pg.Plan != nil || strings.Contains(pg.Why, "no plan names it") {
t.Errorf("the planned key: %+v", pg)
}
}