文档暂以英文提供 · docs are in English for now

DOCS / network & radio

Protocol updates: what changed on the wire

What travels between devices changes rarely and deliberately. This page lists only those changes — one entry per release that touched the wire, with the compatibility line that matters when your devices run different versions. Interface changes live in the log; this page is the protocol’s own memory.


v1.0.11–1.0.12 — the doorbell contract, and delta offers

  • Every ping expects a pong within fifteen seconds — a parked relay listener with an overdue pong is declared dead and re-parked; keepalive send-success no longer counts as liveness. On carrier networks the ping cadence is four minutes, inside what carrier NATs tolerate.
  • A mailbox is offered only the delta — the history is re-laid only on a route change, when a stated route displaces a guess, or daily on a guessed relay. Measured on the Amsterdam relay: 1270 puts/min → 62, 48 MB/min → 1.7. What counts as delivered did not change.
  • “I moved” (1.0.12): a device that changes relays announces where it listens to every peer in every shared space, in one frameless bundle, before its first cycle on the new relay. Route assumptions older than thirty days expire.
  • terminal-relay --status-listen serves the public, aggregate-only Relay Status API — the contract this site’s relay page was built against in August.
  • Compatibility: peers on 1.0.12+ state their relay on start; older peers resolve from guesses as they update (1.0.15 makes a guess-accepted copy show as accepted).

v1.0.2 — a sky is strokes, not a canvas

  • Shared drawings ship as events, not state (ADR-036): a sky is one moment in the chat, and every gesture is a small signed event pointing at it — points on a 128×128 grid, one byte each. Strokes commute: the picture is the union, the log is the merge, and replay order is identical on every replica. An erase removes only the author’s own strokes.
  • Instrument delivery is acknowledged, not assumed (from 1.0.1-rc.2): the USB stand acknowledges every applied frame by event id; a board treats a frame as delivered only on that acknowledgement, and a refused frame stays owed — an instrument’s chain can no longer grow a hole.
  • Compatibility: clients on earlier builds render a sky as the line “✦ a shared sky”; room marks travel as names with a glyph fallback — old and new clients agree on what they see.

v1.0.1-rc.1 — the Wi-Fi courier, and instrument epochs

  • A bearer is a courier, not a member (ADR-035): a provisioned board hears the node’s LAN announcement, recognises its space from the hint, dials over TLS and knocks with a signature bound to the node’s certificate. Readings travel up; key rotations and the clock (NTP) travel down. The transport carries — it never becomes a participant.
  • Instrument membership follows the epoch: an instrument is a member while it speaks under the current key epoch — its card appears with the first reading and leaves with the key, on every replica at once. Ghost identities a board minted and abandoned no longer persist.
  • Compatibility: no new frozen families — the courier is a transport under the existing envelope; USB remains the rescue road for boards that cannot reach the network.

v1.0.0-beta.2 — sweep formats join the freeze

  • Two new frozen .v1 families: field.track.v1 (the sweep trajectory — an ordered stream of samples where a gap is a sample, not a silence: point(dt, lat, lon, accuracy) or gap(dt, duration, reason) with no_fix / suspended / unknown, so a renderer cannot join across an absence it never consumed) and sweep.completed.v1 (the canonical completion fact: sector, start/end, distance, result, bbox, track asset reference).
  • The completion event is radio-sized by measurement: 348 bytes worst-case against the 500-byte LoRa frame. The fact of a finished sweep crosses radio immediately; the detailed track travels as an asset when broadband appears.
  • Observation evidence: an observation event carries a 32-byte media reference — the note stays radio-sized, the photo follows as ordinary media.
  • Compatibility: everything ADR-033 froze in beta.1 stays frozen; sweeps add families, they change nothing existing. (ADR-034)

v1.0.0-beta.1 — the formats are frozen

  • Everything that travels between devices or survives a restart is now a commitment: ninety signed schemas, the envelope, the on-disk layout, the backup container, the relay’s wire, the radio profile. A log written today is opened by every later 1.x.
  • What is not frozen is named just as plainly: the local loopback HTTP API, the interface, per-device projections, and anything refetchable (map tiles, link previews). The rule: what travels or persists is frozen; what a device decides for itself is free. (ADR-033)
  • New wire citizens since 0.1.7: object/work/field events (each field event fits a single LoRa frame — measured, test-pinned), public instrument frames with attested writers, and relay wake hints that carry no content.
  • Compatibility: “beta” marks the reach of evidence, not a reservation — the freeze is effective from this release.

v0.1.7 — instrument plane · idempotent send

  • Instrument readings travel on their own sealed plane, beside the conversation, never inside it. Sealed to the space; relays read neither. Key rotations reach instruments like devices.
  • Every send carries a deduplication reference. A retry — or a double-press — can never mint a second copy; the node deduplicates on the reference, so clients may retry freely.
  • Compatibility: readings ride in envelopes only 0.1.6+ carries. Older devices ignore the plane; conversations are unaffected.
  • Knock: a new envelope kind, sealed to a person’s mailbox — not to a room. The shared room never learns a knock happened. The answer (including a standing “don’t ask again”) travels the same road back.
  • Link previews are sender-fetched, sealed content. The sender’s node fetches a preview once, before sending; readers fetch nothing — no request ever leaves a reader’s device toward the link’s author, so a link cannot become a read receipt.
  • Compatibility: knocks reach only devices on 0.1.6+; older devices simply never see them.

v0.1.5 — media in the envelope · address announcements

  • Small media rides with the message into each recipient’s mailbox at send time; the sender’s device is not needed afterwards. Large files stream by sealed chunks from whoever holds them.
  • Every message quietly announces where the sending device can be reached; the newest statement wins. A device that moved relays becomes reachable the first time it speaks.
  • Pairing introduces a device into an existing identity rather than copying a snapshot; the person’s pre-certification contacts knowledge travels with pairing (closes the 0.1.2 empty-rooms case).
  • Compatibility: the device that holds bytes must be on 0.1.5+ for its answers to route; one older device in a pair keeps the old silence.

v0.1.2 — device certificates, enforced

  • Every device carries a certificate signed by the person’s root key, and every replica checks it before admitting a message.
  • Held, not dropped: a message arriving before its device’s certificate waits and is admitted the moment the proof arrives — on every transport, including ones that forget what they handed over.
  • The kernel rule this release added: a temporary admission failure must never be converted — by transport, deduplication, or caching — into permanent refusal.
  • Compatibility: spaces created before certification keep working without migrating a byte of history.

The current wire limit for a single message is 16 KiB (the interface asks for ~4000 characters — a page — long before that). The full protocol lives in the source; design records (ADRs) in the repository carry the reasoning behind each rule.