Files
hq/04-ISSUES/142-the-host-is-the-one-thing-the-mesh-does-not-deliver/00-report.md
T
jschoubben b7f7b97d8a Group 1: 145's report states its scope, and 107 waits for delivery
145, partly resolved. The sentence that was true for eleven hours of a
mesh in which no module could reach another now says what it is not a
claim about: that is the mesh and the machines agreeing, and nothing here
dials a provision. It checks nothing and does not pretend to — ADR 0146
decides the check and is deliberately not built. What changed is that the
report no longer implies otherwise. Stays open for that reason.

Carried forward: 0146's check needs an internal name fetched over TLS with
the certificate verified, and until today no machine trusted the mesh's
authority. Three of four do now, so whoever builds it does not have to
solve that first.

107, diagnosed and deliberately not built. The premise is confirmed in the
host's own words — unknown fields are refused because "a field the host
does not know is a thing the control plane believes it asked for" — so the
fix is a flag day, not an addition. 087 now makes the cost measurable, and
the measurement is why it waits: one machine of four runs an older host,
it is parked, and nothing delivers a host at all (142). Shipping the field
means hand-placing binaries and unparking a machine, and one missed in
that sequence is unreachable, not degraded. The fault it prevents has
never been observed.

142 gains the note that it is 107's gate, and that it is what makes a
declaration field cost a rollout instead of an expedition.

A judgement about order, not a refusal, and cheap to overrule.
2026-09-30 09:00:18 +02:00

92 lines
5.4 KiB
Markdown

---
status: located
opened: 2026-09-29
located-in:
- mesh-host internal/upgrade
- mesh-host cmd/mesh-host
- mesh-controller (no build source for the host; no resource delivers it)
fixed-by:
amended-design: 03-DESIGN/01-to-be/05-the-node-host.md
---
# 142 — The host is the one thing the mesh does not deliver
## What was observed
A change to the host was merged and could not reach any machine without a person copying a file.
Checked on the mesh of four machines, 2026-09-29:
- **The host is not a build target.** Asked what had been built for it, the control plane answered
`nothing has been built for mesh-host`. A merge on the forge builds every changed module and the
control plane itself, because the control plane is a module. The host is not one, and nothing
builds it.
- **No declaration delivers it.** No resource kind names an executable to place on a machine, and
nothing on a machine fetches one.
- **The half that recovers from a bad host exists and is unused.** `internal/upgrade` can report that
the executable this process started from has been replaced on disk, and records which version last
completed a reconcile so a shell script can roll back a host that will not start. The launcher reads
that record and rolls back. But `Replaced()` is called by nothing except its own tests — the
recovery is wired and the delivery was never built.
- **Every machine runs a byte-identical binary, stamped by hand.** All four carry the same size and
the same timestamp, from the last time somebody built it on a workstation and copied it out. No
package owns the file.
## Why it matters beyond this instance
**The component that implements updating is the one thing not updated.** The mesh's stated shape is
that a push produces the right builds and they reach the machines running them with nobody asking. It
is true of every module and of the control plane. It is false for the host, which is what applies all
of them.
**It is a bootstrap problem being answered by a person.** The host cannot be an ordinary module
because the host is what applies modules; a module that replaces the thing applying it has to survive
its own replacement. That is a real difficulty, and the work already done — noticing that the
executable changed, recording a known-good version, a launcher that rolls back — is the hard half of
solving it. What is missing is the easy half, and its absence makes the hard half dead code.
**A hand-copied binary has no record anywhere.** Nothing says which version a machine runs, so
nothing can say a machine is behind, and the mesh's own account of itself — every machine current with
its source — cannot include the host. Four machines agreeing today is luck, not a property.
**And it silently gates any change that starts in the host.** A change that needs the host to report
something new cannot be rolled out by merging it: the control plane must wait for a person, and until
then it either refuses what depends on the new report or renders something wrong. That cost is paid by
every future change of this shape, and it was paid today.
## Open questions
- How is the host delivered without being applied by itself? A candidate shape: the host is built like
anything else, published as an artifact, and the *running* host fetches and stages the next one, then
stands aside — which is what `Replaced()` was written for and what the launcher's rollback already
covers.
- **Should this ride the bus, rather than becoming a mechanism of its own?** Everything else that
reaches a machine already does: a declaration is sent over it, a report comes back over it, and a
build announces what it produced on it, which is how a module's new version reaches the machines
running it. A host build announcing itself the same way, consumed by the host already running,
would make this the existing mechanism pointed at one more artifact rather than a second way of
delivering things. It would also give the machine somewhere to say which host it is running, on the
report it already sends.
- What records which version of the host a machine runs, so "behind" is answerable? Nothing does now.
- Does the host's version belong in its report, beside the other facts a machine states about itself?
- Who decides when a machine takes a new host — the mesh, on a build, or an operator per machine as
with converging? The rollback path means a bad host costs a reconcile rather than a machine, which
argues for the former.
- Does the same gap apply to the launcher and the units beside the binary, which are also files no
declaration names?
## What now waits on this (2026-09-30)
[Issue 107](../107-a-declaration-carries-no-order/00-report.md) — a declaration carries no order, so a
host cannot tell an older one from a newer. Its fix adds a field to the declaration, and a host refuses a
declaration carrying a field it does not know, **whole**. So it is a flag day: every host upgraded, then
the controller.
With nothing delivering a host, that means placing a binary by hand on every machine and unparking the
adopted one, and a machine missed in the sequence is a machine the mesh cannot send anything to at all.
107 is held for that reason rather than for anything in its own diagnosis.
**This is what makes a declaration field cost a rollout instead of an expedition**, which is a use for
this record beyond keeping machines current: it is the thing standing between the mesh and its own
protocol evolving.