Files
mesh-host/internal/compose/resolution/served_own_names.go
T
jschoubben d68e241724 Take the catalogue's composition rules into the node-engine
ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk
carries no composition rule. The catalogue functions only the
node-engine's composition reaches (Resolve, Resolution's Compose,
Declaration, DataItems, LeftOut, Rules and the rest, the settings,
placeholder and template refusals, the rendering helpers) are copied
with their tests into internal/compose/resolution; a method of a
mesh-sdk shape becomes a function taking it first. The composition
calls its own copies, and the captured catalogue its tests read lives
here now, shared by mesh-compose's tests.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 19:15:55 +01:00

90 lines
2.4 KiB
Go

package resolution
import (
"fmt"
"sort"
mcat "git.novox.be/novox/mesh-sdk/go/catalogue"
)
// requirementsContributedTo is every requirement m contributes to, sorted.
func requirementsContributedTo(m mcat.Manifest) []string {
seen := map[string]bool{}
for to := range m.Contributes {
seen[to] = true
}
for to := range m.ContributesMany {
seen[to] = true
}
out := make([]string, 0, len(seen))
for to := range seen {
out = append(out, to)
}
sort.Strings(out)
return out
}
// ServedOwnNames fills the provider's own composed names into what it serves one provision's
// consumers, from this resolution's composition of the provider's machine (ADR 0346).
//
// A value naming a name this machine does not compose is left out, with its key, and said. The map is
// copied only when something changes, as ServedTo does: the caller's may be the manifest's.
func ServedOwnNames(r mcat.Resolution, m mcat.Manifest, provision string, serves map[string]any, layers []mcat.Layer) (
map[string]any, []string, error) {
var asking []string
for _, key := range sortedAnyKeys(serves) {
if text, ok := serves[key].(string); ok && bound.MatchString(text) {
asking = append(asking, key)
}
}
if len(asking) == 0 {
return serves, nil, nil
}
own := map[string]map[string]string{}
for _, to := range requirementsContributedTo(m) {
names, err := resolutionOwnNames(r, m, to, layers)
if err != nil {
return nil, nil, err
}
values := map[string]string{}
withOwnNames(values, names)
own[to] = values
}
out := make(map[string]any, len(serves))
for k, v := range serves {
out[k] = v
}
var said []string
for _, key := range asking {
text := serves[key].(string)
var missing string
filled := bound.ReplaceAllStringFunc(text, func(token string) string {
parts := bound.FindStringSubmatch(token)
if value := own[parts[1]][parts[2]]; value != "" && parts[3] == "" {
return value
}
if missing == "" {
missing = token
}
return token
})
if missing != "" {
delete(out, key)
said = append(said, fmt.Sprintf(
"%s serves %s without %q: it names %s, and %s composes no such name for %s (it has no "+
"public domain, or the endpoint is not reached publicly) (novox/hq ADR 0346)",
m.Module, provision, key, missing, orHere(r.Node), m.Module))
continue
}
out[key] = filled
}
return out, said, nil
}
func orHere(node string) string {
if node == "" {
return "this machine"
}
return node
}