Add read-only diagnostic and Grafana dashboards #27

Closed
opened 2026-07-15 11:10:39 +02:00 by Kyuubi · 2 comments
Owner

Parent: #1
Depends on: #16, #17, #26
Priority: nice-to-have; not a Rendezvous v1 release gate

Outcome

Provide two deliberately separate views of Rendezvous:

  1. a thin read-only diagnostic web dashboard that exercises the same public session-browser and live-update APIs available to games;
  2. provisioned Grafana dashboards for operators using privacy-safe service metrics.

This issue does not create a privileged administration web UI. Revocation, key management, tenant configuration, and other destructive operations remain in the authenticated operator CLI/API from #16.

Diagnostic dashboard

Build a minimal static web application with no game or server authority. Prefer plain standards-based HTML/CSS/JavaScript or another build-light static approach unless a heavier framework is justified.

Scope

  • Select configured game, environment, protocol, region, capacity, and visibility filters.
  • Fetch the bounded initial session snapshot and subscribe to the SSE stream from #26.
  • Display public session projection fields only: safe metadata, compatibility/build display, region, advisory capacity, visibility/freshness state, and last update age.
  • Apply session_upsert, session_remove, and reset deterministically.
  • Surface stream state: connected, reconnecting, polling fallback, cursor reset, service unavailable, and last successful update.
  • Permit deliberate reconnect/reset/polling-fallback diagnostics without exposing internal credentials.
  • Escape all server-provided metadata and never render it as trusted HTML, CSS, URL, or script.
  • Provide responsive, keyboard-accessible presentation with clear empty/loading/error states.
  • Keep joining and gameplay out of the page unless a future consumer-specific deep link is explicitly designed.
  • Deploy as optional static assets or a separate static container/profile; production operators may disable it completely.
  • Use an allow-listed configuration rather than accepting arbitrary backend URLs that could turn the page into an SSRF/open-proxy aid.

Grafana dashboards

Commit version-controlled provisioning/dashboard definitions covering:

  • HTTP availability, request rate, latency, errors, timeouts, and rate-limit rejections;
  • active/awaiting/stale listings, lease renewal/expiry churn, and browser snapshot/SSE subscriber counts;
  • join issuance, active attempts, endpoint binding, pairing latency, introduction outcomes, reported direct outcomes, and typed failures;
  • UDP packets/bytes accepted and dropped, malformed/replay/limited traffic, response amplification budget, queue depth, and saturation;
  • process CPU, memory, GC, threads, sockets, and graceful-drain status;
  • shared-store health/latency only when a shared store is enabled;
  • key-expiry/configuration health and security/audit event rates;
  • supported/capacity profile overlays and recommended alert thresholds.

Use only low-cardinality tenant/environment/region/outcome dimensions approved by #16. Never use session IDs, attempt IDs, tokens, metadata, or raw IP addresses as labels.

Security and privacy boundaries

  • The diagnostic dashboard calls public read-only browse/SSE APIs only.
  • No operator credential, publisher credential, lease capability, punch capability, connection ticket, raw endpoint, or secret is stored in browser state or returned to it.
  • Apply a restrictive Content Security Policy, safe CORS policy, clickjacking protection, MIME-type protection, and dependency minimization.
  • Public dashboard enablement, allowed games/environments, and rate limits are explicit configuration.
  • Grafana access and datasource credentials remain operator-controlled and are not proxied through the public dashboard.
  • Diagnostic and Grafana logs/telemetry follow the retention/redaction policy from #2/#16.

Acceptance criteria

  • A user can open the diagnostic page, filter sessions, and see live add/update/remove changes without manual refresh.
  • Disconnect, SSE cursor gap, server restart, and unsupported streaming fall back or reset cleanly without leaving a false/stale “live” state.
  • The final client projection matches a fresh server snapshot after every tested event sequence.
  • Malicious metadata regression cases cannot inject markup/script/style/navigation or corrupt the page.
  • Cross-game/environment/protocol/visibility isolation is preserved.
  • The dashboard never receives or exposes raw endpoints or credentials.
  • Slow event bursts are coalesced/rendered without unbounded DOM growth, memory use, or flicker.
  • Keyboard navigation, focus visibility, semantic labels, contrast, loading, empty, and error states pass the chosen accessibility gate.
  • Grafana provisioning loads from a clean Compose/deployment environment with no manual panel construction.
  • Grafana panels populate during the three-party/TestClient scenario and abusive-load tests.
  • Dashboard queries and labels remain bounded/low-cardinality and contain no secrets or personal endpoint data.
  • Both dashboards are optional, documented, and independently disableable.
  • Security tests verify CSP/CORS/headers and prove the page has no privileged administration path.
