Status: built (V1 — all phases). A bounded rolling buffer records every propagation hop, and
GET /admin/api/observatory/stream (WebSocket) + GET /admin/api/observatory/events (JSON) serve it
under the console’s operator session. The Mycelium Observatory screen that visualizes this stream
ships in the console build: the server embeds and serves the console at /admin behind the
default-off embed-console packaging feature. Recording is enabled by default in the dev profile,
off by default in production (opt in explicitly).MemoryDiff diffuses hop-by-hop across the
mesh under an energy budget rather than being fetched by a query. The Topology Observatory is the
instrument that makes that visible: it records each hop a diff takes — where it went, what it cost, and
why it stopped — and streams that to an operator, replaying the recent past and then tailing live.
It is a read-only view. The Observatory never touches the mesh it watches; with observation
disabled the gossip walk is byte-for-byte identical (a load-bearing invariant — the tool cannot perturb
the system it measures).
What it records
Every propagation hop becomes one content-free event. The event carries the shape of propagation — never the memory’s content, embedding, or payload:
The
outcome is the story of a propagation’s edge: delivered reached a new neighbour, deduped hit a
node that already had the diff, pruned failed the relevance gate, exhausted ran the energy budget to
the floor.
Authentication and tenant scoping
The Observatory rides the console operator session (the same OIDC login as the admin console), not thex-hyphae-key data-plane key — see Authorization. Two authority
levels, and the tenant boundary is enforced on every event on both the replay and the live tail:
- A service admin sees propagation across all tenants.
- A project admin sees only its own tenant’s events. It can never observe — or even infer the existence of — another tenant’s traffic: a cross-tenant event, and every id derived from it, is filtered out before it can reach the socket. This is a hard isolation guarantee, not a display filter.
401 before the WebSocket upgrade; an authenticated
non-admin is 403.
The stream endpoint
1
Replay the buffered window
The recent past, oldest-first, as JSON event frames. Pass
?since=<rfc3339> to replay only events
newer than a watermark; omit it to replay the whole retained window (the scrub-back “time machine”).
A malformed ?since is a clean 400 — no upgrade.2
Tail live
After the replay drains, every new propagation streams as it happens. If a slow consumer falls
behind, the server sends a
{"resync":true} marker instead of silently dropping events — reconnect
with ?since=<last-seen-ts> to close the gap.max_concurrent_streams, default 16); a connection over the cap is
refused with 429 before the upgrade.
The snapshot endpoint
For scripts and dashboards that want a one-shot pull instead of a live socket:limit), under the same auth and
the same tenant filter as the stream.
Configuration
Theobservatory config section (profile-derived defaults):
The buffer is bounded by both count and age and never blocks the propagating walk: if the recording
channel saturates, events are dropped and counted, never queued unboundedly.
sample_rate is the
release valve for a busy production mesh.
Observability
The recorder and stream emithyphae.observatory.* metrics — see the metrics
reference: