Part 3: The Mesaĝkesto
Part 3 of a series introducing Mesaĝkesto, a protocol for secure messaging between self-certifying identifiers.
Recap
Part 2 ended on a promise: once identity carries its own proof, the thing that stores your messages has very little left to do. This post is the cash-out. It's about what a box actually is — and the answer is deliberately, almost disappointingly small.
Three things: a shape for messages, an order for them, and a way to catch up.
One envelope for everything
Every message is wrapped in the same envelope, and the envelope is about as plain as it gets. It says which version of the protocol it speaks. It carries its own digest — a hash of its contents, computed from the message itself. It names the identifier it's addressed to. And it carries a payload.
The payload begins with a type, and that type decides everything else: what the rest of the fields mean and what the receiver should do with it. A plain text message is one type. A receipt confirming delivery is another. A channel event, an invitation, an attachment reference, a calendar entry — all types.
This is a small decision with large consequences. New kinds of communication don't need new protocol machinery, new versions or new negotiation between implementations. They need a new type, understood by the clients that care and ignored by everyone else. Remember from Part 1 that "messaging" here means all digital communication between peers — this is the mechanism that makes that generalisation cheap rather than aspirational. The box never has to learn what a calendar invite is. The whole envelope is signed by its author. Not by the box, not on the box's behalf, and not verified into existence by the box: the signature travels with the message so that the receiver — who has the sender's log from Part 2 — can check it themselves. A box that lies about a message's contents is caught by arithmetic, not by policy.
The message names itself
That self-contained digest is worth a moment. Because the hash is computed from the message's own content, the message effectively has a name that anyone can recompute and nobody can forge. Change a byte and it's a different message with a different name.
Small property, useful everywhere. Duplicate delivery becomes harmless — the same message arriving twice is recognisably the same message, so retries are free and delivery can be sloppy. Anything that needs to refer to a message refers to it by digest: a receipt says "I have the message named this", a reply points at what it's replying to, and neither needs the box to have assigned an ID or to be involved at all.
Strict order
When a message arrives at a box, the box does one thing with it that the sender couldn't: it stamps it with the next number. The first message in a box is 1, then 2, then 3, forever upward, no gaps and no reordering.
That's the whole storage model. A box is an ordered list, per identifier. It sounds too simple to matter, and it's the most load-bearing decision in the protocol — because it means a client's entire synchronisation state is one number. I have seen everything up to 42. Nothing else. No per-message bookkeeping, no set of pending IDs, no local database of what has been acknowledged. If this feels familiar it should: it's how email clients have kept mailboxes in sync for decades. Give me everything after this number. It is the humblest possible synchronisation primitive and it has outlived a great many cleverer ones.
Push for speed, pull for truth
Now the part that makes the whole thing robust. A box notifies you when something arrives — a live connection if you have one open, a push notification if your device is asleep. That's how messaging feels instant, and it's how it should work when everything is fine. But notifications are not a delivery mechanism. Your connection drops mid-send. Your phone is in a tunnel. The push service is degraded, or throttled you, or decided your app was idle. The notification arrives out of order, or twice, or not at all. Every real deployment of every messaging system lives in this world, permanently.
The usual answer is to make delivery reliable through acknowledgement: every message tracked, every ack recorded, retries scheduled per recipient, state machines to reconcile when acks go missing — and then acks for the acks, since the ack path is just as unreliable as the message path. It's a lot of machinery, it's where the hard bugs live, and it gets multiplied by every device a person owns.
Here, none of that is necessary, because of the number. Push is an optimisation; the pull is the truth. Whenever a client reconnects, wakes up, recovers from a crash, or simply feels like it, it says "give me everything after 42" and it is correct again. A push that never arrived costs nothing but latency. A push that arrived twice costs nothing at all.
Occasional convergence is dramatically cheaper than continuous agreement, and it fails better: the worst outcome of every failure in the notification path is that a message is late, never that it's lost, and never that two parties disagree about what happened.
Multi-device falls out of the same fact for free. Each device tracks its own number, at its own pace. A laptop opened after three weeks is not a special case needing a sync protocol — it's a device with a small number asking for everything after it. The box doesn't track devices at all; it doesn't know there is more than one.
What a box should refuse to hold
There's an old temptation to make the box do more: store the video, hold the photo library, become the place your data lives. It's worth resisting, and not only for privacy reasons. Messages are small and want to be ordered, replicated and kept in sequence. Bulk content is large, immutable and wants to be stored once and fetched by whoever has a right to it. Those are different problems with different economics, and a box that tries to do both scales like the worse of the two.
So large content travels by reference. The bytes go to storage — addressed by content hash, so a reference is unforgeable and self-verifying in exactly the way Part 2's identifiers are — and the message carries only the reference, inside the part the box can't read. The conversation stays a lightweight, ordered log of small signed events. The bulk becomes somebody else's commodity infrastructure, which is a good thing: storage is a mature, competitive, boring business, and there is no reason your messaging provider should also be your disk. Anyone can host bytes; the reference names them exactly, so it doesn't matter who.
Forgetting is a feature
A box forgets, on a schedule you agreed to when you chose it. This tends to alarm people, and it shouldn't, because of where the messages actually live. A box is a buffer — Part 1's locker. Once your devices have collected a message, the box holding it forever serves nobody but an attacker and a subpoena. Retention is a service level, negotiated openly: keep nothing past delivery, keep a week, keep everything for as long as you pay. Different boxes will sell different answers, which is what a market in infrastructure looks like.
The alternative — a provider who keeps everything indefinitely at no charge — is not generosity. Someone is always paying for storage; when it isn't you, the payment is your data. Being charged honestly for a buffer is the cheaper deal, and Part 7 argues you can only get that honest price where leaving is free.
What the box still knows
Being straight about the gap, as promised. Even with contents it cannot read and messages it forgets on schedule, a box sees that something arrived for this identifier, roughly how large, and when. That's metadata, it's real, and encryption doesn't touch it. Two of the three answers are already in this series. Who is allowed to write to your box is enforced without the box learning who your contacts are — that's the next post, and it's the most surprising piece of the design. Who sent any particular message is hidden inside the encrypted part, so the box routes without learning the pair. What's left after that — sizes, timing, the mere fact of traffic — is genuinely unfinished work, and Part 8 says so plainly rather than hiding it behind the parts that are solved.
The summary you can hold in your head
A box accepts signed envelopes addressed to identifiers it hosts. It puts them in a strict order. It hands them to whoever proves control of the identifier, starting from whatever number they ask for. It forgets on schedule.
That's the protocol. Everything else — encryption, groups, attachments, receipts, presence, whatever comes next — is a payload type agreed between clients, over a transport that doesn't need to understand it.
The reason to keep the box this dumb isn't minimalism for its own sake. It's that a component this simple is one you can replace, and being replaceable is the entire point.
Next: A server that cannot read your contact list — how a box enforces "only my contacts may write to me" while holding no idea who your contacts are.