ADR-0007: Dashboard API Architecture for Multi-Repo Scoping¶
Status: Accepted Date: 2026-02-28 Enforcement: enforced Enforced by: pytest:tests/test_dashboard_routes_repo.py
Context¶
The dashboard routes (dashboard_routes.py) use a closure-based pattern where
all endpoints are defined inside create_router() and share config, state,
event_bus, and orchestrator via closure variables. This design assumes a
single repo context per dashboard instance.
Multi-repo lifecycle is managed by src/repo_runtime.py (RepoRuntime /
RepoRuntimeRegistry) inside a single server:main process; repos are
started/stopped through the dashboard control routes rather than a separate
subprocess per repo. (Historically this was a TCP supervisor layer —
supervisor_service.py / supervisor_client.py — that spawned one subprocess
per repo with its own dashboard port; that layer has since been removed. The
API-scoping decision below is unchanged by that refactor.)
The UI context (HydraFlowContext.jsx) already tracks supervisedRepos and
exposes addRepoShortcut / removeRepoShortcut. Sessions support repo
filtering via state.load_sessions(repo=repo).
The key gap: operational endpoints lack ?repo= scoping, and there are no
per-repo start/stop/status endpoints at the dashboard level. A user viewing the
dashboard sees only one repo's data with no way to switch or aggregate.
Decision¶
Extend the dashboard API to support multi-repo scoping through two mechanisms:
-
Query parameter scoping: Add optional
?repo=<slug>query parameters to operational endpoints (/api/pipeline,/api/sessions,/api/metrics,/api/workers). When omitted, the response covers the current repo (backward compatible). When provided, the dashboard proxies or filters to the specified repo. -
Repo management endpoints: Add dashboard-level endpoints for repo lifecycle operations:
GET /api/repos— list managed repos with status (already exists via supervisor polling)POST /api/repos/{slug}/start— start a repo runtimePOST /api/repos/{slug}/stop— stop a repo runtime-
GET /api/repos/{slug}/status— per-repo health and pipeline state -
WebSocket scoping: Extend the existing WebSocket connection to accept a
repoparameter, allowing the frontend to subscribe to events from a specific repo or all repos.
Consequences¶
Positive: - Dashboard becomes repo-aware without breaking existing single-repo deployments. - Frontend can switch between repos or show aggregated views. - Repo lifecycle management moves from CLI-only to dashboard-accessible.
Trade-offs:
- Proxying to per-repo dashboard ports adds latency and complexity.
- WebSocket multiplexing for multiple repos requires message routing logic.
- Backward compatibility constraint means ?repo= is optional, adding
conditional paths in every endpoint.
Alternatives considered¶
- Separate dashboard per repo with a meta-dashboard aggregator. Rejected for initial implementation: adds operational complexity. May revisit for large-scale deployments.
- Embed repo awareness directly in
create_router()closure. Rejected: would require the single dashboard process to hold state for all repos, breaking the subprocess isolation model. - Use the supervisor TCP protocol directly from the frontend. Rejected: exposes internal protocol to the browser and requires a WebSocket bridge anyway.
Related¶
- Source memory: #1617
- Implementation: #1468
src/dashboard_routes/_routes.py:create_router,src/dashboard.pysrc/repo_runtime.py:RepoRuntime,src/dashboard_routes/_state_routes.py— per-repo start/stop/status control routes (replaced the removed supervisor TCP layer)src/ui/src/context/HydraFlowContext.jsx- ADR-0006 (RepoRuntime Isolation Architecture)
Council Amendment Notes¶
The following amendments were generated from council feedback:
- Architect: The ADR is structurally sound and complementary to ADR-0008 (Multi-Repo Dashboard Architecture), which does not supersede it, but
- Pragmatist: ADR-0007 defines the API contract layer (query-param scoping, endpoint signatures, WebSocket
- Editor: The Architect's evidence that ADR-0008 (Multi-Repo Dashboard Architecture) explicitly references ADR-0007 as a prerequisite settles
These notes are intended to be incorporated before final acceptance.