catalogue: compose a route's name from a label and its node's domain, and resolve it in-mesh
A public route used to carry its whole hostname as a literal in the module manifest, so running the same catalogue against a different domain meant overriding that literal on every routed module, per node. The mesh was, in effect, holding a map of names to services: the one thing it should never hold, because the subdomain is the operator's choice and the domain is the node's. Compose instead. A route contribution carries a `label` (the subdomain); a node carries its `public_domain` as node-level configuration; the mesh joins `<label>.<public-domain>` and grants exactly that, interpreting neither half. Held as a node property beside the node's other node-level facts (endpoint, site, overlay address), not in a module's settings — the ADR calls it node-level, and the settings table is keyed per module. Additive, so an unmigrated catalogue keeps working: a contribution that still carries a full `name` and no `label` passes through unchanged, and the catalogue can migrate module by module. A labelled contribution on a node with no public domain composes nothing, reading downstream as a route that named no host. And propagate: each granted route name is published into internal resolution mesh-wide, mapped to the node that serves it, alongside the `<node>.internal` names every container already gets. So a container — and an internal ACME validator, which cannot complete a challenge for a name it cannot reach — resolves a routed name to the proxy that serves it. Name-agnostic throughout: the mesh propagates whatever names it was told to serve and knows nothing about what they mean. novox/hq 02-DECISIONS/0056 Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
@@ -24,6 +24,10 @@ type Node struct {
|
||||
// At is this machine's own name on the private network, empty if it is not on one. Needed to
|
||||
// tell whether it can reach the node answering its requirements at all.
|
||||
At string
|
||||
// PublicDomain is the domain this node composes its routed names under, empty if it has none
|
||||
// (novox/hq ADR 0056). A route contribution carries only a label — the subdomain — and the mesh
|
||||
// joins <label>.<public-domain> to make the name it grants, interpreting neither half.
|
||||
PublicDomain string
|
||||
}
|
||||
|
||||
// World is what the rest of the mesh already has.
|
||||
@@ -102,6 +106,10 @@ type Resolution struct {
|
||||
// because a consumer bound to something answered on this same machine still has to be told
|
||||
// where it is — the answer being local does not make the port guessable.
|
||||
At string
|
||||
// PublicDomain is the domain this node composes its routed names under, empty if it has none
|
||||
// (novox/hq ADR 0056). Carried from the node so that composing <label>.<public-domain> for a
|
||||
// route contribution needs no store lookup here — the join is a fact about this one machine.
|
||||
PublicDomain string
|
||||
|
||||
// Modules in the order they were resolved: assigned first, then what they pulled in.
|
||||
Modules []Manifest
|
||||
@@ -504,8 +512,8 @@ func Resolve(catalogue map[string]Manifest, assigned []string, node Node, world
|
||||
}
|
||||
}
|
||||
|
||||
resolution := Resolution{Node: node.Name, At: node.At, Because: because, Needs: needs,
|
||||
Unhostable: unhostable}
|
||||
resolution := Resolution{Node: node.Name, At: node.At, PublicDomain: node.PublicDomain,
|
||||
Because: because, Needs: needs, Unhostable: unhostable}
|
||||
for _, n := range providersFirst(order, catalogue) {
|
||||
resolution.Modules = append(resolution.Modules, catalogue[n])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user