Together · message transport · technical page · July 12, 2026 · for people who build and break software

Three questions for every road.

The message transport is an interface (SHARING-SPEC §3): it moves a signed, sealed envelope from one archive's outbox to another's inbox. The interface covers nothing else. This page compares five transport options — one built, four researched and judged — against the same three-question test. Companion doc: COURIER-CONCEPT-v0.1.md. Existing code and specification filenames retain the earlier courier name until the software is migrated. The plain-words version is for everyone else.

The three-question test

Every candidate below is asked the same three questions, in the same order. These three are the entire evaluation:

  1. Does it move bytes reliably between two named people? The test is a PROPOSE→ACCEPT→CONFIRM exchange carried end to end. "Can data flow through it somehow" is the weaker question, and this catalog does not ask it.
  2. What does the operator running that road see, and is that operator already trusted by the circle? The shared-folder transport's operator is whoever runs the folder (Kurt's gitea, a family Syncthing) — someone the circle already trusts. By the uniform-distrust rule, a messaging carrier or a platform's API stays untrusted (COURIER-SMS-SPEC-v0.1.md §2).
  3. What sealing rung does that answer force, per I7? An untrusted operator forces sealing: "e2e" before anything is handed to that road. A well-known platform gets no exception.

Nothing about a candidate's popularity, feature richness, or engineering elegance enters the evaluation. A road either answers these three questions in a way that lets it carry the envelope, or it doesn't.

The five candidates

adopted the properties, skipped the software

Signal Protocol (X3DH + Double Ratchet)

Q1 — moves bytes? Yes, and extremely well: forward secrecy, post-compromise security, a relay that sees ciphertext + routing metadata only.

Q2 — operator trust? N/A as evaluated here. The question this catalog actually answers is whether to run Signal's infrastructure (libsignal, our own X3DH/ratchet state machine, account provisioning per contact) versus borrowing its properties. SHARING-SPEC §3 already answered this: "its software is not the build... a heavy dependency for a star-topology circle of 10."

Q3 — sealing forced? The rail already gets the properties that matter (an untrusted relay sees only ciphertext) via age/X25519 sealing on top of shared-folder or text-message transport. The age/X25519 rung lacks X3DH's specific forward-secrecy guarantee, which we judge to protect against a threat model (future device compromise unwinding today's messages) that a 10-person, voice-verified circle does not currently need. If that judgment changes for a specific circle, real libsignal is the correct upgrade. A home-grown ratchet is never the answer.

Status: FUTURE, researched only. The design does not reach build-readiness.

built — see COURIER-SMS-SPEC-v0.1.md

SMS / iMessage / RCS (text-message transport)

Q1 — moves bytes? Yes: KSP1 framing, base64url chunks, bounded/TTL'd reassembly (pna_text_courier.py).

Q2 — operator trust? No: uniform distrust of every messaging operator, forced in code (configure_text_courier() hardcodes trusted: false; a hand-edited override is re-refused at every use).

Q3 — sealing forced? Yes: frame_for_text() raises TextCourierError on anything not sealing: "e2e". No exception path exists.

Status: BUILT — 25/25 tests green at its July 12, 2026 build, the full pre-existing Personal Neutral Archive (PNA) suite unaffected; current whole-suite counts live on the build log. Not yet wired to a real OS Messages bridge; no live age round-trip in this build environment (no binary present). Full detail on the text-message transport page.

a derived-output target

Google Calendar (Calendar API v3)

Q1 — moves bytes? Technically yes: an opaque blob could ride in an event's description field, or a custom extendedProperties.private value (visible only to the inserting application, per Google's docs). The API also natively supports attendees[].responseStatus (needsAction/accepted/declined/tentative), a real propose/accept/decline verb set already built into the platform.

Q2 — operator trust? No, and this is the disqualifying answer. Q1 is not what rules it out. Google Calendar's freebusy.query and native invite flow exist to broadcast availability — the platform's entire value proposition is knowing your schedule. Routing PROPOSE/ACCEPT through it, even sealed, would still leak that a negotiation with this specific contact is happening on this specific day to an operator whose business model is schedule intelligence — the same social-graph/rhythm leakage the text-message transport spec already names as an accepted, bounded cost for SMS (COURIER-SMS-SPEC §3); accepting it a second time for a platform built specifically to mine calendar data is a different risk calculus, and this catalog answers Q2 "no" and leaves the SMS acceptance where it stands.

Q3 — sealing forced? N/A: Q2 already disqualifies it as a negotiation transport.

Where it's a legitimate future feature: once state == "agreed" (SHARING-SPEC §6), pushing that single confirmed event — via events.insert, no negotiation history, no other party's identity beyond a display name — into the agreeing party's own Google Calendar is the same operation as writing derived/event.ics today, aimed at a hosted target. This publishes a result. No negotiation is routed, and none of I1–I15 changes.

Status: FUTURE as a derived-output integration; not specified. REJECTED as message transport.

CalDAV rejected; EventKit is the last-hop mechanism

Apple Calendar — CalDAV / EventKit

