Skip to content

feat(ui,rest,observability): Subscriptions operator page — read-only dashboard over the live engine - #585

Merged
smunini merged 8 commits into
mainfrom
feat/580-subscriptions-ui
Aug 19, 2026
Merged

feat(ui,rest,observability): Subscriptions operator page — read-only dashboard over the live engine#585
smunini merged 8 commits into
mainfrom
feat/580-subscriptions-ui

Conversation

@angela-helios

Copy link
Copy Markdown
Contributor

Closes #580. The sidebar's Subscriptions placeholder becomes the read-only operator dashboard from Brett's design.

Stacked on #572 — based on fix/543-stylesheet-unification for the shared vocabulary and guards, targeting main so the Development link on #580 is live from day one; the diff shrinks to just this feature when #572 merges.

What renders

  • Four status cards: FAILING (needs attention), IDLE (websocket subscriptions with no connected clients), ACTIVE (delivering), and NOTIFICATIONS since registration.
  • The table: every registered subscription — id and topic (full canonical URL in the tooltip), channel + endpoint, a status chip, the event counter, and the consecutive-failure streak ( where there is no delivery to fail).
  • Sort as plain links: status (default, worst first), most sent, fail streak. Read-only throughout; works without JavaScript.

The read path

Mirrors the dashboard chart's pattern: a plain-data SubscriptionsProvider in helios-observability, implemented in helios-rest over the live engine (the manager's in-memory inventory plus the WebSocket manager's connection counts) and registered exactly where the engine is built. Registration doubles as the "subscriptions advertised" signal from the design note: the nav entry and the page only exist when the engine runs; otherwise the entry hides and the route renders an explained unavailable state.

Honesty rules (same as #555)

  • A websocket subscription nobody is connected to shows 0 clients even while its resource says active — its notifications go nowhere, and that outranks the stored status.
  • The design's 24-hour delivery figures are deliberately absent: the engine does not persist delivery history yet, and this page shows real numbers or none. That instrumentation (a rolling delivery counter or queryable notification log, plus first-try success rate) is the follow-up half of ui: Subscriptions page — read-only operator dashboard (status cards, delivery table) #580.

Verified against the live engine

Manual end-to-end on a running server: an R4 backport topic (Basic), a rest-hook whose endpoint rejects the handshake (405) lands in error — consistently across the UI chip, the persisted resource (status write-back, #357), and $status — while a rest-hook against a real sink handshakes requested → active and delivers notification Bundles that the sink actually receives, with the row's SENT counter matching. The idle websocket accumulates SENT with 0 clients, exactly the design's third example row.

Tests

  • Rust (subscriptions_http.rs): the full state machine over the mounted router with an injected provider — unavailable (nav hidden) → live dashboard (cards summed, worst-first order, chips, streaks, the 0-clients state) → link-based re-sort. Plus a provider unit test in observability.
  • Playwright: the advertised-but-empty engine the e2e server now runs — cards at zero, empty table, sort links, the nav entry — skipping gracefully on a local binary built without the subscriptions feature, which the ui-test workflows now enable. The route joins the shared guard list (a11y both themes, no-cdn, design-system).
  • Full hermetic suite locally: 128 passed.

…dashboard

The sidebar's Subscriptions placeholder becomes a real page (#580), following
Brett's design: four status cards (failing / idle / active / notifications
since registration) over a table of every registered subscription — channel
and endpoint, a status chip, the event counter, and the consecutive-failure
streak. Sort is a plain-links menu (status default: worst first; most sent;
fail streak). Read-only throughout.

The read path mirrors the dashboard chart's: a plain-data provider in
helios-observability, implemented in helios-rest over the live engine (its
in-memory inventory plus the WebSocket manager's connection counts) and
registered where the engine is built. Registration doubles as the
'subscriptions advertised' signal — the nav entry and the page only appear
when the engine runs; otherwise the entry hides and the route renders an
explained unavailable state, per the design note.

Honest by construction: a websocket subscription with no connected clients
shows the 0-clients state even while its resource says active (its
notifications go nowhere), and the design's 24-hour delivery figures are
deliberately absent until the engine grows delivery instrumentation — real
numbers or none (#555's rule). All strings in en/es/de.
Rust drives the full state machine over the mounted router with an injected
provider — unavailable (nav hidden) → live dashboard (cards summed, worst-first
order, chips, streaks, the idle websocket's 0-clients state) → link-based
re-sort. Playwright covers the advertised-but-empty engine the e2e server now
runs (cards at zero, empty table, sort as plain links, the nav entry), skipping
gracefully on a local binary built without the subscriptions feature — which CI
ui-test builds now enable. The route joins the shared guard list, so a11y in
both themes, no-cdn, and the design-system guard cover the page from day one.
angela-helios and others added 6 commits August 19, 2026 14:04
…ubscriptions-ui

Union merge: both export routes join the guard list alongside the
subscriptions page, the locale catalogs keep both new key blocks, and the
.tag status-pill family carries the subscription states next to the export
job states — one vocabulary, as #572 intends.
…s-ui

# Conflicts:
#	crates/ui/assets/app.css
#	crates/ui/e2e/pages/routes.ts
#	locales/de/main.ftl
#	locales/en/main.ftl
#	locales/es/main.ftl
Two call sites exceeded rustfmt's default fn_call_width (60) and were left
on one line, failing `cargo fmt --all -- --check`:

* crates/fhir-validator/src/editor.rs — arrived on main with #573 and is
  already breaking main's Linting job at 9636888; the merge inherited it.
* crates/ui/tests/subscriptions_http.rs — predates the merge on this branch.

Pure formatting; no behavior change.

Claude-Session: https://claude.ai/code/session_0197k7pHRnRPd2TaDjibNSDJ
Both main catch-ups landed in parallel again; content-identical, only block
ordering differed (the .tag family and the locale key blocks). Resolved to
the locally validated layout — the tree is byte-for-byte the one the full
suite passed at 140.
@angela-helios

Copy link
Copy Markdown
Contributor Author

Coordination note: we were both pushing main catch-ups to this branch at the same time — everything is reconciled as of edb2d65a6 (your rustfmt pass included). The tree is the one the full local suite passed at 140: subscriptions + the merged editor/export/stylesheet work together. Backing off the branch now — it is all yours.

@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.56757% with 11 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/ui/src/subscriptions.rs 89.13% 10 Missing ⚠️
crates/ui/src/lib.rs 88.88% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@smunini
smunini merged commit 0d7b492 into main Aug 19, 2026
21 checks passed
@smunini
smunini deleted the feat/580-subscriptions-ui branch August 19, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ui: Subscriptions page — read-only operator dashboard (status cards, delivery table)

2 participants