D-1 Name — made
your.os; each instance is <you>.os.
D-2 Signatures: hybrid Ed25519 + ML-DSA-65 where they live long — proposed
A signature cannot be harvested now and forged later: forging needs a quantum computer at the time, so a short-lived proof is safe classical. A long-lived key is not: whoever can forge the account key mints delegations. So the account key, node keys and delegations are hybrid (both must verify) from the first release; per-call proofs are Ed25519 alone, since they are live and ML-DSA-65 makes each one ~3.3 KB against 64 B. Limit: a passkey or hardware key signs only classical, so a chain rooted at one is classical at its root.
D-3 Five concepts, our own fabric — proposed, under review
Node, log, pipe, session, service (README.md). A relay is a node that
forwards {to, ciphertext} by key and learns nothing else. Not zenoh as the
fabric: spikes/zenoh/ used six calls and pulled 435 crates, and a router
that routes on key expressions sees which verb, on which node, how often. The
spike kept: sealing costs 25 B a message; a chain bound to its session costs
almost nothing.
D-4 Services are processes on a local socket — proposed
Any language, so existing services port unchanged. In-process (a Rust trait) where there are no processes; WASM components later, for services nobody vouches for.
D-5 Licence — open, narrowed by D-16
Argued in README.md (Licence), with pricing: free for people, paid for
businesses. D-16 leaves two: Apache-2.0, or AGPL-3.0 with a contributor
licence agreement, since our relay builds on the open crates and an AGPL
contribution could not reach it without one.
D-6 Domain and passkey RP ID — open
Fixed for ever once the first credential is minted. Per-person subdomains
need the domain on the Public Suffix List. The docs' current host is a
stand-in, and user origins can't go under it: its subdomains already serve
third-party pages through a tunnel, and a key-holding origin must not be
same-site with those. The landing needs a registrable domain of its own.
A self-hosted account brings its own domain and needs no listing
(relay/own-domain); the Public Suffix List is for names on ours, and its
review takes weeks, so the submission goes in as soon as the domain is
chosen. Names leak three ways, and each is closed before the first is
minted: Certificate Transparency logs every name a certificate covers, for
ever and in public, so names share a wildcard certificate; SNI names the
host in the clear, so the edge offers ECH; DNS asks in the clear, which DoH
(the browser's, 1.1.1.1 or any) hides from the network.
D-7 Sessions outlive pipes; pipes bring reliability — proposed, under review
Messages are numbered and sealed one by one; reliable ones are acknowledged
end to end and resent only after a pipe change; datagrams use a replay
window. Congestion control is the pipe's (TCP, SCTP, QUIC). Rejected: a
session that dies with its pipe (a handshake per flap, and no lossy streams);
writing our own QUIC (loss recovery and congestion control are its years).
Open before accepting (spikes/sessions/): TCP_NODELAY on every stream
pipe (Nagle cost a 43 ms p95); protect the header, so a relay cannot read a
message's kind and counter; bound the unacknowledged buffer and end the
session when it overflows; build the rekey ratchet with its generation
number.
D-8 Sessions — proposed, under review
Peers' keys come from the log, so a handshake carries ciphertexts only and takes one round trip, the first request riding in it. HKDF over the handshake, one key per direction, counter nonces, rekey by ratchet on time or count, with the key generation in each message. The chain is verified once; the session ends when it expires or is revoked. Nothing here is a setting.
D-9 Pipes: a WebSocket floor, the rest optional — proposed, under review
Required: WebSocket to a relay. Optional: WebTransport to a node that made
itself reachable (a self-signed ECDSA certificate of ≤ 14 days, its hash sent
sealed), WebRTC for every other NAT (ICE; DTLS underneath, not trusted; TURN
is a relay that sees ciphertext), native QUIC between nodes. Rejected: iroh as
the fabric — relay-only in a browser, and its hybrid key exchange comes from
aws-lc-rs, which may not build for wasm; ours ran in a browser in 23 ms.
Open before accepting (spikes/sessions/): drop or shorten to on a direct
pipe (32 of a message's 66 bytes); the relay drops datagrams under load and
never reliable messages (it forwards everything today). Measured on msi: no
mapping protocol, no IPv6, port-dependent filtering — WebTransport-direct
could not work there, so WebRTC carries the direct path on such networks.
More candidates: WebRTC-direct (with the certificate hash known, sent
sealed, a browser opens WebRTC to a public UDP port with no signalling, as
libp2p does; Safari included); port mapping (UPnP, NAT-PMP, PCP); IPv6
host candidates; port spraying on native nodes for hard NATs; another
mesh's addresses (a tailnet, the LAN) as one more candidate. When punching
fails the WebSocket floor has no datagrams, so a screen or a voice queues
behind everything; Cloudflare Realtime DataChannels are a datagram relay
that sees ciphertext, a fallback beside TURN. MoQ relays (WebTransport to
the edge, which a Worker can't serve) are worth watching while the spec is a
draft. Rejected: WARP and Zero Trust device-to-device (every user enrolled
in our organisation, no browser, Cloudflare's identity instead of the log);
Cloudflare Tunnel (one more relay, an account per machine).
D-10 The account log: a signed DAG, and a revocation wins — proposed
Each entry names its parents by hash, so the log is a grow-only set that is
also tamper-evident and causal: genesis (the account key), add device (key,
Admin or Member, name), revoke key, grant, ungrant. Hybrid-signed (D-2) by the
account key or an Admin device whose authority is in the entry's own past;
the signer's keys come from that past, never from the entry. A revocation is
final and is never undone by what it did not see; anything else the revoked
key signed that the revocation did not see is void, so a lost laptop's
earlier enrolments stand and its later ones do not. Two adds of one key that
disagree take the lower role. Encoding is hand-rolled, one form per entry:
core/crypto-crates-only allows crypto crates only, and a signature needs canonical bytes
that serde formats do not promise. Rejected: a linear chain (two devices
append at once, and one of them would lose); the account key signing
everything (it lives in one browser, and enrolment must work from any Admin);
postcard (a dependency, and canonical only by convention).
D-11 Pairing: 128 bits in the code, no PAKE — proposed
An Admin makes the code: 16 random bytes, Crockford base32 (26 characters),
then @relay. It is pasted (sh -s <code>) or scanned, never typed, so it
can carry a full key. HKDF over it gives the mailbox the relay routes on and
one key per message. The new node sends its hybrid public key, a name and a
proof of possession, sealed; the Admin appends the add and replies with the
log, sealed under a key bound to that hello and a fresh salt. The relay sees a
mailbox id, salts and AEAD ciphertext; changing a byte fails the AEAD. One
code admits one key, until an expiry on the Admin's clock; the same hello
again gets a fresh reply and no second entry. Rejected: SPAKE2 for a typed
six-digit code (classical, so a recorded transcript opens to a quantum
computer later; and nothing in the flow is typed); TOFU on the relay's word.
Not covered: a code read off a screen or shell history before use admits the
reader instead, which the owner sees in the device list.
Revisit for codes of words (pairing/typed-code, pairing/backup-code,
planned): a short live code needs a PAKE, used only to authenticate an
ML-KEM exchange, which answers the objection above.
D-12 Grants live in the log; chains narrow them — proposed
A grant is a log entry: subject key, a key-expression scope, rights (read,
write, call) and an optional expiry. Any key can be a subject (an agent, an
MCP door, another person's node), so every principal is a key holding grants.
The holder asks the log may(key, rights, resource, now): the account key and
Admin devices may do anything, a revoked key nothing, anyone else what an
unexpired grant covers. Ungrant and revoke are final. Delegation chains
(seal) stay the offline, short-lived way to pass on part of a grant.
Rejected: roles with fixed permission sets (they widen as features land);
grants outside the log (two sources of truth for one question).
D-13 Content in Loro, code in git, only built code runs — proposed
Why, and what it was chosen over: shell.md, Content and code and
Sharing: tabs first, then your devices.
D-14 A pane is contained to its rectangle; the shell is not editable — proposed
Why, and what it was chosen over: shell.md, Four rings.
D-15 Escapes independent of what they rescue — proposed
Why, and what it was chosen over: shell.md, Escapes.
D-16 The wire and a relay are open; running ours is not — proposed
The wire (relay.md, version 1, frozen), the client, the core and a
reference relay (relay/) are open, and one suite (e2e/relay/client)
holds every relay to the wire. Our relay is closed: it depends on the open
crates and adds what running it takes (limits by plan, metering, abuse
handling, TURN credentials, names on our domain), never a change to the wire;
a wire change lands open, as a new version, first. Hole-punching is the
client's: offers and answers are sealed frames through any relay, STUN is
public, so a direct pipe needs nothing of ours. The value we keep is
operational (a domain on the Public Suffix List, uptime, TURN, support), the
same line as Tailscale's open client and closed coordination server.
Rejected: all of it open (whoever hosts it best takes the business, and
nothing is left to pay for); the wire closed (the client could not honestly
be called open, and can I leave? would be no); hole-punching on our server
(the client does the work either way, and its server side is too small to be
worth keeping). What it costs: ours sees metadata (relay/ours-sees lists
it), and the reference relay must keep up with ours for one account
(relay/reference).
D-17 The log syncs three ways — proposed
Every session carries both sides' log heads and the difference crosses in
it (log/heads-in-session); a mailbox per device at the relay holds new
entries, sealed, until it attaches (wire2/mailbox); short-lived chains end
what never arrives. A holder drains its mailbox and compares heads before it
answers (log/sync-before-serve), and an account may set how stale a holder
may be (log/freshness). Signatures make an entry tamper-proof; sealing
hides the names and grants in it. Rejected: the mailbox alone (a relay could
withhold a revocation; it can delay one here, but a session or an expiry gets
past it); pushing to every device directly (the ones away miss it); asking a
server for the log (a server's word).
D-18 Wire version 2: mailboxes and the relay's key — proposed
Version 1 stays, frozen; version 2 is a new attach context with its own
suite (relay.md). One mailbox serves pairing, messages for devices that
are away, log entries and wake-ups, rather than three mechanisms. The relay
signs its challenge with a key in the log (wire2/relay-signs). Rejected:
pinning certificates (they rotate, self-hosting breaks, and a pin says less
than a key the account chose); trusting TLS at all (a proxy with its own CA
opens it, and sees only what the relay sees, which is why nothing depends on
it).
D-19 A closed browser is woken by Web Push — proposed
A browser node is online only while a tab is open. Web Push (RFC 8291) carries an encrypted payload through the browser vendor's push service to a closed browser; the relay sends it when a mailbox gets a frame for a device that left an endpoint, sealed to that device, so the vendor sees that a wake happened and nothing else. Native phones use APNs and FCM the same way, later. Rejected: a tab kept open; polling.
D-20 Delivering the browser's code — proposed, open
Native releases are signed, the installer checking against a key it
carries, so only the first download is trust on first use. In a browser,
files other than the page are content-hashed and loaded with Subresource
Integrity, and the service worker accepts an update only when it is signed
by the release key. What that can't stop: the page and the service worker's
own script come from the network, and a proxy that can mint certificates for
the origin can replace them (core.md, What isn't promised). What
more limits a page that isn't ours: D-21.
D-21 Native mode, and noticing interception — future
browser.md. A hostile page gets little: the core asks its host to sign
and never holds a key (WebCrypto keys that can't be exported; a TPM, Secure
Enclave or security key), the account key leaves the browser for a passkey
or a native Admin, a browser's delegation lasts hours, its stored bytes are
sealed under its passkey, and widening the account takes a second device.
Native mode takes the network out of the page's source: the page from your
own node on localhost, or an extension, running releases the account
approved in its log. Interception is noticed where something outside the
page can see it: a native node trusting only bundled roots and our CAA
issuers; a challenge bound to the TLS channel where a relay ends its own
TLS; a relay seeing a TLS fingerprint that disagrees with the browser; a
page finding its update unsigned; a node elsewhere checking what our origin
serves. Findings go to the other devices sealed, and the browser stays
locked until a person clears it. Rejected: a challenge from the page to the
server (a proxy that ends TLS forwards both halves); certificate pinning
(browsers removed it); a build per person (a proxy replaces it as easily).
Limit: an attacker who replaces the page before any clean load, without
native mode, still wins.
D-22 The OS's state is docs in three tiers — proposed
devices.md, Three tiers of state. Account state (workspaces, theme, keybindings) is a
doc per kind synced to every device; device state (zoom, which workspace
each screen shows) is a doc per device, synced too and overriding the
account's; the moment's (focus, selection) is presence or nothing. The
schema fixes each setting's tier. Apps are registry components whose state
is docs of their own (app/component). Rejected: one doc for all the
shell's state (a grant on it would be all or nothing, and it would sync at
the rate of its busiest part); settings in browser storage (lost with the
browser, never reach another device); device state kept only on the device
(lost with it, and can't be copied to a new one).
D-23 Files stay files; a Loro doc sits beside them — proposed
files.md. A folder's files are the truth for your tools; a doc beside it
gives sync, history and merging, and a git repo is mirrored from its
working tree, never its store. Code edits sync live only between your own
devices: anyone else's arrive on a fork merged after its diff is seen, and a
change from git is merged at once only when no line was changed on both
sides, otherwise held as a conflict. This narrows D-13 rather than
reversing it: the spike showed same-line edits merging into code that
compiles (645), so nothing merges code silently. History: every change
for a window, an exact cut, thinned checkpoints outside. Rejected:
converting files into docs (breaks every tool, and leaving); whole-file sync
with conflicted copies (loses the edit, not the file); code as a plain CRDT
(D-13's reason, now measured); keeping all history in the doc (only grows).
D-24 A phone runs one app: the shell, laid out for one pane — proposed
shell.md. A phone is one node with one key, so it runs one app, the
shell, as a PWA and later one native app. It shows one pane at a time as a
stack of cards. A tablet or a phone held sideways shows two side by side,
from the same layout tree (D-22: the layout is device state). Asks go in a
strip that no pane can draw on. The terminal gets a row of keys a phone
lacks (Esc, Ctrl, Tab, arrows). A pane opens straight from a link
(each pane has a URL), from the icon's shortcuts, or when something is shared to it.
Rejected: an app per pane, because each home-screen web app on iOS has its
own storage. That would mean a key, a pairing and a revoke for each app,
each app redoing the shell's asks and grants, and an App Store review for
each one.
D-25 One way to someone else's site: a browser in a box on a node — proposed
browsing.md. A site renders in a real browser on a node, in a profile
that is a box of its own, and the pane is a view of its tab: a copy of the
document where there is one, video where there isn't, the node choosing;
pictures first. A site's script never runs on a key-holding origin.
Rejected, each from the prototype, which built them all: framing through a
tunnel at a second hostname (the wrong origin's cookies, and a site D-6
must keep keys away from); a worker in between, rewriting addresses, or a
service worker keeping cookies (each breaks at the same-origin rule); a
cookie jar on a server (half a jar, and every third-party session in one
place); a reader beside it (a view of the same tab instead); a switch
between engines (a framed page can't say it failed, so the person had to
guess); an extension in your own browser (only where installed, never a
phone, and a second authority across the origin boundary). What it costs
is stated in browsing.md: passkeys, calls, a node that has to be on.
D-26 Untrusted code runs in a box whose only way out is the node — proposed
sandbox.md. One service makes every box, as the node's own user: Linux
namespaces, seccomp, a cgroup, and a network namespace whose one interface
is a TUN the node holds, so the node is the gate for TCP, UDP and DNS and
writes the audit outside the box. A browser profile and each instance of
an extension are boxes; an extension's manifest is its grant (D-12).
Rejected: a proxy setting (an HTTP-layer rule; the prototype's browser
WebRTC'd around it); pasta or slirp as they are (they forward everything,
and decide nothing per flow); rootful containers (the first minute is an
ordinary user); seeing inside TLS (a CA of our own is an inspection box).
Open: Ubuntu's AppArmor restriction on user namespaces, measured before
this is accepted.
D-27 Watching the whole node is opt-in, and stopping needs root — proposed
sandbox.md, The rest of the node. Without root the node reads every
socket from /proc/net and raises what it sees; blocking or seeing every
flow is a separate helper installed with sudo by someone who asked, never
in the one line. Rejected: root for every node (the first minute, and a
root node is a bigger prize); trusting a watcher on the machine it watches
once that machine may have fallen (later, a node that is the network's
router or resolver watches from outside).
D-28 Nothing is kept until chosen; a folder is what's kept — proposed
files.md, Open, keep, hold. Opening a file is live collaboration
through the machine it is on, with nothing kept. Keeping is a choice made on
a folder, an account-wide list; holding is each device's choice of which
kept folders it carries and where, including none. Leaving something out
is an ignore rule inside the folder, .gitignore honoured and .git
never synced. Un-keeping deletes nothing. Rejected: keeping whatever is
opened (a glance fills every device and syncs what was never meant to
leave); keeping the whole home folder (builds, caches, secrets); keeping
single files (a project's files refer to each other; a file is left out of
a kept folder instead); every device holding everything (a phone, a
borrowed browser).
D-29 Every caller is a key, and its holder checks it — proposed
access.md. Devices, machines, each service and extension instance on a
node, each MCP client and someone else's node are all keys, and every call
is may(key, class, resource, now) asked by the node holding the
resource. A service's or a client's key is held by its node, which signs
for it, so a service is a caller of its own to other nodes without ever
holding a key (service/no-keys). Resources are key expressions down to a
path; a verb's class (read, write, run, reach) is the holder's manifest's,
never the caller's. A grantee is never a device, so it can't add, grant or
answer an ask. Rejected: a caller named by a string (the prototype's gateway
told callers apart by browser, agent, mcp, and two MCP clients were
one caller); service-level scopes only (a grant on files is every file);
services trusted to confine themselves with no check by the node (a bug is
then a grant); one key per node for everything on it (the far machine
can't tell the MCP door from the files service).
D-30 Ask is part of the grant, and an answer is a grant — proposed
access.md, An ask, from call to answer. A grant carries ask, so
whoever grants decides whether a person is asked, and no grant means no.
An ask is sealed to every Admin device's mailbox and woken by Web Push; a
person answers with a signature bound to the exact call: once, for this
task (a short chain) or always (a grant in the log). Widening answers need
a passkey with user verification. Rejected: ask as a property of the verb
(it puts the decision with whoever wrote the verb, the prototype's first
gateway); a policy doc beside the log (two sources of truth for one
question, which D-12 rules out); approvals only in an open tab (in
the prototype every ask timed out when no desktop tab was open); a classifier
that approves (only a person answers; one may deny or raise); MCP
elicitation as the prompt (the client draws it, and the client is asking).
D-31 MCP is a built-in service, off until settings turn it on — proposed
mcp.md. Every node ships the MCP service, off. One switch in settings
turns it on and makes a client, a key the node holds, with default grants
shown before they're written: read this node's kept folders, write them
under ask, nothing else. The page gives the line for Claude Code, Codex
and any client that runs a command; the command is a stdio pipe to the
service's local socket. Rejected: on by default (a door nobody asked for);
a command that sets it up (setup is choices about grants, which a page
shows and a command hides); HTTP on localhost (DNS rebinding, other
users); the door as a node of its own (it would need a pairing of its own
and a copy of the log, to do what a service on a node already can); one
key for every client (two agents would share every yes). Open: a door for
agents in the cloud, and where it is hosted.
D-32 A node updates itself from a signed, numbered release, when idle — proposed
machines.md, Updates. A release is a manifest of a number and each
build's hash, signed with one hybrid release key whose public half every
node is built with; the node refuses anything unsigned, signed otherwise,
or not newer than itself. It downloads at once and restarts only when no
session has carried anything for three minutes, or after a day, into a
trial the old build watches: a release that doesn't come up within a
minute is rolled back and never tried again. The manifest names its
component, so services and extensions can be released under rules of
their own (D-33); the account approving releases in its log
(browser/approved-releases) adds to our signature, it doesn't replace it.
D-33's wait for a change to the base sits on top of this and isn't built
yet: today every node release is taken once idle.
The core and today's services ship and update as one binary; services
updated on their own, and services that outlive a restart of the node, are
the next step; an extension is released and signed by its publisher, never
in ours. Rejected: trusting the download host (it serves the installer,
but anyone who takes it over would run code on every machine); updating
the moment a release appears (it would drop a shell mid-command); asking
on every machine (a fleet nobody updates stays vulnerable); a package
manager per distribution (one static file covers every Linux, and the
installer needs no root).
D-33 Releases are tiered; the base waits where it can be seen — proposed
trust.md. A small named trusted base (core, access checks, updater,
sandbox boundary); every release reproducible and in a public log before
any device runs it. Services update as soon as they're idle; a change to
the base runs once the account approves it, automatically after 48 hours
in the log with no rebuild disagreeing, or asked each time if you choose;
an urgent base fix skips the wait only with a second release key. Anything
that widens what code can reach waits for a person, and a device undoes a
release that fails on it. Rejected: asking a person for every update (they
can't judge the diff, so it delays fixes and assures nothing); updating
everything at once (one key decides what runs everywhere, unseen); never
updating the base without a person (security fixes stall on the slowest
device).
D-34 There is no "public"; a node faces outward under its grants — proposed
access.md, Nodes that face outward. A site's worker or an agents'
door is a grantee: its grants bound what anyone can get through it, its
manifest says who it serves and the grant page shows that, and it holds a
copy of a pinned version. Writes from outside are append. Rejected: a
public flag on folders (a second way to say who may read, beside grants);
a worker calling through to the machine per request (the site sleeps with
the laptop); asks on outward grants (strangers would page you).
D-35 One renderer, MDX for structure, apps edited as source — proposed
building.md. The editor's renderer builds this site, pinned by the
commit, and CI fails when it and the released editor disagree. Pages' and
apps' rectangles and words are MDX with literal props and nothing that
runs; layout is Stack, Row, Grid, Box; a component made of others
is a file, one with behaviour is code from a release. An app is edited
from a machine's working tree with a preview in a frame of its own, and
reaches devices only as a release. Rejected: the site keeping its own
renderer (the pane and the site drift); full MDX (expressions and imports
are code in a file anyone can edit); editing the running shell (D-14);
visual edits that rewrite code (unreviewed code changes); a package for
other people's sites now (one user, and the contract isn't settled).
D-36 News of a release rides the relay's socket; the page is its own Worker — proposed
relay.md, Release hints and A deploy is a blip. Every node already
holds a hibernating socket to its account's object, so a release is a hint
on it (release <node> <page>, wire 1.3): sent on attach and on a wake,
and, on ours, pushed by publishing, one request per account. The hint only
says when to look; a node fetches and checks the manifest itself, and also
every fifteen minutes from the static files, so a relay that holds it back
delays a node, never strands it. The page and the releases are a Worker of
their own on the origin, serving files before any script runs and handing
the rest to the relay's Worker over a service binding, so publishing never
restarts the relay and a page load stays a free cache hit. Rejected: a
server-sent-events stream (a second connection beside a socket that is
already there); polling alone (the delay is the interval, and a short
interval only moves the cost); one Worker for page and relay (every page
change restarts every account's object and drops every socket); the relay
in front, handing the page its files (every page load would run a script);
routes splitting the origin between the two (they'd have to name every
file path, and the relay's paths are account ids).
D-37 Contain CSS, don't filter it: one document frame — proposed
building.md, Two frames, and any CSS. Pages, published pages and the
browser's copy of a site are drawn in one frame, sandboxed without
scripts, under default-src blob: data:, its DOM written from outside and
its assets ids held as blobs; inside it any CSS is allowed. Code runs only
in a live frame on an origin of its own. The allowlist stays for edits and
for the shell's realm. Rejected: an allowlist as the limit (no design
beyond its list); scoping user CSS to a pane's root in the shell's realm
(url(), fixed positioning and selectors leak or escape unless every one
is caught); loading public assets straight from the page (the prototype's
mirror does, so a page's CSS can reach the internet from the shell's
origin).
D-38 The remote desktop is a headless shell of the user's own — proposed
machines.md, The desktop. youros-desktop, beside the node, starts
gnome-shell --headless as the user on a private D-Bus, with no logind
session, and the pane is that desktop. The screen at the machine is shown only on request, and only while
it is unlocked. It needs no root, and works whether the machine is
unlocked, locked or logged out. Rejected:
- Mirroring by default, with an extension that keeps casting through the lock. Remote access then reaches past a screen somebody locked.
- A root helper starting a logind session. It needs root, PAM and seat handling, and the physical display path is where an earlier one lost days.
- GNOME Remote Desktop. RDP, with credentials of its own beside the account's grants, and no browser client.
- A
gst-launchchild. A black box, whose watchdog guessed from silence. - Video on the ordered reliable pipe. One lost packet holds up every frame behind it.
Later — not promised yet
Each fits without changing the five concepts.
- Publish a note: a button on a note or folder that grants its published version to a hosting node we run (D-34), md and mdx first.
- Someone else's your.os: another account's devices, peer to peer, holding finely scoped grants on yours (a grantee whose chain starts at their account); how their keys reach your log, and how far you trust their account's revocations.
- Levels: a symmetric profile for weak devices (PSK at enrolment, ratchet), fixed at enrolment; a delegation's minimum level.
- Lossy links (serial, BLE) behind a reliability adapter; a device behind a plaintext hop as a resource of its gateway.
- Mesh: a pipe that reaches many keys (zenoh with opaque key expressions), a hop limit; never dynamic routing in the core.
- Resumption without the KEM after a session has ended.
- Pub/sub with a content key per subtree wrapped to readers.
- Zero copy across the service boundary (shared memory).
- Bridges: zenoh/ROS 2, Matter, Meshtastic.
- Onion pipes: a Tor onion service (arti, in Rust) as a pipe; no relay learns who talks to whom, at Tor's speed.
- Someone else's relays: Nostr relays as a fallback carrying
{to, ciphertext}when every your.os relay is down. - MoQ relays: WebTransport to the edge, once the spec settles (D-9).