Skip to content

spec: fix logical inconsistencies, align with fmsgd behaviour (v0.5.0) - #29

Open
markmnl wants to merge 9 commits into
mainfrom
spec/consistency-fixes
Open

spec: fix logical inconsistencies, align with fmsgd behaviour (v0.5.0)#29
markmnl wants to merge 9 commits into
mainfrom
spec/consistency-fixes

Conversation

@markmnl

@markmnl markmnl commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Analysis of SPECIFICATION.md v0.4.1 found several logical inconsistencies; fmsgd was then audited to see why integration tests pass regardless, and the spec is updated to encode the working behaviour (per discussion). SPEC.md is re-distilled to match; a companion PR syncs it into fmsgd.

Major fixes

  1. Verifying Message Stored excluded messages the host sent. The definition required a prior accept response (200/11), which a host never gives for messages it originated — a literal reading rejects every reply arriving at the originator's host with code 6, and makes the v0.4.0 add-to notification to the original sender's domain impossible. fmsgd already treats sent messages as stored (bare SELECT id FROM msg WHERE sha256 = $1 in store.go, hash populated by ensureSharedHash before first delivery; guarded by integration test 007-reply-to-own-sent.sh). The definition now includes messages the host sent.

  2. Code 11 semantics. The code table, §Reject-or-Accept and the Sending step read "the additional recipients have been accepted" — a state no execution path produces: when any add-to recipient belongs to the receiving host it responds 65, and 11 only when none do. All three places now describe code 11 as acknowledging/recording an add-to batch by a domain hosting none of the added recipients (fmsgd: resolvePostChallengeCode, handleAddToPath).

  3. Single header-response code. §3's steps could literally emit a REJECT 10 or a 64 after a 65 had been sent — bytes the sender state machine would mis-parse as per-recipient codes. §3 step 1 now states exactly one code is determined and sent, first matching rule wins (matching fmsgd's collapse in resolvePostChallengeCode).

  4. add to / to overlap forbidden. NOTE II allowed an address in both lists, which created an unresolvable ambiguity: Terms defines "recipients" as a set (one per-recipient code) while §3 iterates occurrences (two codes) — desyncing the response stream if hosts disagree. fmsgd already rejects the overlap with code 1 (readAddToRecipients). Validation now requires add-to addresses to be distinct from to; NOTE II explains re-serving a recipient who lost the message via plain re-send.

  5. Add-to "exact duplicate except…" list omitted topic. An add-to copy of a thread-starting message gains a pid, and topic is mutually exclusive with pid — so a conforming "exact duplicate" was structurally invalid. The exception list now includes the has-pid flag and topic omission (matching fmsgd's addToHeader).

Minor fixes

  • MUST vs SHOULD conflict on creating the outgoing-message record before transmission → MUST in both places.
  • Unsupported first byte: split by who listens on the other end (49585f7) — value ≤ 128 (unsupported message version) gets REJECT 2, since the sender's first read is always a response code; value > 128 (unsupported CHALLENGE version) TERMINATES without responding, since the challenger's next read is exactly the 32-byte CHALLENGE-RESPONSE hash and a code byte would be indistinguishable from hash bytes. fmsgd is brought in line by Terminate on unsupported challenge version instead of sending code 2 fmsgd#40.
  • Code 10 description covers the add-to batch-duplicate use; §3 wording "none of the recipients" → "none of the add to recipients".
  • "message hash" consistently defined via Computing Message Hash (Terms, Challenge Response).
  • Numbering: Sending steps renumbered 1–10 (started at 2), Handling a Challenge 1–5 (skipped 4), 1.4.6.3.2 → 1.4.6.3.3 cross-ref; TOC gains "Notes on Adding Recipients" and "Computing Message Hash".

Bumped to v0.5.0 since the overlap prohibition is a behavioural change.

🤖 Generated with Claude Code

- Verifying Message Stored also covers messages the host itself sent;
  previously a literal reading rejected every reply to the originator's
  host with code 6 (fmsgd already behaves this way: bare hash lookup in
  msg table, guarded by integration test 007-reply-to-own-sent).
- Exactly one header-response code is sent, evaluated in precedence
  order (batch duplicate -> 10, add-to recipients here -> 65, add-to
  none here -> 11, all-recipient duplicate -> 10, else 64); the old
  step wording could emit contradictory sequences after a 65.
- Code 11 rewritten: it acknowledges an add-to batch by a host with no
  add-to recipients; the "additional recipients have been accepted"
  wording described a state no path produces (65 covers that case).
- add to addresses MUST NOT overlap to (matches fmsgd's reject), which
  also removes the per-recipient code-count ambiguity NOTE II created.
- Add-to copies: exception list now includes has-pid flag and topic
  omission (topic is mutually exclusive with pid).
- Unified unsupported-first-byte handling to REJECT 2 + close in both
  dispatch sections (matches fmsgd readVersionOrChallenge).
- Outgoing-record creation is MUST in both places it is described.
- message hash consistently defined via Computing Message Hash.
- Numbering fixes: Sending steps 1-10, Handling a Challenge 1-5,
  1.4.6.3.3 cross-ref; TOC gains Notes on Adding Recipients and
  Computing Message Hash.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
markmnl and others added 3 commits August 11, 2026 07:04
…h hash

Added recipients participate in (and reply to) the add-to batch message
only, not the original; batches form sibling branches under the original
so the thread evolves as a tree; batch identity is the batch message
hash (covering time), so re-issuing the same addresses at a new time is
a distinct batch, not a duplicate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Generalise Verifying Message Stored NOTE I beyond code 11: an add-to
message's data never crosses the wire when the receiving host already
holds the original (codes 11 and 65), and its sender already holds it,
so every host holding a batch MUST be able to reconstruct the batch
message (header as transmitted + original's data) to verify replies
referencing the batch by its hash. The 65 path now carries the same
record-the-batch-fields obligation the 11 path had, and 'sent by the
host' explicitly includes the host's own add-to batches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ders

A sending host's first read on Connection 1 is always a response code,
so REJECT 2 is unambiguous for an unsupported message version. A
challenger's next read is exactly the 32-byte CHALLENGE-RESPONSE hash,
so a code byte written into that stream is indistinguishable from the
start of a hash - the listener MUST TERMINATE without responding for an
unsupported challenge version (first byte > 128).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
markmnl and others added 5 commits August 11, 2026 09:56
Since add to from is always in from or to, the only possible
notification-only domain is from's - it arises exactly when a
recipient, not the original sender, adds recipients. State this beside
code 11 so readers need not derive it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Code 11 in one breath: the host already holds the rest of the message,
so there is no need to send it again, and it hosts no add-to recipient,
so the exchange completes. Mechanics stay in the protocol steps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An add-to batch is a full message; a recorded batch matching by hash is
just the message having been received. The code table states the
meaning; the distinct checks (batch hash at header time, challenge-hash
all-recipient dedup) stay in the protocol steps. The parenthetical
preserves the restore nuance: a host holding the message for only some
of its recipients continues rather than rejecting 10.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant