Modules
bloccs_web — a self-hosted, real-time dashboard for running bloccs networks.
The default Bloccs.Web.Resolver — the free, open baseline.
The dashboard's own OTP application. Starts a private Phoenix.PubSub (so the
dashboard never has to share the host's) and the telemetry Collector that
folds the [:bloccs, …] stream into per-network rolling windows.
Serves the dashboard's own precompiled app.css / app.js from
priv/static/assets, so the host needs no Plug.Static configuration and the
bundles can't collide with the host's own assets.
A tiny server-rendered SVG throughput chart for the Messages panel: a filled
area for total events/second with a red overlay line for failures. No client
charting library — the series is computed by Bloccs.Web.Telemetry.Flow and
redrawn each frame.
The shared topology SVG: places one <.hex_glyph> per node and one bezier
<path> per edge from a server-computed Bloccs.Web.Topology.Layout. Used by
the topology panel (live node state) and the coverage panel (reached/unreached
overlay). Pure rendering — no data loading, no layout math.
Small, self-contained UI primitives for the dashboard (status pills, metric
badges, the Pro lock). Deliberately minimal and dependency-free — the
dashboard ships its own styling in priv/static and never assumes the host's
component library.
Structural coverage for the dashboard, computed from the runtime
Bloccs.Introspect.Network (so it needs no parsed manifest). Mirrors
Bloccs.Coverage's obligation model — every in-port, out-port, and edge — and
compares it against a reached set derived from Bloccs.Trace events
(recorded live or loaded from a .bloccs-trace file).
The single LiveView behind every dashboard panel. live_action selects the
panel (:networks, :topology, :metrics, :coverage) — the oban_web
pattern — so navigation never remounts.
Small, dependency-free formatting helpers for the dashboard: human durations, counts, rates, and percentages. Pure functions, easy to unit-test.
The bloccs hexagon notation as inline SVG.
Self-contained root and app layouts for the dashboard. The dashboard ships its
own precompiled CSS/JS from priv/static (served by a dashboard-owned static
route), so these layouts never depend on the host's assets or layout.
Panel 4 — structural coverage. Records a run (or loads a .bloccs-trace),
derives the reached obligations with Bloccs.Web.Coverage, and overlays them
on the topology graph (reached nodes/edges lit) alongside a summary bar and the
list of unreached obligations. Trace export sits behind the :trace_export
feature (the Pro seam) — enabled in the open build.
Panel 5 — packages moving through the network. A live throughput chart over the
per-second Bloccs.Web.Telemetry.Flow buckets, plus a scrolling feed of recent
message events: each edge a message crossed (from.port → to.port), its
outcome, the emitting node's latency, and — when Bloccs.Inspect capture is
enabled (bloccs 0.3+) — a bounded, redacted snapshot of the payload.
Filterable by node and outcome.
Panel 3 — live per-node metrics. Renders one row per node from the latest
collector frame (throughput, p50/p95 latency, completed, error rate) with a
state pill. The frame arrives on a 1 Hz PubSub tick handled by
Bloccs.Web.DashboardLive; idle nodes show "—" until traffic flows.
Panel 1 — the list of every running network (Bloccs.Introspect.list_networks/0),
each row linking into its topology. Pure presentation; data is loaded by
Bloccs.Web.DashboardLive and passed in.
Panel 2 — the network graph drawn in the bloccs hexagon notation. The layout
is computed server-side (Bloccs.Web.Topology.Layout) and rendered as a single
SVG: one <.hex_glyph> per node, one cubic-bezier <path> per edge. Live node
state (states[node_id]) is an assign-driven CSS class on each glyph — no
client animation. P4 feeds states; in P3 every node is :idle.
Builds dashboard URLs from the mount base path (e.g. "/bloccs"), which the
router macro stashes in the session. A library can't use the host's ~p
verified routes, so paths are assembled here from one source of truth.
The integration seam between the dashboard and the host application: who is looking, what they may see, and which features are enabled.
Router helpers for mounting the bloccs dashboard into a host Phoenix app.
The single sink for bloccs telemetry. Attaches Bloccs.Web.Telemetry.Handler
to the [:bloccs, …] stream and folds it into two per-network views
The pure core behind the Messages panel: a bounded record of messages moving
through a network. Each event is one edge traversal (a [:bloccs, :emit]
correlated with the emitting node's outcome and latency) or a failure/drop.
Attaches to the [:bloccs, …] telemetry events and forwards normalized data to
the Bloccs.Web.Telemetry.Collector. Runs in the emitting (Broadway) process,
so it does the minimum — normalize and cast — and never blocks the pipeline.
The pure functional core of the metrics collector: folds normalized bloccs
telemetry into per-node rolling windows and renders a snapshot. No processes,
no clock of its own — now (monotonic ms) is always passed in, so the whole
thing is deterministically testable with synthetic events.
A pure, deterministic layered layout for a network's DAG — the server-side alternative to a client layout library. Each node is placed in a column by its longest path from a source, and in a row within that column; edges become cubic-bezier paths between the right and left faces of the hexagons.