Ballot TrailBorn Between 2 Generals

Section 6 · Section 8 · Section 9

The event ledger

Append-only, per-token chained, signed on every write. Nothing below is a recording — the engine is running in this page, and the keys were generated when you loaded it.

Generating an Ed25519 signing key…

What each event carries

Every record is sealed the same way. The hash covers the whole canonical payload including the previous hash for that token, which is what makes a later edit detectable rather than merely discouraged.

// the preimage, in MBLTS-CANONICAL-V1: sorted keys, no whitespace,
// no undefined, timestamps as strings so float formatting never enters a hash
event_hash = SHA-256( canonicalJSON({ …event fields…, previous_event_hash }) )
signature  = Ed25519( event_signing_key, event_hash )

The signature covers the hash rather than the payload directly, so an auditor holding archived public keys can verify a decade-old event without needing the serialization rules to still be in living memory — they only need the hash to recompute, which the canonical form guarantees.

The twelve-step write

Section 6.3 of the specification is an ordered algorithm, and the engine keeps the step numbers in the code so the two can be read side by side. In order: authenticate the caller, validate the schema and idempotency key, resolve the token inside the trusted boundary by digest, reject unknown or terminal tokens, read the current state and validate the transition, authorise the role and any dual-control requirement, canonicalise, chain, sign, persist atomically, queue for anchoring, and alert.

A refusal is evidence. When any of those steps fails, the write does not simply return an error — the ledger appends a signed EVENT_REJECTED or DUPLICATE_OR_REPLAY_DETECTED record. A system that logs only its successes cannot show you an attack.

Idempotency, and why it is not just a retry convenience

A scanner on a bad network sends the same receipt twice. Without idempotency you get two RECEIVED events and a reconciliation that no longer balances. With it, the second call returns the first result and writes nothing. But the same key presented with a different payload is a 409 IDEMPOTENCY_CONFLICT — because that is no longer a retry, it is a rewrite wearing a retry's clothes.

Paper remains authoritativeThe token never touches a voteAppend, never overwrite