2026-05-07 · By Jens-Christian Fischer and Andreas Åström · 5 min

Sovereignty in the envelope: why policy rides with the message

Most messaging systems attach policy outside the message — an external ACL, a policy server, a sidecar next to the queue. Myelin disagrees. The case for moving classification, residency, and model constraints into the envelope itself.

The default pattern

Pick any production messaging system from the last twenty years. The pattern is roughly the same. A message is a body. The body has a header. The header carries routing metadata — topic, partition, timestamp, ID. Policy lives elsewhere: an ACL on the topic, an attribute on the consumer, a token in the connection, a row in a database the consumer reads at startup.

This works well when policy is stable, the message lives for milliseconds, and the trust boundary is the connection. It fails in three places we kept hitting:

The myelin position

Each envelope carries the policy it was sent under, directly inside it. We call this the sovereignty field. It looks like this:

"sovereignty": {
  "classification": "internal",
  "residency":      "EU",
  "model_class":    "frontier-ok",
  "ttl_seconds":    3600
}

The fields are short on purpose. classification is the data classification level — public, internal, confidential, restricted. residency is the jurisdiction the data must stay in. model_class is which class of model is allowed to read it. ttl_seconds is when the envelope's right to exist expires.

Together they answer the four questions every downstream component needs: can I see this?, can I forward this?, can I store this?, can I show this to a model? All readable from the message alone, with no external lookup.

Three consequences

  1. Compliance is a single function call. Any layer above M3 reads the same field and applies the same rule. No database round-trip, no policy-server fan-out, no race condition between "the message arrived" and "the policy loaded."
  2. Archival preserves intent. The envelope that lands in cold storage is the same envelope that ran through hot processing. If we replay it next year, we replay it under the policy it was sent under — not the policy in effect today.
  3. Federation is mechanical. When a federated subscriber pulls an envelope from another organisation's hub, the policy comes with it. There is no separate "and here are the rules for this batch" sync. The envelope is self-describing.
Sovereignty travels with the message.

What this is not

The envelope is not a policy engine. It does not decide whether a recipient is allowed to read it. The recipient does. The envelope is the evidence for that decision — the inputs the recipient's policy code consumes.

That distinction matters. We are not building a permissions system that travels in the message. We are building a permissions statement that travels in the message. Two different things. The statement is small, stable, and signable. The system that interprets it lives where it always has — at the receiver.

The trade-off we accept

Putting policy in the envelope means envelopes are bigger. About 80 bytes bigger, in the current shape. Multiply by every message on the bus and you get a real but modest overhead.

We accept it because the alternative — central policy servers that have to stay consistent with every receiver, every replay, every federated peer — is what we were trying to leave behind. Eighty bytes is a small price for keeping the message self-describing.

What's next on this dimension

← All posts myelin overview Envelope schema ↗