From f6ed3545b765ba6e6bb36148456a12b728b43b33 Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 29 Sep 2026 17:36:40 +0200 Subject: [PATCH] Issue 146: a first node now enrols, and is enrolled twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two more faults behind the three already fixed. The account a token is the password of was never recorded, and the comment above the issuing code said it was; issuing now records it. Placing the composed list at genesis is the other half — the control plane says what it composed and whoever raises the machine writes it beside the bus, because no declaration can reach a machine that has not enrolled. With that a first node enrols. It is then enrolled twice from one attempt, each minting a credential, and it keeps the answer to the first while the mesh keeps the second. The trail for that one stops at a duplicate that survived message-id deduplication. --- .../01-diagnosis.md | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/04-ISSUES/146-the-foundation-cannot-be-raised-on-the-bus-the-mesh-runs-on/01-diagnosis.md b/04-ISSUES/146-the-foundation-cannot-be-raised-on-the-bus-the-mesh-runs-on/01-diagnosis.md index bcbd17b..34c2817 100644 --- a/04-ISSUES/146-the-foundation-cannot-be-raised-on-the-bus-the-mesh-runs-on/01-diagnosis.md +++ b/04-ISSUES/146-the-foundation-cannot-be-raised-on-the-bus-the-mesh-runs-on/01-diagnosis.md @@ -82,6 +82,54 @@ managing, or genesis carries a user list that includes the first node's enrolmen takes over from there. Both are decisions, not patches, and both belong to the genesis step that was deliberately left until last. +## 5 — the composed user list has to be placed by hand at genesis *(fixed)* + +The account a token is the password of is **not recorded at all**: the composer names an enrolment +user for every machine with a live token, nothing minted a credential for it, and the composition +left it out as a user with no password. The comment above the issuing code already claimed +otherwise — *"the account is created before the token is handed over"* — which is how it went +unnoticed. Issuing a token now records that account, with the token's own secret as its password, +because that is the string the machine will present. + +Placing it is the other half. The list reaches the machine running the bus in that machine's +declaration, which a machine that has not enrolled does not get, so at genesis it cannot arrive +that way. **The control plane composes and says what it composed** — `broker accounts`, to standard +output — and whoever is raising the machine writes it beside the bus's configuration and makes the +server re-read it. Twice, because two accounts come into existence at different moments: the +enrolment when the token is issued, and the machine's own when it enrols. A control plane that +wrote the file itself would have to know where the bus keeps its configuration and how to make it +reload, which is the module's knowledge and is what the module takes over on the first push. + +With that, **a first node enrols against the bus it just raised** — measured, from bare, in the +lab. + +## 6 — and is enrolled twice, keeping a credential the mesh has replaced *(open)* + +``` +mesh-controller: enrolled anchor +mesh-controller: enrolled anchor (the same second) +``` + +One `enrol` on the machine, two enrolments in the control plane. Each mints the node a fresh bus +password and returns it; the machine keeps the answer to the first, and the mesh keeps the hash of +the second. The machine then reconnects for ever as a user whose password the mesh rotated out from +under it — *authentication error - User "node.anchor"* on the bus, `Authorization Violation` in the +host's log, and a node that never reports. + +What is ruled out: the host asking twice — it asks again only when the mesh says *try again*, and +a refused attempt is not logged as an enrolment. Redelivery by the consumer — there is one +consumer, its acknowledgement window is thirty seconds, and the handler is quick. + +What is left: the client re-publishing when an acknowledgement is slow, which is what its defaults +do. That was addressed by giving the publish a message id derived from its own bytes, so the stream +discards the copy — **and the duplicate survived it**, so either the id is not reaching the stream +or the second copy is not a copy. This is where the trail stops. + +Worth saying plainly: **the mint is the fragile part, not the delivery.** An enrolment answered +twice is survivable if the answer is the same both times, and it cannot be — the mesh keeps only +the hash, so a second answer is necessarily a different credential. Whatever closes this either +makes the enrolment arrive once, or stops the second arrival from rotating anything. + ## Where it belongs `mesh-host` (the bundle and the enrolment path) and `mesh-controller` (the certificate command, and