Read the foundation's ports from each node's settings, wherever a port is used (hq ADR 0100)

This commit is contained in:
2026-09-22 17:31:07 +02:00
parent 1ea84f8b8f
commit dbf62b5212
9 changed files with 352 additions and 6 deletions
+36 -1
View File
@@ -133,12 +133,20 @@ type Rendering struct {
// force, so no module that loads a filter is declared there, and what the mesh needs
// reachable is declared as openings, with its own ports guarded by a table that only refuses.
Adopted bool
// Given is the machine ports this node was given for its modules' ports, by module and by the
// port the software uses (novox/hq ADR 0100) — the foundation's ports, as genesis chose them.
// They win over anything the mesh would assign and over a manifest's own long-form mapping.
Given map[string]map[int]int
}
// machinePort is where a module's port lives on this machine, or the port itself when the mesh has
// not been asked. Unassigned is not an error here: a module with no `listens` never needed one,
// and a caller composing a declaration without a store still gets something coherent.
func (r Rendering) machinePort(module string, wanted int) int {
if at, given := r.Given[module][wanted]; given {
return at
}
if at, known := r.Ports[module][wanted]; known {
return at
}
@@ -1188,7 +1196,11 @@ func publishedOn(resource map[string]any, module string, with Rendering) {
for _, entry := range listed {
written := fmt.Sprint(entry)
if strings.Contains(written, ":") {
out = append(out, written)
// Written the long way, and left alone — unless this node was given a machine port for
// it (novox/hq ADR 0100): the foundation's ports are the node's, and a manifest's
// number is only the default. The outer port only; an address and the software's
// port stay as written.
out = append(out, givenOuter(written, with.Given[module]))
continue
}
wanted, err := strconv.Atoi(strings.TrimSpace(written))
@@ -1203,6 +1215,29 @@ func publishedOn(resource map[string]any, module string, with Rendering) {
resource["ports"] = out
}
// givenOuter rewrites the machine side of a long-form mapping to the port this node was given for
// its software side, when it was given one.
func givenOuter(written string, given map[int]int) string {
if len(given) == 0 {
return written
}
mapping, protocol := written, ""
if cut := strings.LastIndex(written, "/"); cut >= 0 {
mapping, protocol = written[:cut], written[cut:]
}
parts := strings.Split(mapping, ":")
inner, err := strconv.Atoi(strings.TrimSpace(parts[len(parts)-1]))
if err != nil {
return written
}
at, ok := given[inner]
if !ok {
return written
}
parts[len(parts)-2] = strconv.Itoa(at)
return strings.Join(parts, ":") + protocol
}
// ServedOn is what a provider tells a consumer, with the port that machine actually uses.
//
// **The module writes the port once, in `listens`** (novox/hq ADR 0038). It used to write it three