Belay.Dashboard (Belay v1.0.0)

Copy Markdown View Source

An embedded web dashboard with zero dependencies — no Phoenix, no Plug, no JS build. One child spec:

children = [
  {Belay, name: MyApp.Belay, ...},
  {Belay.Dashboard, belay: MyApp.Belay, port: 4004}
]

Then open http://localhost:4004 — live queue tiles, a filterable job list, a job drawer with the full journal (steps with costs, events, errors, children), a rendered workflow DAG, and operator actions: retry, cancel, signal, and steer.

Options:

  • :belay (required) — the instance name
  • :port — default 4004 (0 picks an ephemeral port; see port/1)
  • :bind — default {127, 0, 0, 1}; bind {0, 0, 0, 0} only behind a proxy you trust
  • :token — when set, every request must carry it (Authorization: Bearer <token>; ?token= is accepted only for GET requests so browser EventSource can authenticate)
  • :authorizer — gates the mutating endpoints exactly like the MCP server's authorizer: authorize(tool, args) -> :ok | {:error, msg}

Mutations are disabled by default. Configure either :token or :authorizer to enable them. Mutating requests must use JSON and, when an Origin header is present, it must match the request's Host header.

The server speaks plain HTTP/1.1 over gen_tcp with Erlang's built-in request parsing; live updates stream over SSE. It is an operator tool: no TLS (front it with your proxy for remote access) and one connection per request.

Summary

Functions

The port the dashboard is listening on (useful with port: 0).

Functions

port(pid)

@spec port(GenServer.server()) :: :inet.port_number()

The port the dashboard is listening on (useful with port: 0).