Commit Graph
407 Commits
Author SHA1 Message Date
jochen 0e57186bf1 Place the bus's users before the enrolment's wait begins
The installer placed them between making the enrolment's deadline and
using it, so a failure returned without cancelling it, and go vet refused
the package.
2026-10-08 01:40:47 +02:00
jschoubben e30d838395 A joining machine dials the bus once the hub has answered its tunnel
Issuing the token sends the hub its new peer, and the hub applies it on
its own time; a bus dialled before then timed out naming the bus. The
first tunnel now waits for a handshake with the hub, and says so in the
tunnel's words when there is none (novox/hq ADR 0169).
2026-10-08 01:33:30 +02:00
jschoubben 0863695012 The installer lets the first node onto the bus it raised
At genesis the bus's users reach it in no declaration, because the
machine running it has not enrolled. The installer, which raised the
bus from its bundle, places the control plane's composed list beside it
and makes it re-read it: before the machine enrols, for the token's
account, and after, for the node's own (novox/hq issue 146).
2026-10-08 01:33:30 +02:00
jschoubben c38f21bb39 A machine makes its tunnel key first and joins through the tunnel
nox-mesh-host key makes the tunnel key, or reads the one made, and
prints its public half for the token to be issued for. enrol with a
token that carries a tunnel takes that key, refuses another, writes
mesh0 with the hub as its one peer and starts it, then reaches the bus
over it (novox/hq ADR 0169). Tokens without a tunnel enrol as before.
2026-10-08 01:33:30 +02:00
mesh-admin fcca8d9ce8 Merge pull request 'Judge the machine's own networking beside what its modules run (hq ADR 0241)' (#51) from feat/machine-network-health into main 2026-10-07 18:16:08 +00:00
jochen f8ef2de91d Hold the network statement's field names on the engine's side (hq ADR 0241)
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery-group group feat/machine-network-health delivering: 0 of 2 delivered
mesh/delivery delivered
2026-10-07 18:53:21 +02:00
jochen babd32cfc7 Take a tick a little early as the network look's tick
The liveness loop's ticker drifts; a look skipped for a few milliseconds
would wait a whole further tick.
2026-10-07 18:52:16 +02:00
jochen 039abeff69 Drill the network judge in a throwaway machine (hq ADR 0241)
The judge's tests run against files and fakes; the drill runs it against a
real resolver file and real resolvers, rewritten as the VPN client does,
and records the statements the controller's replay raises and clears from.
2026-10-07 18:51:45 +02:00
jschoubben 429ea42357 Judge the machine's own networking beside what its modules run (hq ADR 0241)
A VPN client rewrote the laptop's resolver file and every mesh name failed
while each module read healthy: nothing asked the machine. The engine now
looks every 30 s at the resolver file the uplink holder declared (naming
the program that rewrote it), the names through each listed resolver
(NXDOMAIN for a mesh name's IPv6 address is a finding, issue 262), the
tunnel's handshake with the hub, the bus and the default route; a part is
unhealthy on its second failing look, and the statement carries it.
2026-10-07 18:43:39 +02:00
mesh-admin 56e2ebec4b Merge pull request 'Judge how a module says it is ready, beside whether it stays up (hq ADR 0240, to-be 48 Phase B)' (#50) from feat/health-the-field into main 2026-10-07 16:28:34 +00:00
jochen 96bf9415aa Ask the merge check for this pull request: opening it announced nothing to the build seat
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery-group group feat/health-the-field delivering: 1 of 3 delivered
mesh/delivery delivered
2026-10-07 16:17:40 +02:00
jochen bdd44154cc Judge how a module says it is ready, beside whether it stays up (hq ADR 0240, to-be 48 Phase B)
Liveness alone could not see a web application whose port was open and whose
program ran while every request hung for eleven hours (issue 145). A resource
now carries the `health` its module declared: the engine makes http and tcp
looks itself from the machine to the endpoint's published port, reads a unit's
readiness from the show it already makes, hands an exec command or the image's
own check to the runtime as the container's check with the declared timing and
reads its state from the inspect it already makes, and asks a module's tool on
its own node tools. Starting until the check passed, unhealthy once its looks
after the grace fail the declared number of times; never more looks than the
measured budget; nothing restarted. The statement says contract 2, which tells
the controller this engine may be sent the field.
2026-10-07 14:08:32 +02:00
mesh-admin 41f908b803 Merge pull request 'Let a planned maintenance window fail no apply (hq issue 291)' (#49) from fix/a-planned-window-fails-no-apply into main 2026-10-07 11:20:20 +00:00
jochen 3c1ac6aef2 Let a planned maintenance window fail no apply (hq issue 291)
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
At 03:30 the store's collector held the registry still while the
node-engine's reconcile on that machine was fetching bundle blobs from
it: every archive failed 'connection refused' and the machine was held
until the next pass. Other machines can meet the same window.

A scheduled step now opens its window only once no apply is in flight
here (the apply lock is taken just to write the record, so a push still
never queues behind the window). An apply whose fetch the store does
not answer waits for a window open on its own machine to close, and
elsewhere retries with backoff within one bounded budget per apply,
well past the window's length; an answer such as 404 still fails at
once.
2026-10-07 13:11:03 +02:00
mesh-admin 038eff5ca0 Merge pull request 'Keep a replaced build reachable, and delete it only once no process runs from it (hq issue 289)' (#48) from fix/a-verb-survives-the-handover into main 2026-10-07 00:55:23 +00:00
jochen 3a117c2d2b Keep a replaced build reachable, and delete it only once no process runs from it (hq issue 289)
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
The witness moved a running controller's build into a 0700 directory and deleted it
on proof, while the old process could still be serving. Its directories are now
0711, and a build without a reader is retired and swept once /proc shows nothing
runs from it.
2026-10-07 02:45:08 +02:00
mesh-admin 03031a46dd Merge pull request 'Judge whether what a module runs stays up, and say it (hq ADR 0240, to-be 48 Phase A)' (#47) from feat/a-module-says-how-it-is-healthy into main 2026-10-07 00:39:39 +00:00
jochen 1fc1e74cc3 Judge whether what a module runs stays up, and say it (hq ADR 0240, to-be 48 Phase A)
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group feat/a-module-says-how-it-is-healthy delivered: every member is delivered
A container that crash-looped after its compose applied passed every check the
gate had: nothing looked at what a module runs. The node-engine now judges every
long-running resource on every look — one read of the runtime, one per service
manager — keeps the restarts it counts across recreates and its own restarts,
and says the state in every report and as an event on change, again every minute
while not healthy. It reads only; nothing is restarted for being unhealthy.
2026-10-07 02:28:15 +02:00
mesh-admin a338c2e581 Merge pull request 'Lay out the publishing test as every gofmt agrees (hq issue 286)' (#46) from fix/gofmt-as-the-toolchain into main 2026-10-07 00:27:48 +00:00
jochen bd30534ab1 Check again, judged by the controller with the gate's fix (novox/hq issue 285)
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
2026-10-07 02:06:51 +02:00
jochen 2a4b521e1b Cite the hq issues by the numbers they were given: 285, 286, 287
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (0 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
2026-10-07 02:00:13 +02:00
jochen ed43d65bf3 Lay out the publishing test's return as every gofmt agrees, so the build seat's check passes
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (0 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
The toolchain the build seat runs merge-check.sh in (Go 1.26) and a newer local Go format a return of
several multi-line composite literals differently; the seat's is the one that judges, and it failed every
pull request on this file (novox/hq issue 283).
2026-10-07 01:29:06 +02:00
mesh-admin 971881d58d Merge pull request 'Let the controller ask the delivery's owner stalled and close (hq ADR 0239)' (#45) from feat/mesh-delivery-waits-said into main 2026-10-06 22:30:57 +00:00
jochen b196cabd8f Let the controller ask the delivery's owner stalled and close (hq ADR 0239)
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (0 of 4 compose)
mesh/repo-check fail: its merge-check.sh failed: internal/bootstrap/publish_test.go
mesh/delivery delivered
mesh/delivery-group group feat/mesh-delivery-waits-said delivered: every member is delivered
The controller's self-check reads mesh-delivery's stalled and healer H2 calls
its close; a controller raised from genesis must be granted both.
2026-10-07 00:14:19 +02:00
mesh-admin 880e7461f9 Merge pull request 'Carry plan-moved in the installer's first user list (hq ADR 0239)' (#44) from feat/mesh-delivery into main 2026-10-06 22:07:19 +00:00
jochen 94e49c6b2d Carry plan-moved in the installer's first user list (hq ADR 0239)
mesh/merge-gate pass: every machine composes with the change as it did without (0 of 4 compose)
mesh/delivery delivered
mesh/delivery-group group feat/mesh-delivery delivered: every member is delivered
The controller says every walk it keeps as plan-moved; a controller raised
from genesis must be allowed to say it from its first start.
2026-10-06 23:59:19 +02:00
mesh-admin ad812a5888 Merge pull request 'Leave the gate to the build seat; merge-check.sh checks the node-engine's own code (hq ADR 0238)' (#43) from feat/the-graph-decides-what-is-checked into main
mesh/delivery delivered
2026-10-06 21:00:35 +00:00
jochen f823ade868 Leave the gate to the build seat; check the node-engine's own code here (hq ADR 0237)
The build seat now runs the gate itself, judging a node-engine change with the change's
validator in the running controller because the module graph builds mesh-host from here.
This script is the repository's own layer (mesh/repo-check): format, vet, and the suite
under the race detector when the toolchain can.
2026-10-06 21:51:49 +02:00
mesh-admin f39e282fed Merge pull request 'Phase 5: check the node-engine's changes against every machine before they merge (hq ADR 0237)' (#42) from feat/merge-gate into main
mesh/delivery delivered
2026-10-06 19:19:20 +00:00
jochen 2fb7c91eaf Check the node-engine's changes against every machine before they merge (hq ADR 0237)
merge-check.sh runs the suite, then builds the controller the mesh runs with this change's
validator in place of the one it vendors and runs the merge gate: a change to the node-engine
that would refuse what the mesh sends today fails its pull request, naming the machine. The
installer's first user list lets the controller say a check's verdict and hear a pull request's
head, as the controller now composes it.
2026-10-06 21:16:33 +02:00
mesh-admin 7a6f9218a0 Merge pull request 'Core upgrades that roll back: the host side (hq to-be 45 Phase 4, ADR 0227 rule 8)' (#40) from feat/core-upgrades-roll-back into main
mesh/delivery delivered
2026-10-06 18:00:07 +00:00
mesh-admin ad39988bc6 Merge pull request 'Genesis grants for the gate's event and the bus step's snapshot (hq ADR 0236)' (#41) from feat/core-upgrades-that-roll-back into main
mesh/delivery delivered
2026-10-06 17:15:07 +00:00
jochen 7b450ab371 Carry the controller's grants for the gate's event and the bus step's snapshot (hq ADR 0236)
The controller says a rollback as rolled-back and asks the bus machine's backup holder
for a snapshot before the planned bus step; the installer's first user list must grant
both, or a fresh mesh's controller is refused the first time it uses them.
2026-10-06 18:34:41 +02:00
jochen 0c405b70cc Roll a core build back by a witness that is not the new build (hq to-be 45 Phase 4)
The launcher trusted a counter only a by-hand reconcile ever cleared and a
known-good nothing in the daemon wrote, so no machine could roll its host back;
the controller and the node tools were replaced in place with nothing kept.

- The launcher runs a delivered host that is not known-good on trial: one that
  crashes, stops for nothing, or does not report within ten minutes goes back
  to known-good, once per version, recorded in rolled-back. The host proves
  itself when the mesh takes a report under its own build, says every standing
  verdict on its reports, never stands aside for a rolled-back version, and
  restarts its service once when its launcher was replaced on disk.
- The engine keeps the controller's and the node tools' previous build beside
  the new one and judges the new one: the lease taken by the controller it
  started (read-only direct get of mesh-controller_lease/holder), or this
  machine's runtime answering $SRV.PING.node-tools.<node>, within sixty seconds
  of time it could ask. Not healthy: the previous restored, once, said. Proved:
  the previous deleted. A build declared not-reversible is never rolled back.
- Retire never removes a version newer than the running one.
2026-10-06 18:23:56 +02:00
mesh-admin 8d853791b2 Merge pull request 'Genesis grant for D13; a kept directory is never 'removed by hand' (hq ADR 0233)' (#39) from feat/a-module-declares-the-data-it-holds into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
2026-10-06 15:00:52 +00:00
jochen 7e9ae9f07e Carry the controller's new self-check grant; stop telling people to delete kept data (hq ADR 0233)
The installer's first user list must match the controller's composed grant, which now reads every
machine's backup holder; and a kept directory's report pointed at the one act that loses data.
2026-10-06 16:47:49 +02:00
mesh-admin 2e884438f9 Merge pull request 'Genesis assigns mesh-wireguard, not the retired networking bundle (hq ADR 0226)' (#31) from feat/genesis-assigns-the-private-network into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
2026-10-06 13:04:28 +00:00
jochen 98885e953e Genesis assigns mesh-wireguard, not the retired networking bundle (hq ADR 0226)
A controller that no longer ships networking refuses it, which would stop genesis where the hub
joins the private network.
2026-10-06 14:59:26 +02:00
mesh-admin f274b6effe Merge pull request 'Genesis lock: let the controller hear provisioner.retirement (hq ADR 0230)' (#38) from feat/retired-consumers into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
2026-10-06 12:46:32 +00:00
jochen 240b903a04 Let the genesis controller hear what providers retire (hq ADR 0230)
The controller now derives a subscription to provisioner.retirement; the first
user list the installer carries must match it, or the genesis controller is
refused the subject its composition expects.
2026-10-06 14:45:56 +02:00
mesh-admin 280d3b2e1e Merge pull request 'Say again what was last applied when the mesh asks (hq to-be 45 Phase 3, the report verb)' (#37) from feat/a-core-that-cannot-fail-silently-phase-3 into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
2026-10-06 12:29:14 +00:00
jochen 6e1bcdbde4 Say again what was last applied when the mesh asks (hq to-be 45 Phase 3, the report verb)
The controller's healer H1 answers a send that went unreported by asking the
machine first: a report lost on its way (issue 264) needs no second send. The
node-engine now hears mesh.node.<self>.ask.report on core NATS and enqueues a
reconcile whose account is said whether or not it is news; a delivery waiting
meanwhile is applied and reported instead. The answer is an ordinary report on
its own subject, so the node publishes nothing new and answers nobody's inbox.

The genesis lock grants the controller the healer-acted seat event, which it
now composes; the genesis test in mesh-controller holds the two equal.
2026-10-06 14:05:02 +02:00
mesh-admin b2808549ee Merge pull request 'Grant the genesis controller its lease and secret-replaced, not mesh.control.> (hq to-be 45 Phase 2)' (#36) from feat/a-core-that-cannot-fail-silently-phase-2-grants into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
2026-10-06 10:30:28 +00:00
jochen bbe74f3fc2 Grant the genesis controller its lease and the secret-replaced event, and not what the machines say (hq to-be 45 Phase 2)
The controller now composes a publish grant for its lease bucket
($KV.mesh-controller_lease.>), which it must write before it acts, and for
the seat event secret-replaced (hq ADR 0228, mesh-controller #82); and it no
longer publishes mesh.control.>: a machine's report has one writer, its
node-engine, and the writers table refuses a second at composition. The
installer's first user list must say what the controller derives, or a new
mesh's first controller is refused its lease and serves without one.
2026-10-06 12:25:12 +02:00
mesh-admin 3e80b7ae32 Merge pull request 'Apply through one queue, and order what is applied and reported (hq to-be 45 Phase 2)' (#35) from feat/a-core-that-cannot-fail-silently-phase-2 into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
2026-10-06 09:55:19 +00:00
jochen 31804bd8c2 Apply through one queue, and order what is applied and reported (hq to-be 45 Phase 2)
A delivery and the five-minute reconcile were two paths that applied, ordered only by a lock, and
each order it allowed was met live (issues 257, 261, 267). Now both only enqueue: one worker takes
the newest declaration held when it starts, applies it once and makes one report, and reports leave
in the order they are made.

A declaration may carry the controller's lease epoch beside its sequence; one older than what this
node applied is refused before anything is touched, counted, logged and reported. A report carries
the declaration's epoch and sequence and the host's own report sequence, kept on disk so it goes on
increasing across restarts and self-updates. Without an epoch, today's behaviour stands.
2026-10-06 11:54:10 +02:00
mesh-admin d7d93f57c5 Merge pull request 'Grant the genesis controller the self-check's ban-list question (hq to-be 45 Phase 1, D8)' (#34) from fix/phase-1-d8-grant-and-d10-version into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
2026-10-06 08:45:16 +00:00
jochen b9774ea426 Grant the genesis controller the self-check's ban-list question (hq to-be 45 Phase 1, D8)
The controller now composes a publish grant for
mesh.seat.node-intrusion-prevention.tool.banned.*, which D8 asks every
machine; the installer's first user list must say what the controller
derives, or a new mesh's first self-check is refused it.
2026-10-06 10:44:39 +02:00
mesh-admin 1545b00a87 Merge pull request 'Say the heartbeat's interval, export the host's validator, grant the genesis controller Phase 1 (hq to-be 45)' (#33) from feat/a-core-that-cannot-fail-silently-phase-1 into main
mesh/delivery held for a person: merged without a passing check: only a person decides that it goes on
2026-10-06 08:24:39 +00:00
jochen 6953b5bafd Say the heartbeat's interval, export the host's validator, grant the genesis controller Phase 1 (hq to-be 45)
The controller's watchdog of a machine's heartbeat (S1) is bound to three
of its intervals, and a bound the controller guessed would not move when
the interval does: the heartbeat now carries interval_seconds.

Its self-check (D1) must judge every composed declaration as the host
does, and a second validator written from the host's rules would drift
from them: the host's own parsing is exported, unchanged, as
github.com/novox/mesh-host/validate.

The installer's first user list grants what the controller now composes
for itself: its condition buckets, the condition and doctor-heartbeat
events, the bus's two consumer advisories and $SRV.INFO — or the first
controller would be refused them until the broker's machine is pushed.
2026-10-06 10:18:54 +02:00