Delivery Guarantees
trueseal-sync guarantees that every blob sent reaches every current group member. Eventually, unconditionally. This isn’t best-effort. It’s the contract.
This page covers how that guarantee is actually built, and where the limits are.
The two-sided mechanism
Guaranteed delivery comes from two independent mechanisms working in tandem:
Sender side: the Outbox. Every blob is written to the local Operation Log before it’s pushed to the relay. It’s marked undelivered until the relay confirms receipt. If the sender drops offline before the push succeeds, the blob stays in the Outbox. On reconnect, the session replays every undelivered entry to the relay in global sequence order. The sender never loses a blob — it stays locally until delivery is confirmed.
Relay side: deferred delivery. When the relay receives a blob addressed to a recipient that’s currently offline, it stores it in that recipient’s Inbox. When the recipient reconnects, the relay flushes the Inbox immediately and deletes each blob on confirmed delivery. The relay holds blobs for offline recipients so the sender doesn’t have to wait around.
Combined: the sender keeps trying until the relay confirms. The relay holds the blob until the recipient collects it. Between them, nothing gets dropped.
What “eventually” actually means
“Eventually” has one boundary, and it’s the relay’s TTL. Blobs held in the relay’s Inbox past the TTL get reaped, delivered or not. A device that’s been offline longer than the TTL will miss those blobs — they won’t be on the relay when it comes back.
The sender’s Outbox isn’t subject to TTL. Undelivered entries stay in the local Operation Log indefinitely. If a sender has been offline for months and reconnects, the Outbox gets replayed in full. But the relay will only accept and deliver those blobs to recipients who are online now or who reconnect within their own TTL window.
So the practical edge case: if both sender and recipient are offline longer than the relay TTL, delivery isn’t guaranteed. Within the TTL, it is.
Order of delivery
Blobs arrive at on_message in arrival order — whatever order the relay hands them to the recipient’s active Receive Session. That can be different from send order if the sender was offline and pushed a batch of Outbox entries on reconnect.
Causal ordering survives through parent hashes. Each Envelope points at the hash of its predecessor, so a recipient can tell whether a blob is causally downstream of one they haven’t seen yet, regardless of the arrival order.
trueseal-sync doesn’t buffer or reorder Envelopes on the recipient side. What arrives is what your callback gets. If you need strict causal ordering, use the parent hashes.
Fan-out delivery
When a device calls send(), trueseal-sync builds one Envelope per current group member and pushes all of them over a single Push Session. Each Envelope is independently addressed and encrypted. The relay routes each one to the right Inbox.
Delivery to each recipient is tracked independently. A blob isn’t really “delivered” until every current member has confirmed receipt. The Outbox tracks delivery per (object_id, sequence) entry — not per recipient. In v0, an entry is marked delivered when the relay confirms the push succeeded, which means all N Envelopes for that send were accepted by the relay.
What delivery doesn’t cover
Newly added members. A device that joins the group after a blob was sent will not receive that blob. The relay doesn’t go back and retroactively route old blobs to new recipients. If you want new members to receive history, send it explicitly after onMemberJoined fires.
Removed members. A device removed from the group won’t receive blobs sent after the manifest update that excludes it. It may still receive blobs that were in-flight at the time of removal — already addressed to its key and sitting in the relay’s Inbox.
Relay TTL expiry. As above: blobs held past the relay TTL are reaped. This is the only scenario where a blob can be permanently lost without the sender knowing about it.