Two distinct things share this name and get separate verdicts.

CalDAV (RFC 4791, WebDAV-based, federated). Q1: yes, any CalDAV server (iCloud's, or a self-hosted one) can carry arbitrary event data. Q2: same disqualifying answer as Google's — the calendar-never-leaves invariant (I1) applies to any calendar service the negotiation would route through, regardless of who operates it; a self-hosted CalDAV server run by an operator the circle already trusts changes the operator-trust math for other purposes. Even so, this catalog routes negotiation through no calendar server at all, however much the circle trusts its operator. Q3: N/A, disqualified at Q2.

EventKit (on-device framework, with no network model of its own). This is the mechanism for spec §7's "the person is the last hop." It is not a transport candidate at all. Where stage_text_send() hands framed text to Messages via a share sheet today, an Apple-platform build of pna_share could hand a confirmed event directly to EKEventStore. That drops the manual import of derived/event.ics — same last-hop doctrine, one fewer manual step, on Apple hardware specifically.

Status: FUTURE for the EventKit last-hop integration; not specified. REJECTED as message transport (both CalDAV and any calendar-hosted transport).

researched, then rejected as message transport — may still be useful elsewhere

AT Protocol (the protocol underneath BlueSky)

What it actually is, precisely: each identity is a DID (decentralized identifier) resolving to a DID document; a person's data lives in a PDS (Personal Data Server, self-hostable); records are typed by lexicons (JSON-schema-like definitions) and committed into a repository — a signed, Merkle-Search-Tree-backed commit log; a public relay ingests every subscribed PDS's commits and republishes them on a firehose that any client (including BlueSky's own app) subscribes to.

Q1 — moves bytes? Yes, and in an interesting way: a custom lexicon (e.g. org.kisop.together.propose) is a well-defined path to typed, versioned KISOP record types living in a repo with real provenance — the same "signed thread is canonical" doctrine SHARING-SPEC §6 already uses for exchange/, arrived at independently by an unrelated protocol.

Q2 — operator trust? No, and structurally so: the relay/firehose's entire purpose is public broadcast of every subscribed repo's writes. This is the load-bearing mismatch: SHARING-SPEC §2's founding rule ("known people only... not a social network," I3 "unknown senders never reach the human") is the *opposite* of AT Protocol's default posture. A private PDS that never subscribes to or publishes on any relay is possible, but at that point it has re-derived shared-folder transport with a heavier identity/schema layer bolted on. Nothing AT-Protocol-specific is gained.

Q3 — sealing forced? Yes if attempted at all — records would need encryption before they ever leave the PDS, which is exactly the same age/e2e work every other untrusted-operator transport on this page already requires. AT Protocol's own machinery adds nothing on top of it.

What's worth a second look, separated from message transport entirely: the DID identity model as a possible future contact-id namespace (portable, person-owned, closer to the spirit of a contact-id than a phone number), and the repo/commit-log pattern as a possible alternate storage engine for exchange/ in a much later version. Neither requires adopting the public firehose transport.

Status: FUTURE, researched only — the furthest from build-readiness of the five; would require a private-PDS operating model, a custom lexicon, and a DID key-management story this catalog does not specify. REJECTED as message transport.

Enforced versus recorded

Same discipline as every technical page in this series: a claim is ENFORCED only when a test refuses the violation today; RECORDED is written down and honored by convention; FUTURE is researched or designed. The build has not started.

ClaimStandingWhere
Shared-folder transport moves envelopes between paired archives, trust declared and enforced at sendENFORCEDpna_share.py — I7/A10
Text-message transport refuses to frame anything not sealed e2e; uniform distrust hardcodedENFORCEDpna_text_courier.py — test B1
The three-question test applied to Signal, Google Calendar, Apple Calendar, AT ProtocolRECORDEDCOURIER-CONCEPT-v0.1.md §2 — reasoning written down; nothing coded yet
Google/Apple Calendar as derived-output (post-agreement) targetsFUTUREnot specified
EventKit as the Apple-platform last-hop mechanismFUTUREnot specified
AT Protocol DID as a contact-id namespace / repo-log as an exchange/ storage engineFUTUREresearch idea only, no spec
Real libsignal integration (X3DH/ratchet) for a higher-threat-model circleFUTUREexplicitly deferred, reopen only if the threat model changes

Attack here

Good-faith security research is welcome through the main site's Write to us → security door — a safe harbor written into our Terms, §15.

Where this stands

Written July 12, 2026, as a research catalog. Nothing was built in that session. Two transport options are real and tested: shared-folder transport (built earlier, 88-test adversarial suite green) and text-message transport (built this week, 25 tests green). The other three candidates on this page were evaluated on paper against the same three-question test and rejected as message transport for named, specific reasons. Time was not the constraint.

Open design calls (Carmen's, recorded in COURIER-CONCEPT-v0.1.md §4; work continues while they wait): whether the Google/Apple Calendar derived-output integrations are worth speccing next · whether AT Protocol's identity model is worth a dedicated research session · confirming the Signal-properties-without-Signal-software judgment stands.