Skip to content

the net routes around damage. so do we.

Tieroute is an open, federated protocol for end-to-end encrypted chat.

It starts from your contact list, not a public square: direct chats, groups of up to 25, and voice calls with people you've actually added. Your identity is a chain of entries you sign yourself. Groups run on MLS, and every key exchange is hybrid post-quantum, because recorded traffic doesn't expire. We build Reroute, a desktop app, and rerouted, the reference server. But the spec is the point.

Tieroute v1 draft. The v1 spec hasn't had its outside cryptographic review yet, and the wire format can still change. Don't rely on it for anything sensitive.

Group encryption
MLS (RFC 9420)
Key exchange
ML-KEM-768 + X25519
Wire format
JSON, with CDDL schemas
Contact requests
Invite code only
Group chats
Up to 25 people
Calls
Voice, up to 10 people
Files
64 MiB, kept 30 days
Phone or email
Never asked for

Protocol

Written so someone else can implement it

We want someone who has never talked to us to be able to build a compatible server or client from the spec alone. So servers are kept deliberately dull: they move sealed bytes and check a short list of rules, and all the cryptography lives in clients. A lot of the design is a reaction to what we watched go wrong elsewhere, like servers that own your identity, direct messages the admin can read, loose schemas, unsigned content, and small servers drowning in fan-out.

The server never sees inside MLS
It only reads the Tieroute envelope we put next to the ciphertext: group, epoch, message type, recipients. That’s enough to route and enforce allowlists. The cryptography stays on the clients.
§2.3
Nothing new in the crypto
MLS, SFrame, HPKE, ML-KEM-768 with X25519, and Ed25519, all published and reviewed by people who aren’t us. How we fit them together gets an outside review before v1 is frozen.
§2.2
Bring your own MLS library
There’s no libtieroute. Any MLS library that supports the profile will do, which is why the profile sticks to features the mainstream libraries already have.
§11.1
Invite codes, always
Nobody can even ask to be your contact without one. You hand codes out, or publish one on your profile if you want to be findable. Requests carry no text, so there’s nothing to spam you with. And a refused delivery gets the same 202 as an accepted one, so nobody can probe your allowlist.
§9.1, §10.3
No phone number, no email
Your devices sign you in. If you lose all of them, 12 recovery words get you back; there’s no reset link, since there’s nowhere to send one.
§6.1
Plain JSON
Every protocol object is JSON. A bit verbose, but you can read live traffic with curl, and what’s stored today stays readable long after whatever wrote it is gone.
§4

Network

Alpha homeservers, checked live

  • rerouteholdings.llc

    Checking

  • nocarrier.fail

    Checking

Each server document is fetched and checked for a v1 API, at most once a minute.

Homeservers and federation

Anyone can run a homeserver. It carries sealed traffic for its own users and nobody else’s. Finding a server takes one JSON document, and every call between servers is a plain HTTPS POST with a signed body. No special transport, no persistent connections between servers.

Roles

Homeserver
Per user. Stores your identity chain, device list, MLS key packages, contact list and group allowlist, and an inbox with a read position per device. Authenticates your devices, enforces allowlists, and speaks server-to-server for you. Never sees plaintext.
§8–10
Hub
Per group. Not a separate server, but a role a homeserver plays for one group: the creator’s to begin with, and another member’s if an admin hands it off later. It orders commits (first valid one per epoch wins), stores them for members who were offline, and signs receipts. Application messages never touch it.
§11.6, §11.11
TURN relay
Each homeserver relays calls for its own users. Calls relay by default, so contacts don’t learn each other’s IP addresses.
§15.1
Device
Each device has its own Ed25519 key, its own MLS leaf in every chat, and pulls its own copy of every delivery.
§7

