HydraIssues

hydraorganization: org dashboard UI and asset performance aggregation
done feature Project: hydraorganization Parent: #589 Reporter: cederik 28 Aug 2026 07:24

Description

Part of #589.

CONTEXT
With login in place, this issue builds the dashboard itself: server-rendered HTML plus a session-authed JSON overview endpoint. hydraorganization acts as backend-for-frontend: it holds the downstream admin and bearer tokens in its config and does all org filtering server-side. No downstream token ever reaches the browser. No downstream service gains org scoping in v1; that stays a platform follow-up (#545 direction).

SCOPE

  1. CONFIG: add a services block to config.yaml: hydravenues.base_url (public reads, no token), hydraexperiencelibrary.base_url plus token, hydracluster.base_url plus token, hydrastreamingmonitor.base_url plus token. Update config.example.yaml and the runbook.
  2. AGGREGATION (internal/dashboard or similar package), all behind the org-membership middleware:
    • Venues: GET /api/v1/venues?organization={orgID}. Show each venue with its display name (map museum = sint-niklaas-tourism-office, mobile booth = mobile-kit per the hydravenues runbook map).
    • Live status: GET /api/v1/nodes (admin token), match node.venue to the org's venue IDs (valid after the node.venue integrity issue), show heads and bodies per venue with online/offline and last-seen.
    • Sessions: GET /api/v1/sessions/history?from=&to=&venue= per org venue. Show per-venue session counts and total streamed time for a selected range (default 30 days). State on the page that history starts at the session-persistence deploy date.
    • Experiences: GET /api/v1/experiences?organization={orgID} (bearer token). Show name, deployment venues, live status. Per-experience SESSION COUNTS are conditional: include them only if the hydracluster experience-name verification confirmed stamping; otherwise omit the column and add a note. Check that issue's posted outcome before building.
    • Reliability: GET /api/v1/intelligence (admin token). Show 7d/30d reliability labeled "platform services", explicitly NOT per-venue uptime. Per-venue uptime history has no data source and is out of scope (accepted risk on the master issue).
  3. UI: Go html/template pages under /dashboard, embedded like the hydraissue web package. Keep it plain: org header, venue cards with live status and session numbers, experience list, reliability panel. No SPA, no external assets.
  4. JSON: GET /api/v1/organizations/{id}/overview behind the session middleware (not the admin token), returning the same aggregate for future clients.
  5. Resilience: each downstream fetch has a timeout; a failed source renders a "data unavailable" panel, never a 500 for the whole page. Cache aggregates in memory for 30 to 60 seconds.
  6. Tests: aggregation filtering (only the org's venues survive), downstream-failure rendering, overview endpoint auth.

ACCEPTANCE CRITERIA

  • The Visit Flanders owner logs in and sees: venues rupelmonde, sint-niklaas-tourism-office, mobile-kit, ad6, cloud-seven with live head/body status; session counts and streamed time per venue over the chosen range; experiences mercator-talks and rupelmonde-castle-viewer with deployment status (with session counts only if stamping was confirmed); the labeled service-level reliability panel.
  • All data shown belongs to visit-flanders only; a member of a different org sees only their own org.
  • No downstream token appears in any response, page source, or browser request.
  • With hydrastreamingmonitor stopped, the dashboard still renders with that panel marked unavailable.
  • Runbook documents the config block, the data sources, and the deferrals (per-venue uptime, hydraneckwebrtc telemetry, SSE organization_id).

FILES

  • /home/claude-user/hydraorganization/internal/api/server.go
  • /home/claude-user/hydraorganization/internal/api/handlers.go
  • /home/claude-user/hydraorganization/config.example.yaml
  • /home/claude-user/hydraorganization/docs/runbooks/runbook.md
  • /home/claude-user/hydraissue/internal/web (embedded-template pattern reference)
  • /home/claude-user/hydrastreamingmonitor/internal/web/handler.go (:117-118 intelligence API shape)

DEPLOY
Tag, push, CI, host auto-update, hydrarelease verify --project hydraorganization. Then run the end-to-end acceptance against the live dashboard with the real visit-flanders membership and post the result on the master issue.

Comments (5)

claude 28 Aug 2026 11:41

UI shipped ahead of the data work as a MOCK DATA preview: https://hydraorganization.experiencenet.com/dashboard (hydraorganization v0.3.0, deployed 2026-08-28). internal/dashboard.Overview is the contract; internal/dashboard.Mock fills it today and this issue replaces Mock with real aggregation over hydravenues, hydraexperiencelibrary, hydracluster, and hydrastreamingmonitor. The JSON shape is live at GET /api/v1/organizations/visit-flanders/overview with mock:true. Templates stay as they are; only the provider changes. The page is public while it shows mock data only; it must go behind the iamnim middleware from #596 before real data connects.

claude 28 Aug 2026 19:12

Visitor ratings added to the dashboard contract and the mock preview (hydraorganization v0.3.1, live). Overview, Venue, and Experience each carry an optional rating {average, responses}; the UI shows a summary tile, a Rating row per venue card, and a Rating column on the experiences table. Real source is hydranps (#565): per-venue and per-experience aggregates over rated sessions only, excluding disconnected sessions per the #565 design. This issue connects it; the panels render only when rating data is present, so shipping without #565 is safe.

claude 31 Aug 2026 21:13

LIVE DATA SHIPPED in hydraorganization v0.5.1 (2026-08-31). internal/dashboard.Live replaces Mock as the default provider; ?mock=1 still serves examples.

WIRED: venue roster from hydravenues (?organization=, no token); heads from hydracluster /api/v1/heads and bodies from /api/v1/nodes filtered on the hydrabody role (admin token); experiences from hydraexperiencelibrary /api/v1/experiences joined client side on venue id (admin token); reliability from hydrastreamingmonitor /api/v1/intelligence plus /api/v1/health (no token). Verified live: 4 venues, 1/8 heads and 3/3 bodies online, 4 experiences, 9/11 services healthy, all four sources ok.

DELIBERATELY ABSENT, not faked: session counts, streamed time, visitor ratings and the date-range selector. Probing found streaming sessions carry no venue and survive only in an in-memory ring (#595), and hydranps holds 208 records of which exactly ONE has a score and none has a venue, with no writes since 2026-03-23 (#565). health extra.rating_count is a session count, not a rating count. Unknown values are pointers plus Known flags so an absent number is never serialised as a confident zero, and a venue whose fleet could not be read reports unknown rather than offline.

TWO BUGS THE LIVE DATA EXPOSED, both fixed: hydrastreamingmonitor /api/v1/intelligence reports full uptime for a service that is down right now, because an outage is only counted once it closes, so /api/v1/health is now required alongside it and the percentages are dropped for any currently-down service; and the experience venue join needed dedup, since a venue repeats across district entries and listed cloud-seven four times for one experience.

KNOWN WEAKNESS: the fleet join is a bare string match on hydracluster node.venue, which nothing enforces against hydravenues ids. Unmatched cluster venue values are logged (#594). Experiences answer "deployed at your venues", not "owned by you", because the library has no organization link (#593).

claude 1 Sep 2026 05:29

FIELDS RESTORED as hyphens in v0.6.1, per the owner. Sessions, streamed time and visitor ratings are back on the page and in the contract as pointers: the UI renders a hyphen when there is no source, and the JSON OMITS the keys rather than sending 0, so unknown stays distinguishable from none. The date-range selector was NOT restored: it would be a control that changes nothing until session history exists (#595). Live now shows real fleet numbers next to hyphens for the unrecorded fields, which makes the gap visible on the page rather than hidden.

claude 1 Sep 2026 09:57

CLOSING as done at hydraorganization v0.7.0. Live at https://hydraorganization.experiencenet.com/dashboard behind iamnim sign-in.

Delivered: venue roster, per-venue head and body counts, deployed experiences and platform reliability, all from the live services; mobile-first UI with a card deck for venues and experiences; org dropdown for people with more than one membership; sessions, streamed time and ratings present as fields showing a hyphen until their sources exist.

Still blocking real numbers in this page: #595 (session persistence plus venue stamp) for sessions and streamed time, #565 for visitor ratings, #593 for a real org link on experiences, #594 for trustworthy node.venue. The page is honest about all four today rather than guessing.