Files
hq/01-RESEARCH/036-everything-over-nats/02-utopia.md
T
jochen 5e9a27a6a3
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
Research 036: measure where the mesh talks around the bus, so views can be built from it
2026-10-08 15:28:57 +02:00

82 lines
4.4 KiB
Markdown

# 036 — The target: a mesh that happens on the bus
This is where the gaps in [01-evidence.md](01-evidence.md) point. It is a picture to test proposals
against, not a design. Each paragraph names the gap it answers.
## Every link between modules is a subject
A module owns its state: its files, its database, its container. It is reached only by its tools, its
seat's verbs, its events and its buckets.
- **No module acts on another's container, socket or files.** A store module serves its own dump. The
registry says what it holds. The resolver's verbs are called over the bus like any other seat's. A
download client answers whether it is reachable with a key (G5).
- **Every act is grantable.** Because every act is a subject, the bus can refuse it, and the controller
can say who may perform it.
The bus is not for bulk bytes, and two kinds of traffic stay off it by name:
- **Bulk bytes stay where they are.** The bytes of an artifact and of a git repository, and an app
using its database, keep their own protocols.
- **Who reaches them is decided on the bus.** Where to reach them is a provision, and what exists is
announced on the bus (G4).
## Every important state is watchable
For each thing a person would look at, the owner keeps three things on the bus:
1. **A bucket** of current state, one key per thing: a node, an assignment, a plan, a build, a
delivery, a setting, a licence, an open ask.
2. **An event** for each change, naming the thing and what changed. Another module can consume it, and
a view can redraw from it.
3. **A history stream**, where the past matters, with a retention the owner declares (G8).
The store remains the owner's record where it needs one. The bucket is written from it on change, never
instead of it. The open conditions already work this way. Plans, builds, nodes, assignments, settings
and licences come next (G2, G6). A verb is still how something is asked or done. It stops being the
only way to see.
## Views are built from the bus
A view is a web page or a terminal UI that shows part of the mesh. *View* is proposed here as the
glossary word for this. It has no backend of its own:
- **It connects** to the bus over WebSocket, through the proxy, as the person using it.
- **It reads** the buckets it shows, watches them, and subscribes to the events that explain a change.
- **It acts** by calling the same tools and verbs an agent calls. A decision travels as an answer to
an ask, carrying its proof, and the controller checks it (the approval flow, §6 of the evidence).
The person is admitted by an **auth callout** served by a mesh module. That module checks the person's
login with the mesh's identity provider and issues a short-lived bus user. The user's grant is derived
from the view's declaration: these buckets to read, these events to hear, these tools to call. No
password is written into the server's file for a person, and a person's access ends when the credential
expires (G1).
## The bus survives a machine
Every machine runs a **leaf node**:
- **Local traffic stays local.** A module's connection is local, and tool calls between modules on one
machine keep working when the hub is away, as they must on a laptop behind a VPN client.
- **What must not be lost is replicated.** The control-node's server is one of three in a cluster, and
the declarations, the control stream and the controller's buckets are kept on three disks rather than
one. The nightly snapshot remains the guard against our own mistakes, not against a disk (G3).
## The bus watches itself
- **Server events become conditions.** The `nats` module holds a system-account user and turns the
server's own events into conditions, like any other probe: a slow consumer, a permission refused, a
client reconnecting in a loop, a consumer that nothing feeds.
- **Exhausted messages are kept.** A message delivered as often as allowed lands in a dead-letter stream
that a view can show (G7).
- **Nothing to rescue by paging.** Answers stay within one message because views read keys, not
whole lists (G9).
## What is not wanted
- **No view with a database of its own** that copies the mesh's state. That copy drifts, which is the
thing the mesh exists to prevent.
- **No HTTP API on the controller beside the bus** (G10).
- **No second signing hierarchy** for its own sake. The callout issues users under the account the mesh
already has, unless a separate account for people turns out to be the simpler grant.