bus-conformance.md audits the flybus crate against bus-v1 sections 2 to 11, one row per normative sentence: requirement, status, code location, the test that proves it. 195 rows, 177 conforming, 10 deviating with the sentence that allows each, 1 must-fix (the teardown starvation, fixed in this branch) and 7 not implemented with an owner named. It also maps every BUS-01/02/03 acceptance bullet to its test, reconciles all ten of the crate's own differences from the draft, records the frame measurement with the reasons it is not a capacity claim, and lists the two contradictions inside the draft it will not guess at: the per-client queued byte budget against the latest-mode guarantee, and section 2's call budget against section 6's client-owned deadline. Neither changed any code. bus-v1 gains section 12: dated amendments for the three error codes the implementation needs and the draft left unnamed (CONFLICT, NO_TOPIC, ARTIFACT_MISMATCH), one line of reason each, and for the one operation it adds (rpc.responder.release), which is how bounded call correlation ends when a handler keeps reply authority after releasing the request delivery. Section 9's error list is inclusive, and section 4 already provides for a digest change. The crate README points at the report, carries the new measurement summary in place of the old numbers, and describes the two new test files; the design index and the flybus index point at the report too.
74 lines
4.3 KiB
Markdown
74 lines
4.3 KiB
Markdown
# flybus: the communications bus
|
|
|
|
Status: **crate landed, nothing wired onto it**. Written 2026-09-22. Index only; the
|
|
authority for the API and the wire format is the crate's own
|
|
[README](../../services/flysim/crates/flybus/README.md), and the audit of the crate against
|
|
the draft is the [conformance report](session-framework/bus-conformance.md).
|
|
|
|
## What it is
|
|
|
|
`flybus` is a local RPC and pub/sub bus for Tokio processes on one host, with immutable
|
|
file-backed artifacts for large payloads. One library, one router, one wire protocol:
|
|
messages are small strict-JSON envelopes carrying metadata and artifact references, while
|
|
bulk bytes (frames, audio, spike bitsets) live in a store directory the router owns.
|
|
Ownership follows deliveries and explicit holds; the router moves messages and tracks
|
|
ownership and does not interpret them. It implements the Flybus v1 draft (`bus-v1`, draft 1
|
|
of 2026-09-18) over the `ipc-v1` scalar encodings.
|
|
|
|
Transports are an in-memory pair, an accepted `AsyncRead + AsyncWrite` stream, or a Unix
|
|
socket. Identity is bound by the launcher before Hello and checked against a `Policy` of
|
|
per-client grants; open/unbound mode is for trusted tests only and is not authentication.
|
|
|
|
Nothing in the crate is specific to a game, a brain or a stream.
|
|
|
|
## What it is meant to replace
|
|
|
|
Today the three processes talk over two ad-hoc loopback surfaces:
|
|
|
|
| Today | Under the bus |
|
|
| --- | --- |
|
|
| Feed: WebSocket `127.0.0.1:7400/feed`, one binary message per snapshot at 30 Hz, header plus RGBA frame, audio and spike attachments, re-serialized per consumer | One `latest`-mode topic per stream, with the frame as a sealed artifact shared by fan-out instead of copied per subscriber |
|
|
| Control: loopback HTTP `127.0.0.1:7401` (`/stimulate`, `/chat`, `/checkpoint`, `/pause`, `/status`, ...) | RPC services with per-client grants, FIFO dispatch, explicit cancel states and backpressure |
|
|
| Per-surface limits, rate limits and timeouts written twice | `Limits` and `Policy` in one place, negotiated at Hello |
|
|
|
|
The feed and control contracts in [feed-protocol.md](../feed-protocol.md) and
|
|
[control-api.md](../control-api.md) stay binding until a migration replaces them. The bus
|
|
does not change any published contract by existing.
|
|
|
|
## Crate layout
|
|
|
|
`services/flysim/crates/flybus`, a workspace member of the flysim workspace; no other crate
|
|
depends on it yet.
|
|
|
|
| Module | Contents |
|
|
| --- | --- |
|
|
| `wire` | Scalars, strict JSON, `Envelope`, `ArtifactRef`, `Attachment`, `Location`, framing, `CONTRACT` and `contract_digest()` |
|
|
| `error` | `ErrorCode`, `Dispatch`, `BusError` |
|
|
| `limits` | `Limits` and its hello encoding |
|
|
| `policy` | `Policy`, `Grants`, `Pattern` |
|
|
| `router` | `Router`, `RouterConfig`, `RouterStats`, `UnixListenerHandle`; the state machine in `router/state.rs` |
|
|
| `client` | `Client` and the handle types |
|
|
| `store` | The router-side file store and client-side location resolution |
|
|
| `transport` | `Transport` and the `Stream` trait |
|
|
|
|
Dependencies are already in the workspace lockfile: `tokio`, `serde`, `serde_json`, `sha2`,
|
|
`libc`. Tests run every integration case twice, once in memory and once over a Unix socket:
|
|
wire negotiation, RPC authority and cancellation, pub/sub credits and retention, artifact
|
|
allocate/seal/read with quotas and router restarts, plus the conformance suites and an
|
|
`--ignored` perf measurement.
|
|
|
|
## Wiring still pending
|
|
|
|
- **flysim publisher.** Router startup inside the sim service, a store root under its
|
|
runtime directory, and snapshot publication as artifact plus header envelope.
|
|
- **flysim control services.** The control endpoints as RPC services with grants, so the
|
|
"no button endpoint" structural guarantee is expressed as a grant table.
|
|
- **Stage and bridge clients.** Both are TypeScript/Node; the crate is Rust only, so either
|
|
a binding or a thin translating edge process is required before they leave the WebSocket
|
|
and HTTP surfaces.
|
|
- **Sizing.** `max_store_bytes`, `max_retained_bytes` and `max_latest_in_flight` need values
|
|
chosen for 1.2 MB frames at 30 to 60 Hz with a slow consumer, not the defaults.
|
|
- **Lifecycle.** Orphaned store directories are cleaned only when a new router starts on the
|
|
same root, so service restart order and the store root's location need a decision.
|
|
- **Migration order.** The feed is the cheaper first move; control should follow only once
|
|
the bus carries the feed in production for a full session.
|