What runs since 2026-10-04 and what its first live use showed: refused requests as timeouts, a late machine reading the whole set, the partial secrets guard; the agent module and the licence manager on every machine.
3.4 KiB
3.4 KiB
layer, status, code, updated, decisions
| layer | status | code | updated | decisions | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| as-is | implemented |
|
2026-10-04 |
|
A module's state, as it runs
A module keeps the current value of something on the bus, and every machine sees it — including one
that joins later. Since 2026-10-04 a manifest may say state (buckets the module owns) and reads
(another module's, as <module>.<name>). The first two modules to use it are the operator's agent on a
machine and its licence manager; on the day this was written, three buckets existed on the bus.
What runs
- The controller creates a key-value bucket
<module>_<name>for every declared state, from the catalogue — on every start and, since the first module that declared state found it missing, on every push before the memberships that name it. A bucket nothing declares any more is reported and kept. Every bucket carries the mesh's caps: 256 KiB a value, 64 MiB a bucket. - The grants: the machine's runtime is granted, for each bucket a module it carries owns, writing under the bucket's own subjects and reading; for a bucket it only reads, reading. Measured once built, with the composed grants loaded into a server: a reader's write is refused by the server.
- The membership issued to each assignment lists its buckets by the names the module uses, and whether it may write.
- The runtime answers
mesh/state.get,put,delete,keysandwatchon the bundle's channel. A watch hands the current values — none that is deleted — then every change, each naming the watch it belongs to; it is answered once the current values are delivered. The runtime refuses, with the reason, a state the module was not issued, a reader's write, a key the bus cannot hold, and a value carrying a field named like a credential. - The SDKs:
state(name)in TypeScript,stdio.State(name)in Go (taggo/v0.1.7and later).
What the first live use showed
- A refused request is a timeout, not a refusal. The bus reloads a machine's grants a moment after the push that changed them; a bundle that asks in between waits out its deadline. A module that watches at start therefore watches beside its handshake and asks again until the state answers — the agent module needed two to seven attempts on its first start on each machine.
- A late machine reads the whole set. A server registered for every machine before one machine was assigned the module reached that machine from the current values at its start.
- The secrets guard is partial and works for what it covers: an entry carrying an
Authorizationheader was refused on the live bus. A sealed value is plain text to an inspector, and is not caught.
How it is checked
The controller's catalogue and broker tests (names, grants, memberships, a bucket asserted in place
against a real server); the runtime's tests over a real bus (current values without deletions, refusals,
the TypeScript SDK through the runtime); module check names a read whose owner on the shelf keeps no
such state.