A message, end to end · §10.2

  1. 01 Encrypt The device encrypts with MLS and wraps the ciphertext in a delivery envelope: group, epoch, message type, and every recipient identity, from the MLS tree.
  2. 02 Submit POST send to its own homeserver, authenticated by a session token bound to the device key. Commits go to the group’s hub first and come back with a signed receipt.
  3. 03 Fan out The homeserver groups recipients by their current home, from cached chains, and makes one signed deliver call per destination server, with to narrowed to that server’s users.
  4. 04 Verify The receiving server checks the server signature, the clock, and the nonce, then that the sender’s chain names the calling server as home.
  5. 05 Admit Each recipient’s allowlists decide: chat traffic needs a group they joined, and a Welcome needs a contact. Refusals still answer 202.
  6. 06 Pull Every device of the recipient pulls the item from its inbox and acknowledges it. Once all devices have, it’s deleted; otherwise it expires after 30 days.

/.well-known/tieroute/server

name
The server’s DNS name. Never an IP address.
§5.1
roles
"home" in v1. Readers ignore roles they don’t know, so later versions can add more.
§5.1
apis
The client and server-to-server base URLs for each wire version. The only fixed path in the protocol is this document; everything else is found from here.
§8.1
keys
Ed25519 signing keys, each with a key ID and a validity window. Readers keep old keys until they expire, so rotation never breaks signatures in flight.
§5.1
handles
The domain this homeserver gives out free handles under, like tieroute.example for user.tieroute.example.
§5.2
registration
"invite" or "closed". A server open to everyone publishes a public invite code, and closes by revoking it.
§8.2

When things break

A server goes down

Everyone sending to it keeps their calls in a durable outbox and retries with backoff. For 72 hours. Then the sending device is told, so a message never just vanishes. §10.5

A device is stolen

If the thief removes one of your devices or moves your account, every device you still have raises an alarm right away. For the next 72 hours your recovery code can overrule anything they did, on every server. After that their changes stand, but you can still kick the device out. §6.4.1

You leave a server

Your app asks the new server first, and gets back a signed reservation for the move. Your old server won’t record the move without one, so a move can’t leave you between two servers. If the old one is gone, or decides to be difficult, sign the move with your recovery code instead. Every server accepts that, from anywhere. §6.6

Try it

Ask a real server

These go to the real alpha homeservers, through this site, as you press Send. They’re the protocol’s public read-only endpoints (the server document, a handle, an identity chain), so you can’t break anything by poking at them.

GET https://{server}/.well-known/tieroute/server

The one fixed path in the protocol. It names the server, lists its API base URLs for each wire version, its signing keys with their validity windows, the domain it gives handles under, and whether it takes new accounts.

Choose Send to run the request.

Identity

Identity is a chain you sign

Your identifier is a hash of the first entry in a chain that only you sign. A server can host the chain, but it can’t forge an entry, take your identifier, or keep you from leaving. Every device signs with its own key. The recovery key stays offline, and it outranks all of them.

Identity chain
A hash-linked list of signed entries. Ops: add-device, remove-device, set-home, set-handle, set-recovery. The first entry (genesis) is signed by your first device.
§6.3
tr:…
Your permanent identifier: "tr:" plus the first 15 bytes (120 bits) of SHA-256 of the canonical (JCS) genesis entry, in lowercase base32.
§6.2
Handles
Domain names: user.tieroute.example or your own domain. Resolved over HTTPS at /.well-known/tieroute/handle (a DNS TXT record counts only with DNSSEC), and only trusted if the chain names the handle back.
§5.2–5.3
Recovery code
16 random bytes shown as 12 BIP-39 words. Recovery keys derive from it with HKDF. Pre-rotation: the chain publishes only SHA-256 of the next recovery key, so no recovery public key is exposed before it’s used.
§6.3
Fork rule
A recovery-signed entry may replace device-signed entries up to 72 hours older than itself. That’s how a stolen device’s changes are undone everywhere, even where the forked chain is shorter.
§6.4.1
Who vouches
A device-signed entry only counts if the server that was home immediately before it appended it, so it went through that server’s clock check and alerts. A thief can’t have their own server push a backdated move to your contacts. Recovery-signed entries count from anywhere.
§6.5
Alerts
A device-signed remove-device or set-home raises an alarm on every device of the account; add-device raises a notice. Chats show a line when a member’s devices change.
§6.4.1
Verification codes
XXXX-XXXX in Crockford base32, 40 bits, from a commit-then-reveal round inside the direct chat, so an attacker gets one guess per round. The transcript includes both chain heads, so a match also proves you see the same chains.
§6.7

