The machine has reported its host version since ADR 0141, whose own comment says why it must: without it nothing can say a machine is behind. The controller's copy of the report did not have the field, so it unmarshalled into nothing and was thrown away on arrival. Two structs describe one message and only the sending side had it. node show names it per machine, "not reported" where the mesh has not been told. status names every machine running an older host than another does, and which is newest. Disagreement rather than staleness, deliberately: nothing delivers a host version yet, so the mesh holds no canonical current one and "behind" has no fixed point. What it can say is that the oldest host in the mesh is what the mesh may send. Two refusals to guess: a machine that reported nothing is not called behind, and versions compare as strings — right for the timestamps this mesh uses, wrong for a scheme where 10 sorts before 9, said at the place that would have to learn. 107 gains the note that this is what makes its new field safe to consider, and that one machine of four is behind today, so it is not free yet.
2.1 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design | |||
|---|---|---|---|---|---|---|---|
| resolved | 2026-09-22 |
|
mesh-controller 7683ba8 |
087 — The controller cannot tell that a node's host is too old for what it sends
What was observed
Found in review of the adoption-mode build, 2026-09-22, by reading the code.
A host parses a declaration strictly: a field it does not know makes it refuse the whole declaration, and nothing is applied. That is deliberate, and it is what keeps a half-understood declaration off a machine. It also means every new field in a declaration is a flag day: hosts must be upgraded before the controller sends it.
The controller has no record of which version of the host a node runs. It is not in what a node reports, and it is not in the node's profile. So when a node refuses a declaration for that reason, the mesh shows the node failing and relays the host's refusal. Nothing says the host on this machine is older than what the mesh now sends, and nothing could have said so beforehand.
Adoption mode adds four such fields, one of them on the declaration of every node, and its merge order exists for this reason alone: the host merges first, every machine is upgraded, then the controller.
Why it matters beyond this instance
Every future field in a declaration has the same flag day, and the mesh upgrades itself. A mesh that cannot say which machines are ready for what it is about to send has to be upgraded by someone remembering the order. The rule that a host refuses what it does not understand is right; the missing half is that the controller should know before it sends.
Open questions
- Should a node report the version of its host, so the controller can refuse to send a declaration a node cannot parse, and say which machines are behind?
- Should the mesh refuse to send a field no node understands yet, or refuse per node and say so?
- Is there a general shape here — a declaration saying which version of the host it needs — or is a reported version enough?