Commit Graph
4 Commits
Author SHA1 Message Date
jschoubben 27c4b765b2 Refuse a declaration for the other mode, or older than the mesh's last, and say what an apply would change first
An operator ran `mesh-host reconcile` on an adopted control-node with twelve
modules assigned. It applied the bundle the host carries — the genesis
declaration, foundation only, converged: recreated the store, failed on the
broker's held port, wrote the converged base filter and started its service,
and stopped at the first failing action. The filter closed the machine for
forty-five minutes. The host reported the node adopted in every report, the
declaration said converged, and nothing compared the two; nothing was printed
before acting (hq issue 104).

The host now records the node's mode — from every declaration the mesh sends,
and at genesis from what the operator said — and refuses, at the point of
application, a declaration that says the other mode, naming both and the act
that changes it. Only a declaration the link delivers, signed, changes the
mode: that is how `converge` and `adopt` arrive, so the flip still works and
nothing else can do it. Genesis marks the bundle consumed, with the digest of
what it applied, so `reconcile` holds a node the mesh has spoken to against
what the mesh last said and never the bundle, and refuses the carried bytes
when they are not what genesis applied. A file is refused when it is not what
the mesh last said: a declaration carries no sequence and no issued-at, so the
host cannot tell older from newer, and says so. Both commands print what they
would change — a hold, a removal, an action named as one — before touching
anything, and --dry-run is that list and nothing more.
2026-09-23 23:15:28 +02:00
jschoubben 5e3dd3f59c Raise a machine in use adopted: keep its firewall, load no dropping table, guard the mesh's own ports, and take only the mesh's own modules (hq ADR 0100) 2026-09-22 17:32:44 +02:00
jschoubben 121367319d Rename mesh-control -> mesh-controller, substrate -> foundation
One name per thing, per the HQ glossary: the module/container/image/binary/repo
becomes mesh-controller, the seat the-controller, and the store+broker pair the
foundation (embedded base bundles, default template and example lock renamed with
their go:embed directives). No behaviour change — a pure vocabulary rename.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
2026-09-16 18:40:40 +02:00
jschoubben f534cf8b42 bootstrap: the rest of the pivot — enrol, registry, publish, reinstall, retire
Steps 6 to 10, which turn a substrate into a mesh that can maintain itself
(novox/hq ADR 0067).

 6 enrol      a node record, a token, `mesh-host enrol`, and the host agent
              running. Proved by the mesh having HEARD from the node, not by a
              process existing: a host that cannot reach the broker looks exactly
              like a successful install until the first push applies nothing.
 7 registry   the module that gives this mesh an image store, registered from a
              --catalog checkout, assigned and pushed. Its image is upstream and
              never built (04-ISSUES/029) — a placeholder digest there is refused.
              Verified by asking `/v2/`, because a container that is up is not a
              registry that serves.
 8 publish    the carried image pushed into that registry, which assigns it the
              first manifest digest it has ever had. This is the hinge: without
              it the mesh works and can never upgrade itself.
 9 control    the control plane registered as an ordinary module pinned to that
              digest, with the substrate's own store connections delivered
              through `secret accept` — read out of the bundle that made them,
              because the mesh cannot invent a credential that predates it.
10 retire     the temporary control plane dropped from the bundle and removed by
              the host's ordinary removal pass.

Every step asks before it acts and reports "already done". No step leaves the
machine without a control plane: steps 9 and 10 overlap deliberately, and two
stateless control planes are untidy rather than broken.

mesh-control's `internal/builder`.PublishImage is mirrored rather than imported —
tier 0 depends on nothing that must be installed first — with one correction: the
digest is chosen from RepoDigests by repository instead of taken as element zero,
so an image pushed to two registries cannot silently pin this mesh to the wrong
one.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
2026-09-10 23:59:57 +02:00