Contacts and delivery

Contacts, and how messages travel

Nobody reaches you without an invite code. Even then, nothing gets to your devices that your allowlists didn’t let in. Between servers every call is signed, and when something can’t be delivered the sender hears about it.

Invite codes
10 characters, created on your homeserver with an optional use count and expiry; the server stores only a keyed hash, under a secret outside its database. Paste @handle::code to send a request, or share it as a link: rerouteholdings.llc/@handle::code, a page that stores nothing. A decline blocks new requests for 30 days.
§9.1–9.4
delivery
{id, kind, from, to, group, epoch, mls, receipt, ephemeral, data}. Servers read every field except data, which is a base64url MLS PrivateMessage or Welcome.
§10.1
s2s-request
Every server-to-server call is a POST whose body is signed by a server key named in the sender’s /.well-known/tieroute/server document. Checked: destination, path, ±5 minutes, and a fresh nonce.
§8.3
Push, then pull
Your homeserver pushes each delivery to the recipient’s homeserver; their devices pull from an inbox and acknowledge. Items are kept 30 days, and deduplicated by ID for 7.
§10.2–10.4
Durable outbox
Failed calls are retried with exponential backoff and jitter, from 10 seconds up to hourly, on one schedule per destination server. 408, 429, and 5xx are retried; other 4xx are final. After 72 hours the sending device is told.
§10.5
Speaking for users
A server may act only for identities whose chain names it as home. After a move, the old home gets 72 more hours for one thing, delivering what was already queued; it can’t claim key packages or send requests in your name. Fetched chains must extend the cached one or be a valid recovery fork; nothing else replaces a cache.
§6.5, §6.6, §10.2

Live

Watch the server work

This is rerouteholdings.llc, live. Each row is a message, a group change, or an invitation, with everyone it reached. The server keeps the ciphertext to itself, and the group ID too, so all you get is the envelope it routes on: who, what kind, how big. Open a row to see what’s left of it.

rerouteholdings.llc is a public development server. Its traffic is shown here on purpose, including who talks to whom. Use another homeserver for anything you want kept between you and your server.

Connecting
  1. Waiting for something to happen. The server replays its last 50 deliveries when you connect.
kind, mls
What the server routes: mls for chat traffic, and the MLS message type (app, commit, or welcome).
from, to
The sender’s identifier, and every recipient’s. Servers need them to enforce allowlists.
group, epoch
Which MLS group, and how many times its membership or keys have changed.
data
The MLS message, base64url. Only the recipients’ devices can decrypt it.
receipt
On commits: the hub’s signed receipt that it accepted the commit (§11.6).

Groups and devices

Group chats with MLS, ordered by one hub

MLS needs every member to apply commits in the same order, so something has to pick the order. We picked one server per group, the hub, and then made it hard for the hub to misbehave: only members can sign a commit request, and every commit it accepts comes back with a signed receipt.

