swactor/crates/dashboard
Zachery Aaron Shores-Chmielewski c42bf5e983 demo: rename xtask demo command; dashboard-established data-plane edges
Rename `cargo xtask provisioning-reconciler-demo` to `cargo xtask demo`
(CLI dispatch, help, child re-exec argv, launch spec strings, module dir
xtask/src/provisioning_demo -> xtask/src/demo).

Add iteration-1 data-plane edges, established from Fleet Control:

- Fleet Control "edge" button -> POST /control/edge (new
  ControlCommand::EstablishEdge) -> supervisor actor resolves the node's
  advertised EndpointAddr (stashed in NodeRuntime by AnnounceActor) and
  provisions a real outbound EdgeRuntime (arena ring lease, recorder
  WorkerPort, EDGE_ALPN send pump) in a new edge pump thread.
- Node gains EDGE_ALPN, an actor bridge decoding EdgeProvision gossip,
  and a NodeEdgeAgent that provisions its (single) inbound edge, polls
  it, mirrors observations onto the node.edge telemetry channel
  (render-only), and answers EdgeAck gossip which terminates the
  supervisor's provision retries. Node teardown replaces its inbound on
  re-provision; supervisor replaces sessions per node and tears them
  down on node exit/replacement/shutdown.
- The edge pump runs on the engine's blocking pool with sole session
  ownership (commands in, state mirror + feed lines out): the connect
  handshake blocks its thread and must not run on a Tokio worker or
  share a lock with the actor. Connects are bounded (10s) so a dead
  node faults its session instead of wedging edge polling.
- iroh-driver: retain_telemetry_connections() opts an application out
  of the driver-owned TELEMETRY_ALPN ingress so the node's pull server
  can drain those connections itself (the actor-bridge pump would
  otherwise claim them).
- Dashboard: edges array in the reconciler snapshot, per-node edge
  badges and edge button in Fleet Control, node_edges render mirror.
2026-08-17 00:11:20 +04:00
..
src demo: rename xtask demo command; dashboard-established data-plane edges 2026-08-17 00:11:20 +04:00
.gitignore feat: stability for deployment and distribution (#44) 2026-02-19 14:39:33 +00:00
AGENTS.md feat(dashboard): fused control-plane view with unified navbar and stale pooling 2026-08-16 02:42:40 +04:00
Cargo.lock refactor: datastream crate is now telemetry 2026-08-15 12:18:56 +04:00
Cargo.toml feat(xtask): provisioning-reconciler-demo with live fleet control 2026-08-15 18:11:33 +04:00
README.md feat(dashboard): fused control-plane view with unified navbar and stale pooling 2026-08-16 02:42:40 +04:00

dashboard

Read-only HTML/SSE dashboard over incoming telemetry frames.

The crate owns the Axum server, bounded raw frame window, and view registry. Component crates can keep their own view implementations beside their code and register them through DashboardHandle::register_view. The built-in control-plane view is hosted here because worker/actor/message processing is universal to swactor programs.

The control-plane page fuses machine stats and actor stats per node stream: node cards (CPU/GPU/net + actor rollup) → per-node actor roster → per-actor dossier (identity, message diet, sampled message history). The Rust type name is the actor's display name; the address is the unique key. Stale streams (silent beyond the liveness window) render in a separate collapsed pool, superseded life generations are evicted immediately, and the stale pool is hard-capped.

Routes

  • GET / — fleet control plane (home; same page as /view/fleet)
  • GET /events — raw incoming frames as SSE
  • GET /api/frames — recent raw frame window
  • GET /api/views — registered view metadata
  • GET /view/telemetry/live — generic live explorer over retained and incoming telemetry frames
  • GET /api/view/telemetry/live — bounded per-stream/channel explorer snapshot
  • GET /view/fleet — fused control-plane page (machine + actors per node)
  • GET /api/view/fleet — live/stale pools with per-node machine and roster snapshot
  • GET /api/view/fleet/detail?stream=<node#life>&actor=<addr> — bounded per-actor dossier detail (diet, history, sampled receipts)

Every page carries the unified top navbar, built from the view registry at serve time — pages include a <!--swactor:nav--> placeholder and the server substitutes the links, so app-registered views appear automatically.

All state is derived from observed frames. The dashboard sends no control signals back to producers.