The architecture
The architecture, drawn
Every component, every hop, and which of them holds state. The rest of this section assumes this page; read it once and the runbooks stop needing prose to explain where a request is.
The whole picture
Drawing the diagram…
Three properties fall out of this, and they are what make it operable:
| Property | Consequence |
|---|---|
| Only the beam host is exposed | No inbound route to an installation, no certificate on it, no port to firewall |
| The beam host holds almost nothing | Tunnels are in memory. Losing the host interrupts access and loses no work |
| An installation holds everything | Its volume is the thing to back up, and the thing an upgrade must not touch |
What is state, and what is not
Drawing the diagram…
The settings directory and the database are one unit
Restoring half of them produces a state that never existed: a database whose sessions reference a signing secret that is gone, or settings pointing at conversations that are not there.
Back the blob index up with the bodies
Each store keeps a small JSON index beside its blobs, and that index is the manifest. Nothing rebuilds one by scanning, so an index lost without a backup orphans the bodies behind it.
Connecting: the dial
The installation dials out. The host judges the credential before the upgrade, so a wrong token is a 401 rather than a socket that closes for no stated reason.
Drawing the diagram…
Who gets a slot somebody is on
Drawing the diagram…
The same machine restarting is the reclaim case, and it is why a restart no longer knocks itself off the air. POST /api/beam/takeover is the only path that displaces anybody; it is the Take the slot button. Saving beam settings does not take a slot.
A refusal only makes an installation wait when somebody named its slot. With the slot left empty, an installation whose credential opens any slot (the host says so as anySlot) moves down its own list: default, then <machine>, then <machine>-<id4>. It keeps the one it connected on. A process pinned to a non-default profile by the environment, which is every dev task, starts at <machine>-<profile>. Use slot is the same move on a person's word (mechabedo ADR 511).
An empty installation id never matches an empty one, so two installations too old to carry one are two machines rather than one restarting.
A request, all the way through
Drawing the diagram…
Two things in that path are worth an operator's attention:
- The installation compresses, not the host. Response bytes go installation to host to browser, so the slow hop is the installation's own uplink. The host and the tunnel carry opaque bytes and neither had to learn anything about it.
- An event stream is never compressed, because the compressor would buffer across exactly the flush boundaries the tunnel preserves one frame at a time.
Why one big transfer does not stall a terminal
Sending is metered per channel, not per socket.
Drawing the diagram…
The receiver hands credit back as its own consumer drains, so only the channel that ran out waits. Credit is negotiated by feature name on hello, not by the protocol version, so a host and an installation of different vintages still connect and simply fall back to the socket-wide gate.
channels settles back to zero between exchanges. A count that only grows is a leak while it is happening, which is why it is on /__beam/slots at all.
Liveness, from both ends
Drawing the diagram…
A WebSocket client can set no idle timeout, so the installation watches for silence instead. Without it, a blackholed route left the installation believing it was connected until OS keepalive fired, about two hours later.
The vitals ride the pong the host was already sending, so a near-live reading of every slot costs no frame of its own. That is what /__beam/slots reports.
The auth gate
A desktop is permissive locally and must not be over a beam. The gate is one decision, made from how the request arrived.
Drawing the diagram…
/api/health reports beam: true for a forwarded request, and auth.enabled: true with it, so the page skips the local logins rather than trying one that cannot work.
One operator at a time. One installation carries one seat. A login arriving while somebody is driving is told who, rather than quietly becoming the second. An idle holder hands over without being asked; an active one only when the caller said takeover.
Two installations, peering
An agent in one installation reaching an agent in another goes through the host, because the host is the only party that can say who called.
Drawing the diagram…
Nothing of the caller's request is forwarded, and the host strips x-beam-peer-from from every browser forward, so the only way an installation sees that header is that the host put it there.
A remote reach is exactly a local one and no wider: no shell, no file, no other /api path.
Logbook sync
Several installations converge on one archive without any of them trusting the host with plaintext.
Drawing the diagram…
| Fact | Detail |
|---|---|
| Tenancy | A slot token is a sync tenant, slot:<name>. One credential covers the tunnel and the sync |
| Expiry | A sync blob has no TTL by design. Two installations converge on whatever the host holds, so expiry would mean one of them re-uploading forever |
| The bound | BEAM_MAX_TENANT_BYTES. Over it, an upload answers 507 and that installation's pass counts one failed session and carries on |
| The dataset | Plaintext, opt-in per installation, and the only thing on the host that exists nowhere else |
Where a failure shows up
Drawing the diagram…
Every row here is expanded in Running a beam host.
Next
- Cloud agentic workspaces - this shape, provisioned as a fleet
- Running a beam host - sizing, the proxy, the secrets, the watch list
- Running mechabedo as a server - the volume, capacity, backup and restore