MLS profile
RFC 9420 with MLS_128_MLKEM768X25519_AES128GCM_SHA256_Ed25519 (0x004F until IANA registers 0x0010). PrivateMessage only. A direct chat is a two-person group.
§11.1
tieroute_group
GroupContext extension 0xF0A1: kind, hub, admins, since, replaces, and the add-approval bookkeeping, plus heads and basis, the chain history each change was checked against. Groups without it are refused.
§11.2
The hub
One server orders each group’s commits. That’s the creator’s homeserver at first; after a hub handoff, it’s another member’s. Whichever it is accepts the first valid commit per epoch, answers later ones with 409 stale-epoch, and signs a receipt every client checks.
§11.6, §11.11
Epoch keys
Ed25519 keys derived from MLS-Exporter("tieroute hub", group_id, 32). Only members can sign a commit request, and the hub learns nothing it could read.
§11.6
Admins
Admins add their contacts directly, remove people, and grant or revoke admin. Other members propose an add; it goes through only with an admin’s signed approval, carried encrypted inside the commit and used once, so every member reaches the same verdict.
§11.8
Same verdict everywhere
A change carries its own evidence: for each person it depends on, the chain entry it was checked against, by hash, and the few entries before it. Every member judges it against that same history, however old their own copy is, so nobody ends up stuck in an epoch the rest left. A member who can’t get the history waits, and sends nothing to the group meanwhile.
§7.1
Devices as members
Every device is its own MLS leaf, with credential [identifier, device key]. When a chain changes, whichever member notices first commits it. A removed device goes at once, and until it’s out, members hold their own messages to that group. Replacing someone’s only device is one commit, so they never drop out in between.
§7, §11.9
Linking a device
The new device shows a link code; a typed code is answered with an XXXX-XXXX confirmation that must be typed back and signed. The link bundle, sealed with hybrid HPKE, brings contacts, groups, and history.
§7.2
Limits
At most 25 people and 250 devices per group, 10 per person. A stuck group can be re-created in one click; everyone else gets it as an offer, and decides whether to switch.
§11.10–11.11

Privacy

What your homeserver can and can’t see

Passes through sealed

  • Messages

    MLS, and each one signed by the sending device

  • Files

    Encrypted before upload; 64 MiB, kept 30 days

  • Group name, topic, picture

    Inside MLS, so only members see them

  • Typing and read receipts

    Encrypted and never stored; receipts only when both sides agree

  • Calls

    DTLS-SRTP plus SFrame keyed from the chat’s MLS group

What your server does see

  • Who talks to whom

    The sender ID on each delivery, which allowlists need

  • Contacts and groups

    Your homeserver keeps them as allowlists

  • Presence and status

    Seen by your homeserver; shown only to contacts

  • Public profile

    Display name, picture, bio, and any public invite code, to anyone

  • Timing and sizes

    When deliveries happen and how large they are

So servers see who talks to whom, and never what’s said. Hiding the social graph too would take mixnets or private information retrieval, and we decided v1 can live without them; §18.1 lists everything a server can see. Moderation is report-only. Nobody scans your chats, and a report shares a decrypted copy only when the person reporting chooses to, signed by whoever sent it.

Calls

Voice calls between contacts

A call lives inside the chat you already have. Signaling goes through that chat’s MLS group and the media keys come from it, so a call is exactly as private as the chat it started in.

Signaling
Ringing, offers, answers, and ICE candidates are messages inside the chat’s MLS group, end-to-end encrypted like any other. A missed ring shows up later as a missed call.
§15.2
Media
WebRTC between participants, with no media server: a mesh of up to 10 people, even in a 25-person group. No separate video calling: a camera is one more thing to cast.
§15.2
Media casting
Proposed: anyone in a call can cast video, audio, or both, from a screen, a camera, or a film, over the call’s own connections and sealed with the same SFrame keys. Cast sound stays apart from voices, so people talk over it, and each listener sets its volume or mutes it.
§15.3
Sealed twice
DTLS-SRTP between peers, plus SFrame keyed from the chat’s post-quantum MLS group, so recorded calls stay sealed against a future quantum computer.
§15.2
Relayed by default
Media goes through each side’s own homeserver TURN, so neither side sees the other’s IP address. A setting allows direct connections.
§15.1–15.2
Community servers
Self-hosted spaces with voice and text channels are planned for a later version. They aren’t part of v1; the draft design is with the spec pages.
Later

Wire format

JSON on the wire, signed and checkable

