An address is read from the node's settings where it is used, never recorded with a port

Three readers did not follow a moved foundation port (novox/hq 04-ISSUES/102),
and each took the control-node down in its own way: the control plane's own
store and broker connections, sealed at genesis with the port inside; and every
build the mesh ever recorded, kept as `<registry>:<port>/<module>/<artifact>@…`.

The control plane cannot open its own sealed connections to move a port, and it
cannot bind the store as a consumer would — a binding mints a credential. So its
settings get a third twin: `NAME_PORT`, composed into its container from the
node's settings by a placeholder that names a seat, `${seat:mesh-store:5432}`,
and read on top of the sealed value by the store, the broker, the management API
and the bus connection. The answer is empty when the mesh has nothing to add,
so what genesis wrote stands until the node says otherwise.

A build is now recorded by digest and path — `artifact-store://<module>/<artifact>@…`
— and the store's address is composed in where a reference is used: the
declaration, the trust file, the bases a build is handed, a replay to the
catalogue. A reference recorded before this, with an address, is re-routed the
same way when the mesh built it. The trust file and every provider's address
now come from one derivation, with the node's given port over the mesh's
assignment over the manifest's number.

novox/hq 04-ISSUES/102
This commit is contained in:
2026-09-23 23:26:43 +02:00
parent 8fb32d7ee0
commit b7da02e370
20 changed files with 1463 additions and 46 deletions
+27
View File
@@ -143,6 +143,23 @@ type Rendering struct {
// from these only (ADR 0103): a port of a module assigned but not taken may still be the
// predecessor's.
Taken map[string]bool
// Seats is where this machine put each mesh-scoped seat's holder, by seat and by the port the
// holder's software uses (novox/hq 04-ISSUES/102) — read from the node's settings and
// assignments for whichever module claims the seat, whether or not it is in this node's set.
// What ${seat:…} answers with; see seat_into.go for why the answer may be absent.
Seats map[string]map[int]int
// ArtifactStore is the mesh's artifact store as this network reaches it (host:port) — the
// node holding it and the port that node put it on — or empty when the mesh has none on its
// network yet. Composed into every image and archive the mesh built, at this moment and never
// stored (novox/hq 04-ISSUES/102).
ArtifactStore string
// Built is every `<module>/<artifact>` the mesh has built. What tells a reference recorded
// with an address — before references were kept without one — from an image a module runs
// straight from a public registry.
Built map[string]bool
}
// machinePort is where a module's port lives on this machine, or the port itself when the mesh has
@@ -539,6 +556,11 @@ func (r Resolution) compose(with Rendering, owner map[string]string) ([]map[stri
if err := portInto(copied, m.Module, m.Listens, with); err != nil {
return nil, err
}
// And where this machine put the foundation's servers, for the one module that
// reaches them by seat rather than by binding (novox/hq 04-ISSUES/102).
if err := seatInto(copied, m.Module, with); err != nil {
return nil, err
}
if err := machineInto(copied, thisMachine, m.Module); err != nil {
return nil, err
}
@@ -550,6 +572,11 @@ func (r Resolution) compose(with Rendering, owner map[string]string) ([]map[stri
if err := built(copied, m.Module); err != nil {
return nil, err
}
// What the mesh built is kept by digest and path; the store's address is this
// network's now, composed here and never recorded (novox/hq 04-ISSUES/102).
if err := artifactsInto(copied, m.Module, with); err != nil {
return nil, err
}
publishedOn(copied, m.Module, with)
copied["id"] = m.Module + "." + fmt.Sprint(resource["id"])
// A service saying what it reflects names resources within its own module, so those