package catalogue import "slices" // The one rule of which provisions the seat mesh-provisioner keys and a want waits for (novox/hq ADR 0570 §1, §2, §4; // issue 774). The plan composition puts a need in a consumer's plan by it, the holder of mesh-provisioner keys what the // plans name, and the assigner's rule 8 waits for what Awaited answers: three parts, one rule, so they cannot drift // again (on 2026-10-30 the assigner waited for every `requires` while the plans named only some, and every new build of // grafana, dnsmasq, mesh-knowledge, mesh-mail and the builders waited for a key nobody would make). // // A need a module answers (not a record, not nothing) is keyed when its consumer is handed to the provisioner, or the // provider's offer says the provider helper answers it. A need of a consumer not handed whose provider's helper does // not answer it is still answered by the controller's composition: it is neither keyed nor waited for. // HandedByManifest is whether a module is handed to the provisioner as far as its manifest says (Rendering.Handing // without the machine's own words, and begin's): marked moved, not a held module's stub, with a template its build // kept or an item. func (m Manifest) HandedByManifest() bool { return m.Moved && m.Handed != nil && !m.Stubbed && (len(m.Handed.Templates) > 0 || len(m.Items) > 0) } // Keyed is whether a need is a provision of the seat mesh-provisioner: a key, an entry in its consumer's plan, and a // wait of the consumer's want. consumerHanded is whether the composition hands the consumer to the provisioner. func Keyed(consumerHanded bool, n Needed) bool { if n.ByRecord || n.Module == "" || n.From == "" { return false } return consumerHanded || n.AnsweredByHelper } // Awaited is, of what consumer requires (not optionally), each provision Keyed answers yes for, judged from manifests // alone, as the assigner reads them: providers answers the modules providing a provision. A provision is a need when a // provider offers it to the mesh, or one on the consumer's machine serves facts about it (Resolve: one answered on the // machine with nothing served binds nothing). It is keyed when the consumer is handed, or every provider's offer is // answered by the helper: where the providers disagree, which one answers is the composition's, and nothing is waited // for that might never be keyed. Sorted, each once. func Awaited(consumer Manifest, providers func(provision string) []Manifest) []string { var out []string for _, r := range consumer.Requires { if consumer.OptionalRequires[r] || slices.Contains(out, r) { continue } by := providers(r) if len(by) == 0 { continue } need, helper := false, true for _, p := range by { for _, o := range p.Provides { if o.Name != r { continue } if o.At() == ScopeMesh || len(p.Serves[r]) > 0 { need = true } } if !p.AnsweredByHelperFor(r) { helper = false } } if need && (consumer.HandedByManifest() || helper) { out = append(out, r) } } slices.Sort(out) return out }