JSON
I-JSON (RFC 7493): UTF-8, no duplicate names, integers only. Byte strings are unpadded base64url. Plain text can be inspected and preserved with ordinary tools.
§4.1
signed
{t, b, k or kid, s}: a type tag, the body as JSON text, the signing key, and an Ed25519 signature over JCS ["tieroute/v1", t, b]. Verifiers check the exact text they received; nobody re-encodes a signed body. Verification is pinned exactly (S < L, no small-order points) so every implementation agrees on every chain.
§4.3
Schemas
Every wire object is CDDL in the spec, extracted to one file and checked for duplicate and undefined rules.
§4
Test vectors
Signed envelopes, Ed25519 edge cases, recovery derivation, a full identity chain, the fork rule, verification codes, device linking, formatting, and the group evidence checks, checked by both implementations and an independent script, which agree byte for byte.
§19.3
v1 core
§3 to §11, the app-message envelope and text, the APIs, and the vectors. Every change is logged; v1 is frozen once the outside cryptographic review is done.
§19
  • MLS RFC 9420
  • SFrame RFC 9605
  • HPKE RFC 9180
  • Ed25519 RFC 8032
  • I-JSON RFC 7493
  • JCS RFC 8785
  • X-Wing IETF draft

Status

What exists today

There’s working code. rerouted, the reference homeserver, is Go and implements every endpoint in the v1 draft. Reroute is Rust and Svelte and implements the whole draft, calls included. Both are alpha, and we mean that.

Contacts and chats
Invite codes, requests, declines, and blocking. Direct chats with replies, edits, deletes, reactions, typing, and read receipts only when both sides agree.
Stage 1
Federation
Signed server-to-server calls, chain pushes, a durable outbox, and a notice when a message can’t be delivered.
Stage 2
Devices and groups
Linking by QR code or typed code, with a hybrid HPKE link bundle that carries contacts and history. Recovery with 12 words, verification codes, and group chats of up to 25 with admins, approvals, and re-create.
Stage 3
Recovery and backups
Encrypted account data, a message backup locked with a passphrase that the recovery code also opens, moving between homeservers, and devices that rejoin after being offline too long.
Stage 4
Profiles and files
Signed public profiles with pictures, presence with auto-away, files encrypted before upload, and reports that carry the sender’s signature as proof.
Stage 5
Voice calls
One to one and in groups of up to 10: WebRTC between devices, signaled inside the chat, with SFrame keyed from its post-quantum MLS group, relayed by default so nobody sees anybody’s IP address.
Calls
Outside review
An independent cryptographic review comes before v1 is frozen.
Before v1
  • 24

    attacks on the server-side claims of §17.2, tried from outside against two servers and two rogue ones. Each one was refused.

  • 3

    implementations of the test vectors that have to agree: the Go server, the Rust client, and an independent JavaScript checker.

  • 12

    demo scripts in the repo that run the protocol end to end across federated servers, from the bare server to calls. A few attack it, and one upgrades data and clients from older releases.

Reroute is a desktop app for macOS, Windows, and Linux. The alpha homeservers register new accounts by invite code. rerouteholdings.llc is a public development server: its traffic, sealed but with who-sends-to-whom visible, is shown in the live feed above.

Company

Built so that it doesn’t depend on us

Reroute Holdings LLC is a small company that designs Tieroute and builds Reroute and rerouted.

We’d like to be optional. Your identity is a chain you sign, not an account we hold, and servers are interchangeable; anyone can run one. The spec and its test vectors are written so you can build a compatible server or client without ever asking us anything. If we disappeared tomorrow, your contacts would still have your keys and the servers would keep routing.

  • Open by design

    Self-certifying identity and an open spec mean nobody can close the network later, including whoever owns this company by then.

  • No phone or email

    Never asked for, so never depended on for your identity.

  • No scanning

    Encrypted chats aren’t scanned on the server or on your device.

  • No directory

    There’s no central list of people to search. The people you give a code to can reach you.