Each send is numbered, inside the signed bytes

novox/hq 04-ISSUES/107. The controller already held a per-node lock while
it composed and recorded each send; the order existed and was thrown away
at the wire. Each send now takes the next number for its node, one
higher than the last, under that hold and before the body exists — so
the number is inside what the mesh signs, and a replayed older
declaration cannot borrow a newer one's.

Zero is not sent. A host reads absence as "no order claimed", which is
the shape of every declaration before this, so nothing that worked
before changes for a machine sent nothing since numbering existed.

One subtlety, and it is the one that would have read every machine as
behind for ever: the mesh decides a machine is behind by comparing the
digest of what it WOULD send against what it DID send, and a number
changes the bytes. The read-only comparison composes with the number the
machine was LAST sent, not a fresh one, so it is byte for byte what was
sent when nothing else changed.

Hosts went first and every machine runs one that understands the field.
This commit is contained in:
2026-09-30 14:09:12 +02:00
parent 1bc099a2db
commit 9a5584b1b6
5 changed files with 158 additions and 0 deletions
@@ -0,0 +1,11 @@
-- The order of what a machine was sent, so a host can tell an older declaration from a newer.
--
-- novox/hq 04-ISSUES/107. A declaration's only identity was the digest of its bytes. The host could
-- say "this is not the last one" and could not say "this is older", so a backlog drained out of
-- order applied a declaration the mesh had already superseded. The controller already holds a
-- per-node lock while it composes and records each send — the order existed and was thrown away at
-- the wire.
--
-- One counter per node, taken under that hold, one higher per send. Null is a machine sent nothing
-- since this existed, which is not the same as a machine sent nothing.
alter table node add column sequence bigint;