diff --git a/04-ISSUES/107-a-declaration-carries-no-order/01-diagnosis.md b/04-ISSUES/107-a-declaration-carries-no-order/01-diagnosis.md new file mode 100644 index 0000000..de7e24e --- /dev/null +++ b/04-ISSUES/107-a-declaration-carries-no-order/01-diagnosis.md @@ -0,0 +1,68 @@ +# 107 — diagnosis: the fix is a flag day, and it should wait for delivery + +*2026-09-30. Read, measured, and not built — deliberately.* + +## The premise is confirmed + +A host parses a declaration with unknown fields refused, and the code says why rather than leaving it +to be inferred: + +> `DisallowUnknownFields` is the whole point rather than strictness for its own sake: a field the host +> does not know is a thing the control plane believes it asked for. + +So adding `sequence` and `supersedes` is not an additive change. **Any host that has not been upgraded +refuses the whole declaration and applies nothing** — which is exactly the behaviour that keeps a +half-understood declaration off a machine, and exactly what makes this expensive. + +## What has changed since this was filed + +[Issue 087](../087-the-controller-cannot-tell-a-host-is-too-old/00-report.md) is resolved: the mesh now +records the host version each machine reports and `status` names every machine running an older host +than another does. The flag day is visible before it is walked into, which it was not on 2026-09-23. + +That makes the cost measurable rather than hypothetical, and the measurement is the reason this is not +being built today. + +## Why it waits + +**One machine of four runs an older host, and it cannot be upgraded.** `ace` is adopted, deliberately +parked until the network and module-assignment work is settled, and **nothing delivers a host version at +all** — [ADR 0141](../../02-DECISIONS/0141-the-host-delivers-its-own-successor.md) is accepted and not +built, which is [issue 142](../142-the-host-is-the-one-thing-the-mesh-does-not-deliver/00-report.md). +Every machine takes a hand-placed binary. + +So shipping the field means, in order: place a host by hand on three machines, unpark the fourth, place +it there too, and only then turn the controller half on. A machine missed in that sequence is a machine +the mesh cannot send anything to at all — not degraded, unreachable. + +**And the fault it prevents has never been observed.** The record says so itself: *"Not observed; +constructed from the code, and narrow."* It needs a backlog of more than sixteen declarations queued +across a `converge`/`adopt` pair, or a broker slow enough to split one, and the host already applies the +newest of a drained batch and refuses a declaration that is not the last by digest. + +**Trading a machine's reachability for a replay nobody has seen is the wrong way round.** The right +order is [issue 142](../142-the-host-is-the-one-thing-the-mesh-does-not-deliver/00-report.md) first — +when the mesh can deliver a host, a declaration field costs a rollout instead of an expedition — and the +work order already puts that in its last group, as the proof that the mesh can make another of itself. + +## What the open questions look like now + +- *A per-node `sequence` under the controller's node hold, and `supersedes` as the previous digest?* + Still the right shape. The controller already holds the lock and already records each send, so the + order exists and is thrown away at the wire — unchanged since this was filed. +- *Genesis signing its bundle as sequence zero?* Yes, and it is the cheaper half: the bundle is written + by the host that will read it, so it has no flag day of its own. +- *Is a sequence enough, or does a mode change deserve its own marker?* A sequence alone does not stop + a replayed *converged* declaration reaching a node that has since been returned to adopted, which is + the incident of issue 104 by another door and is what this record names as its real risk. It wants + both, and the second is the one worth having first. +- **And one this record did not ask:** should a declaration say which host version it needs? 087 makes + that comparable for the first time, and it is the general form of the answer — a field that announces + its own requirement, rather than a flag day per field, for ever. + +## Status + +Left `located`. The owner is unchanged, the shape of the fix is agreed, and the gate is +[issue 142](../142-the-host-is-the-one-thing-the-mesh-does-not-deliver/00-report.md) rather than anything +in this record. **This is a judgement about order, not a refusal** — it is cheap to overrule, and the +code is a day's work once a host can be delivered. diff --git a/04-ISSUES/142-the-host-is-the-one-thing-the-mesh-does-not-deliver/00-report.md b/04-ISSUES/142-the-host-is-the-one-thing-the-mesh-does-not-deliver/00-report.md index b147e04..30b4e1d 100644 --- a/04-ISSUES/142-the-host-is-the-one-thing-the-mesh-does-not-deliver/00-report.md +++ b/04-ISSUES/142-the-host-is-the-one-thing-the-mesh-does-not-deliver/00-report.md @@ -74,3 +74,18 @@ every future change of this shape, and it was paid today. 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. diff --git a/04-ISSUES/145-a-machine-reads-healthy-while-its-modules-cannot-reach-each-other/00-report.md b/04-ISSUES/145-a-machine-reads-healthy-while-its-modules-cannot-reach-each-other/00-report.md index ee8ac6b..6931708 100644 --- a/04-ISSUES/145-a-machine-reads-healthy-while-its-modules-cannot-reach-each-other/00-report.md +++ b/04-ISSUES/145-a-machine-reads-healthy-while-its-modules-cannot-reach-each-other/00-report.md @@ -4,7 +4,7 @@ opened: 2026-09-29 located-in: - mesh-controller internal/catalogue/filtering.go (fixed for this instance) - mesh-controller (what status reports, and what it does not ask) -fixed-by: +fixed-by: partly — mesh-controller 1da96e8 makes the report state its own scope; nothing dials a provision yet, which is ADR 0146 and is not built amended-design: 03-DESIGN/01-to-be/10-delivery.md --- diff --git a/04-ISSUES/145-a-machine-reads-healthy-while-its-modules-cannot-reach-each-other/01-resolution.md b/04-ISSUES/145-a-machine-reads-healthy-while-its-modules-cannot-reach-each-other/01-resolution.md new file mode 100644 index 0000000..8ec7ab5 --- /dev/null +++ b/04-ISSUES/145-a-machine-reads-healthy-while-its-modules-cannot-reach-each-other/01-resolution.md @@ -0,0 +1,64 @@ +# 145 — partly resolved: the report says what it is not a claim about + +*2026-09-30.* + +## What was done + +The sentence that was true for eleven hours now states its own scope, immediately below itself: + +``` +4 machine(s), all doing what they were told, all heard from, running what the mesh would send +them, and every module current with its source + + That is the mesh and the machines agreeing. Nothing here dials a provision: + no grant the mesh composed has been tested, so a module unable to reach what it + requires would not appear above (04-ISSUES/145) +``` + +That is the whole of what this change does, and it is deliberately small. It does not check anything. +It closes the distance between *the machines are as the mesh described them* and *it works* by naming +it, and that distance is where the eleven hours went: the report was read as the second and only ever +meant the first. + +Two other reports in this group now carry real information they did not +([issue 125](../125-a-hold-is-not-a-line-in-the-apply-report/00-report.md): a hold is a line in the +apply report and breaks the all-well sentence; +[issue 087](../087-the-controller-cannot-tell-a-host-is-too-old/00-report.md): the mesh knows which +host runs a machine). Neither would have caught this fault, and both were the same shape of blindness. + +`printStatus` is now separated from the asking, so these words can be read by a test with no store, bus +or machine — they have been acted on and been misleading twice, which makes them worth holding still. + +## What is NOT done, and why this record stays open + +**Nothing dials a provision.** [ADR 0146](../../02-DECISIONS/0146-connectivity-is-checked-by-name-per-hosting-form.md) +decides how it should be done — a module on every machine serving an endpoint of its own and dialling +every other machine's, one name per hosting form, over TLS with the certificate verified. **Nothing is +built**, the module that existed was deleted, and the work was deferred deliberately by the operator. +It is not this record's to start. + +So the measured fault of this issue — that the mesh can only report on itself — is unchanged. What +changed is that the report no longer implies otherwise. + +## The open questions, where they stand + +- *Should a grant be checked, and from where?* Answered by ADR 0146 and not built: from the position + the callers are in, by a module on every machine, per hosting form. +- *What would it cost to be wrong in the other direction?* Unanswered and important. A check that + reports a provision broken while it works trains a reader to ignore the report, which is the failure + this whole issue is about arriving by the other door. +- *What should `status` say about a machine whose modules cannot reach each other?* Answered in part: + until something checks, it says that it has not checked. What it says when a check exists is ADR + 0146's to settle. +- *Is there a cheaper signal than a probe?* Still open. The affected module logged the failure 6,154 + times; the mesh reads no module's logs and arguably should not, but something a module could *say* + about its own provisions would have surfaced this in minutes. +- *Does the same blindness apply to a provider that lost a consumer's grant?* Still open, and still + nothing checks it. + +## One thing worth carrying forward + +**The certificate half of ADR 0146 is now possible where it was not.** Its check requires an internal +name fetched over TLS with the certificate verified, and until 2026-09-30 no machine trusted the mesh's +authority at all ([issue 129](../129-nothing-makes-a-machine-trust-the-meshs-authority/02-resolution.md)). +Three of four do now. Whoever builds 0146 no longer has to solve that first.