Parent: #1 Depends on: #16, #17, #26 Priority: nice-to-have; not a Rendezvous v1 release gate ## Outcome Provide two deliberately separate views of Rendezvous: 1. a thin read-only diagnostic web dashboard that exercises the same public session-browser and live-update APIs available to games; 2. provisioned Grafana dashboards for operators using privacy-safe service metrics. This issue does not create a privileged administration web UI. Revocation, key management, tenant configuration, and other destructive operations remain in the authenticated operator CLI/API from #16. ## Diagnostic dashboard Build a minimal static web application with no game or server authority. Prefer plain standards-based HTML/CSS/JavaScript or another build-light static approach unless a heavier framework is justified. ### Scope - Select configured game, environment, protocol, region, capacity, and visibility filters. - Fetch the bounded initial session snapshot and subscribe to the SSE stream from #26. - Display public session projection fields only: safe metadata, compatibility/build display, region, advisory capacity, visibility/freshness state, and last update age. - Apply `session_upsert`, `session_remove`, and `reset` deterministically. - Surface stream state: connected, reconnecting, polling fallback, cursor reset, service unavailable, and last successful update. - Permit deliberate reconnect/reset/polling-fallback diagnostics without exposing internal credentials. - Escape all server-provided metadata and never render it as trusted HTML, CSS, URL, or script. - Provide responsive, keyboard-accessible presentation with clear empty/loading/error states. - Keep joining and gameplay out of the page unless a future consumer-specific deep link is explicitly designed. - Deploy as optional static assets or a separate static container/profile; production operators may disable it completely. - Use an allow-listed configuration rather than accepting arbitrary backend URLs that could turn the page into an SSRF/open-proxy aid. ## Grafana dashboards Commit version-controlled provisioning/dashboard definitions covering: - HTTP availability, request rate, latency, errors, timeouts, and rate-limit rejections; - active/awaiting/stale listings, lease renewal/expiry churn, and browser snapshot/SSE subscriber counts; - join issuance, active attempts, endpoint binding, pairing latency, introduction outcomes, reported direct outcomes, and typed failures; - UDP packets/bytes accepted and dropped, malformed/replay/limited traffic, response amplification budget, queue depth, and saturation; - process CPU, memory, GC, threads, sockets, and graceful-drain status; - shared-store health/latency only when a shared store is enabled; - key-expiry/configuration health and security/audit event rates; - supported/capacity profile overlays and recommended alert thresholds. Use only low-cardinality tenant/environment/region/outcome dimensions approved by #16. Never use session IDs, attempt IDs, tokens, metadata, or raw IP addresses as labels. ## Security and privacy boundaries - The diagnostic dashboard calls public read-only browse/SSE APIs only. - No operator credential, publisher credential, lease capability, punch capability, connection ticket, raw endpoint, or secret is stored in browser state or returned to it. - Apply a restrictive Content Security Policy, safe CORS policy, clickjacking protection, MIME-type protection, and dependency minimization. - Public dashboard enablement, allowed games/environments, and rate limits are explicit configuration. - Grafana access and datasource credentials remain operator-controlled and are not proxied through the public dashboard. - Diagnostic and Grafana logs/telemetry follow the retention/redaction policy from #2/#16. ## Acceptance criteria - A user can open the diagnostic page, filter sessions, and see live add/update/remove changes without manual refresh. - Disconnect, SSE cursor gap, server restart, and unsupported streaming fall back or reset cleanly without leaving a false/stale “live” state. - The final client projection matches a fresh server snapshot after every tested event sequence. - Malicious metadata regression cases cannot inject markup/script/style/navigation or corrupt the page. - Cross-game/environment/protocol/visibility isolation is preserved. - The dashboard never receives or exposes raw endpoints or credentials. - Slow event bursts are coalesced/rendered without unbounded DOM growth, memory use, or flicker. - Keyboard navigation, focus visibility, semantic labels, contrast, loading, empty, and error states pass the chosen accessibility gate. - Grafana provisioning loads from a clean Compose/deployment environment with no manual panel construction. - Grafana panels populate during the three-party/TestClient scenario and abusive-load tests. - Dashboard queries and labels remain bounded/low-cardinality and contain no secrets or personal endpoint data. - Both dashboards are optional, documented, and independently disableable. - Security tests verify CSP/CORS/headers and prove the page has no privileged administration path.
Kyuubi added reference codex/issue-27-diagnostic-dashboards 2026-07-16 23:27:35 +02:00
Kyuubi self-assigned this 2026-07-16 23:27:36 +02:00
Author
Owner

Starting implementation on codex/issue-27-diagnostic-dashboards from verified issue #26. Scope will preserve the public read-only diagnostic/operator Grafana separation, use build-light static assets, add explicit security and low-cardinality boundaries, and verify WCAG 2.2 AA plus clean provisioning.

Starting implementation on `codex/issue-27-diagnostic-dashboards` from verified issue #26. Scope will preserve the public read-only diagnostic/operator Grafana separation, use build-light static assets, add explicit security and low-cardinality boundaries, and verify WCAG 2.2 AA plus clean provisioning.
Author
Owner

Implemented and verified in 99885f8 (codex/issue-27-diagnostic-dashboards).

