Frontend Requirements¶
Requirements distilled from design-iteration conversations. One requirement per bullet. Refines and extends docs/SAD.md Β§7 "Dashboard Frontend (MVP)".
Functional¶
Views¶
- The dashboard provides two views β Matrix and Swimlanes β switchable via a top-nav segmented control.
- The Matrix view renders deployments as a services Γ environments grid with rows = services and columns = environments.
- The Swimlanes view renders deployments as per-service DAGs with one horizontal swimlane per service.
- The Swimlanes view stacks multiple disconnected DAGs within a service's lane vertically (top-to-bottom), not horizontally.
- The Swimlanes view uses rank-based 2D layout where each node's rank equals its max parent-distance from a root.
- The Swimlanes view places parallel branches at the same rank on different vertical tracks.
- The Swimlanes view derives edges from each node's
parent_deploymentsfield. - The Swimlanes view places no cross-service edges β each lane is fully self-contained.
- The Swimlanes view time axis flows left-to-right within each DAG based on
happened_at. - The Swimlanes view does NOT render
parent_deploymentsas text on nodes β graph edges already convey parent relationships, so the text would duplicate information.
Filtering and correlation¶
- The Matrix view supports filtering deployments by service name via an inline text input.
- The Matrix view supports a failures-only pill toggle that hides non-failed states.
- The Swimlanes view provides a correlation predicate picker with single-select choice of five options:
same sha,same run_number,same actor,same version,explicit parent. - The Swimlanes view provides a separate time-window parameter (e.g. 5 min / 1 hr / 1 day / 7 days) that bounds parent search for non-
explicit-parentpredicates. - The time-window control is disabled when
explicit parentis the selected correlation predicate.
Attribute visibility¶
- Both views provide an attribute visibility picker that lets the user choose which fields render on deployment elements.
- The Matrix attribute picker exposes 8 toggles:
version,run_url,sha,run_number,ref,actor,happened_at,parent_deployments. - The Swimlanes attribute picker exposes 8 toggles:
environment,version,run_url,sha,run_number,ref,actor,happened_at.parent_deploymentsis intentionally absent β the graph edges convey it. - Both attribute pickers default to all options ON.
Column visibility and order (Matrix only)¶
- The Matrix view provides a column visibility picker (Columns button,
β) that lets the user show or hide individual environment columns. - Hiding an environment column fully removes it from the grid (header + all cells); no placeholder column remains.
- The last visible environment column cannot be hidden.
- Visible environment columns are draggable to reorder via a
β Ώgrip handle on each column header. - A "Show all Β· reset order" action in the Columns popover restores all columns to visible and resets to the default column order.
- Column visibility (hidden set) and column order persist client-side to
localStoragekeysdd:colHiddenanddd:colOrder. - Both persistence keys are cleared by "Show all Β· reset order".
- On reload, persisted column state is restored; a stale
colOrder(environment set changed) falls back to the default order. - The Fields button and Columns button each display an accent active state plus a numeric count badge when their respective hidden counts are greater than zero. The badge and accent clear when the count returns to zero.
- Each button's tooltip reflects the current hidden count:
"Fields β N field(s) hidden"/"Columns β N environment(s) hidden"when N > 0; default label text when N = 0.
Details surfaces¶
- Clicking any slot in the Matrix view opens a side drawer showing the per-slot deployment history.
- Clicking any node in the Swimlanes view selects it and updates a persistent Inspector panel.
- The history drawer and Inspector panel always display every visible domain-model field regardless of attribute-picker state.
Header surfaces¶
- A KPI strip in the header surfaces services count, environments count, in-flight count, and failed count, all derived from rendered data.
- A live/SSE indicator surfaces real-time connection status in the header.
- A theme switcher in the header provides three modes β dark, light, auto.
- The auto theme mode resolves the active theme via the system
prefers-color-schememedia query. - The user's theme selection persists across reloads via
localStorage.
Operational telemetry β fetcher rate-limit indicator¶
Scope. This subsection governs a fetcher operational telemetry surface in the header. It is distinct from deployment data. The 11-field deployment whitelist (see Data β Visible-field whitelist) governs deployment elements (tiles, nodes, drawers, inspector) and does not apply to this indicator.
Sources: docs/diagrams/fetcher-rate-limit.md, docs/api/api-guidelines.md Β§11 "Rate-limit report payload".
Stream. The SPA subscribes to GET /api/control/events/stream (SSE, event name component), filters frames where event_type === "rate-limit", and maintains a per-adapter map keyed by payload.adapter (last-value-wins per adapter; no history).
Visibility. Chips are rendered only after the first qualifying event arrives; absent on initial load. The last-known per-adapter map persists to localStorage (key dd.rateLimit) and is hydrated on init so chips appear immediately after reload.
Chips (.hdr-icons group). One compact icon-button per adapter, sorted alphabetically by adapter name. Each displays inline own_used / own_budget. Clicking opens that adapter's p-popover with the full breakdown. With a single adapter the header looks identical to the single-chip design.
Popover fields (per chip).
- adapter β CI/CD adapter name; always present.
- own_used / own_budget β fetcher's own request usage vs self-throttle budget; displays β for null values.
- Usage bar β visual proportion of own_used / own_budget; rendered only when own_budget > 0; never divides by zero.
- ci_remaining / ci_limit β CI/CD-wide remaining vs total quota; displays β for null values.
- reset_at β window rollover time as local clock string; displays β when null.
- state badge β running (green) or paused (amber); styled distinctly.
Null safety. Any null numeric or time field renders as an em-dash (β). No NaN may appear in the UI.
Live/SSE indicator. sseConnected reflects EventSource connection state: true on onopen, false on onerror or when the connection is closed. It is independent of data-event arrival β the indicator stays green during idle periods between deployment events (e.g., : ping heartbeats keep the connection alive but do not fire JS events).
Live interactions¶
- Hovering any version anywhere in the Matrix amber-highlights every tile across environments where the same version is deployed.
Analytics view¶
- The dashboard provides a third view β Analytics β accessible via the top-nav segmented control as a 3rd tab alongside Matrix and Swimlanes.
- The Analytics view is read-only β no user writes; CI/CD writes are the sole data source.
- The period selector exposes three windows: 7d, 14d, 30d; only one may be active at a time.
- The active window is bounded server-side by
HISTORY_RETENTION_DAYS; whenwindow.clamped === truethe SPA surfaces the clamp in the period selector subtitle ("bounded by HISTORY_RETENTION_DAYS"). - All aggregation is server-side; the SPA MUST NOT compute p95 / group-by / frequency counts over raw deployment history client-side.
- The DORA KPI band displays four keys: Deployment Frequency (
per_day), Lead Time for Changes (hours), Change Failure Rate (ratio), and Time to Restore (minutes). - Each DORA KPI card renders: formatted value + unit, a performance classification chip (
elite/high/medium/low), a signed trend chip vs the prior half-window (direction semantics: up = good for frequency; up = bad for CFR, lead-time, MTTR), and a per-day sparkline. - The Lead Time card MUST display a visible approximation label; the value MUST NOT be presented as measured commitβprod lead time (source:
api-guidelines.mdΒ§12 lead-time caveat). - The chart grid contains 8 charts backed by the 9 focused analytics endpoints:
- Deployment frequency over time β stacked bars, success vs failure per day (
GET /api/analytics/frequency). - Change failure rate trend β daily CFR line + dashed 15% elite reference line (
GET /api/analytics/change-failure-rate). - Deployment duration distribution β histogram bins (minutes) + p50 and p95 markers (
GET /api/analytics/duration-histogram). - Promotion funnel β operator-configured promotion ladder (default
dev,staging,qa,preprod,prod) sankey/funnel, count + conversion per stage (GET /api/analytics/promotion-funnel). - Status distribution β donut of all 8 statuses, zero-filled for stable slice set (
GET /api/analytics/status-distribution). - Deploy heatmap β 7-row (day-of-week) Γ 24-col (UTC hour) intensity grid (
GET /api/analytics/heatmap). - Top deployers β leaderboard of actor + count, descending, default 10 entries (
GET /api/analytics/top-deployers). - Time to restore β recent incidents list, worst-first; each row shows service, environment, elapsed, severity chip (
GET /api/analytics/incidents). - The DORA KPI band data comes from
GET /api/analytics/dora(a 9th endpoint β not one of the 8 charts). - Every analytics GET carries a weak
ETag; the SPA SHOULD sendIf-None-Matchfor304short-circuit on unchanged data. - The Analytics view uses
ngx-echarts(echartsas peer) for all 8 chart renders. Seedocs/design/libraries.mdfor rationale and version.
Visual¶
Box states (Matrix)¶
- Each Matrix slot renders one of six box states per the SAD's 6-box-states table.
- The Success state renders a full green tile with version, actor, and elapsed time.
- The Running (no prior) state renders a full orange spinning tile with version only.
- The Running + Failed (no prior) state renders a full orange spinning tile with a β prev-failed badge and no running-version text.
- The Running + Last Successful state renders a split tile with an orange spinner + running version on top and the last-successful identifier below.
- The Running + Failed + Last Successful state renders a split tile with an orange spinner + β badge on top (no running version) and the last-successful identifier below.
- The Failed + Last Successful state renders a split tile with a red top + failed version and the last-successful identifier below.
- Split-tile states use a literal dashed divider between the current and last-successful sections.
- The bottom section of any split tile renders a single identifier picked via the fallback chain
versionβshaβrefβrun_number.
Palette and semantics¶
- The status palette uses green for success, orange for running, red for failed, and amber for the cross-matrix version hover-highlight.
- The status palette is fixed semantic β colours never appear decoratively.
Identifier prominence¶
- The Matrix tile renders
versionas its prominent headline identifier. - The Swimlanes node renders
environmentas the prominent identifier in the bottom-right corner. - The Swimlanes node renders
versionas a secondary smaller mono identifier. - The Matrix tile
versionfont-size and the Swimlanes nodeenvironmentfont-size are matched β the two surfaces' primary identifiers share a size.
Field treatment on deployment elements¶
- Fields on Matrix tiles and Swimlanes nodes use mixed visual treatments β position, glyph prefix, typography weight β rather than uniform label/value rows.
- The reader identifies each field on a tile/node by its shape and position, not by a text label.
Field treatment on details surfaces¶
- The history drawer and Inspector panel use explicit text label/value rows because they are details surfaces.
Matrix structure¶
- The Matrix provides clear visual separation between service rows via a hairline divider plus a service-name left accent.
- The Matrix container has a visible bottom edge so the last row does not visually hang in empty space.
Swimlanes node structure¶
- A Swimlanes node has a single top row that spans the full card width (colspan=2).
versionis flush to the card's left edge;happened_atis flush to the card's right edge. - The remaining rows of a Swimlanes node form a 2-column grid: left content sits in column 1, right content in column 2.
- Column 1 of the body holds (top-to-bottom):
ref,sha. Column 2 of the body holds (top-to-bottom): the run cluster (run_url+run_number+actor),environment. - The horizontal gap between body columns is a single uniform value applied to every body row.
shasits at the bottom-left corner of the node;environmentsits at the bottom-right corner on the same row.- Rows scroll horizontally inside the node when their content exceeds the node's width, rather than overflowing the lane.
- Inter-row vertical distance inside a Swimlanes node is uniform across every node regardless of card height; long-version cards may grow taller but the inter-row distance itself does not vary.
Behavior¶
Responsive sizing¶
- Deployment elements size to their currently visible content.
- Tiles and node cards shrink when attribute fields are toggled off.
- The Swimlanes layout recomputes lane heights, rank-column positions, and total canvas size on every attribute toggle.
- Tiles and node cards stretch horizontally to fit their widest content.
- The
versionfield may be up to 50 characters and must render fully on tiles and nodes as a single line, without truncation and without wrap. - The Matrix grid columns expand to consume available viewport width when content allows.
- The Matrix and Swimlanes containers scroll horizontally when total content width exceeds viewport.
- The Matrix service column remains sticky during horizontal scroll so service names stay visible.
- The Swimlanes lanes pack densely with minimal inter-lane and inter-track gaps.
- Tile content distributes vertically across the available cell height (no large empty middle).
Layout integrity¶
- No deployment element overlaps another in either view, regardless of content variance.
- Per-rank column spacing in the Swimlanes equals the maximum card width in that rank plus a fixed gap.
- DAG edges never cross node bounding boxes.
- All elements remain accessible β nothing is clipped, hidden, or rendered behind other surfaces unreachably.
- Split-tile bottom content remains contained within its cell and never visually bleeds into adjacent rows.
Control surfaces¶
- The filter input and failures-only toggle are persistent inline elements in the Matrix header.
- The fields picker, columns picker, correlation picker, and time-window control are on-demand header icon-button popovers.
- The columns picker icon button is hidden when the Swimlanes view is active.
- The theme switcher is a persistent header control.
- Every interactive topbar control carries a concise hover tooltip.
- Popover surfaces render above all canvas content via z-index without being clipped by stacking contexts.
Data¶
Visible-field whitelist¶
- The visible-field whitelist contains 11 fields:
service,environment,version,status,run_url,sha,run_number,ref,actor,happened_at,parent_deployments. - The
idfield is synthetic and never appears in any visible UI surface. - No fields outside the visible-field whitelist may appear in the UI.
Derived values¶
- KPI counts derive purely from the whitelisted fields (no invented metrics).
- The
reffield renders as a branch name or PR number per its domain definition. - The
happened_atfield renders as elapsed time on tiles and nodes, and as elapsed plus absolute UTC in drawer and inspector rows.