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:
@@ -22,7 +22,7 @@ import (
|
||||
|
||||
func nodeCommand(ctx context.Context, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("node add <name>, node list, or node show <name>")
|
||||
return errors.New("node add <name>, node list, node show <name>, or node public-domain <name> [domain]")
|
||||
}
|
||||
open, err := openStores(ctx)
|
||||
if err != nil {
|
||||
@@ -65,8 +65,30 @@ func nodeCommand(ctx context.Context, args []string) error {
|
||||
}
|
||||
return nil
|
||||
|
||||
case "public-domain":
|
||||
// The domain this node composes its routed names under (novox/hq ADR 0056). Given a domain,
|
||||
// it is set; given nothing, it is cleared — a node that stops facing the outside composes no
|
||||
// names. Lab-versus-production is this one setting and nothing else (see the ADR).
|
||||
if len(args) < 2 || len(args) > 3 {
|
||||
return errors.New(
|
||||
"node public-domain <name> [domain] — a domain sets it, nothing clears it")
|
||||
}
|
||||
domain := ""
|
||||
if len(args) == 3 {
|
||||
domain = args[2]
|
||||
}
|
||||
if err := inv.SetPublicDomain(ctx, args[1], domain); err != nil {
|
||||
return err
|
||||
}
|
||||
if domain == "" {
|
||||
fmt.Printf("%s has no public domain, so it composes no routed names\n", args[1])
|
||||
} else {
|
||||
fmt.Printf("%s composes its routed names under %s\n", args[1], domain)
|
||||
}
|
||||
return nil
|
||||
|
||||
default:
|
||||
return fmt.Errorf("node has no %q; it has add and list", args[0])
|
||||
return fmt.Errorf("node has no %q; it has add, list, show and public-domain", args[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +283,17 @@ func showNode(ctx context.Context, inv *inventory.Inventory, name string) error
|
||||
fmt.Printf("%s\n", node.Name)
|
||||
fmt.Printf(" last heard from %s\n", heardFrom(node))
|
||||
|
||||
// The domain its routed names are composed under, when it has one (novox/hq ADR 0056). Shown
|
||||
// only when set: a machine that serves nothing to the outside has no domain, and saying so of
|
||||
// every internal node would be noise.
|
||||
domain, err := inv.PublicDomainOf(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if domain != "" {
|
||||
fmt.Printf(" public domain %s\n", domain)
|
||||
}
|
||||
|
||||
held, err := inv.Profile(ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user