Delivered:

  • optional same-origin, read-only /diagnostics static dashboard using the public bounded browse + SSE contracts only;
  • explicit game/environment/protocol/region/capacity selection with fixed public visibility, safe public projection rendering, deterministic add/update/remove/reset handling, deliberate reconnect/reset/poll-only diagnostics, bounded DOM/projection state, and polling fallback;
  • restrictive CSP, clickjacking/MIME/referrer/browser-capability protections, no CORS relaxation, no privileged path or browser credential state, and disabled-by-default allowlisted configuration;
  • bearer-protected, disabled-by-default Prometheus exporter with bounded privacy-safe labels and store/SSE/HTTP/UDP/join/outcome/security/key/process/.NET metrics;
  • digest-pinned hardened Prometheus 3.13.1 + Grafana 13.1.0 Compose overlay, file-based secrets, private Prometheus, loopback/authenticated Grafana, read-only versioned datasource/dashboard provisioning, and 24 operational/capacity panels;
  • operator documentation, CI asset gates, null-bound configuration guards, and regression tests.

Observed acceptance evidence:

  • in-app browser: semantic regions/labels, empty/loading/live/poll/reset states, visible high-contrast layout, 320 px reflow, 44–47 px controls, no page-script errors; deliberate polling remained selected across refresh and reconnect restored SSE;
  • actual response headers: CSP default-src 'none' / same-origin connect/script/style, DENY, nosniff, no-referrer, COOP/CORP, permissions disabled, no-store;
  • clean merged Compose startup provisioned Prometheus/Grafana without manual construction; unauthenticated /metrics returned 404, anonymous Grafana API returned 401, Prometheus had no published host port;
  • live target up=1, store available, and process metrics populated; Grafana rendered UP / AVAILABLE / ACCEPTING and the capacity panels;
  • real smoke-deployment.sh three-party scenario passed and populated registration, browse/join issuance, presence, waiting-for-peer, introduction, connected outcome, pairing latency, and UDP byte series;
  • bounded low-limit abusive burst populated rendezvous_limiter_drops_total{transport="udp",partition="rate-or-concurrency"}=860 while target health remained up=1;
  • adversarial branch audit findings fixed: null-bound config NREs, missing polling-only regression gate, workload-backed observability proof, stale README status;
  • formatting clean; dashboard tests 6/6 + provisioning tests 3/3; Debug and Release builds clean; full Release suite 320 passed / 0 failed / 0 skipped; merged Compose config clean; no containers, volumes, or disposable secrets left behind.
Implemented and verified in `99885f8` (`codex/issue-27-diagnostic-dashboards`). Delivered: - optional same-origin, read-only `/diagnostics` static dashboard using the public bounded browse + SSE contracts only; - explicit game/environment/protocol/region/capacity selection with fixed public visibility, safe public projection rendering, deterministic add/update/remove/reset handling, deliberate reconnect/reset/poll-only diagnostics, bounded DOM/projection state, and polling fallback; - restrictive CSP, clickjacking/MIME/referrer/browser-capability protections, no CORS relaxation, no privileged path or browser credential state, and disabled-by-default allowlisted configuration; - bearer-protected, disabled-by-default Prometheus exporter with bounded privacy-safe labels and store/SSE/HTTP/UDP/join/outcome/security/key/process/.NET metrics; - digest-pinned hardened Prometheus 3.13.1 + Grafana 13.1.0 Compose overlay, file-based secrets, private Prometheus, loopback/authenticated Grafana, read-only versioned datasource/dashboard provisioning, and 24 operational/capacity panels; - operator documentation, CI asset gates, null-bound configuration guards, and regression tests. Observed acceptance evidence: - in-app browser: semantic regions/labels, empty/loading/live/poll/reset states, visible high-contrast layout, 320 px reflow, 44–47 px controls, no page-script errors; deliberate polling remained selected across refresh and reconnect restored SSE; - actual response headers: CSP `default-src 'none'` / same-origin connect/script/style, `DENY`, `nosniff`, `no-referrer`, COOP/CORP, permissions disabled, `no-store`; - clean merged Compose startup provisioned Prometheus/Grafana without manual construction; unauthenticated `/metrics` returned 404, anonymous Grafana API returned 401, Prometheus had no published host port; - live target `up=1`, store available, and process metrics populated; Grafana rendered UP / AVAILABLE / ACCEPTING and the capacity panels; - real `smoke-deployment.sh` three-party scenario passed and populated registration, browse/join issuance, presence, waiting-for-peer, introduction, connected outcome, pairing latency, and UDP byte series; - bounded low-limit abusive burst populated `rendezvous_limiter_drops_total{transport="udp",partition="rate-or-concurrency"}=860` while target health remained `up=1`; - adversarial branch audit findings fixed: null-bound config NREs, missing polling-only regression gate, workload-backed observability proof, stale README status; - formatting clean; dashboard tests 6/6 + provisioning tests 3/3; Debug and Release builds clean; full Release suite 320 passed / 0 failed / 0 skipped; merged Compose config clean; no containers, volumes, or disposable secrets left behind.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: HeiKyu/Rendezvous#27