Diagnosis access boundary: detail-free overview, why behind admin gate#
ops-db-ui diagnosis wiring, epic #139. Relates to ADR-0001 (live-check contract) and the data-transfer error-breadcrumb work.
Context#
Two audiences watch the transfer pipeline. Observers (scientists,
data-reduction users) cannot act on the system — no tokens, no SSH — but need to
know what is stuck where (“did my data leave the site, is my package stuck”).
Admins can act and need the why. The new “dive into the diagnosis” UI hangs
a Diagnose action off the shown failures; the question is who may see the
error_context (paths, hosts, traceback, the Diagnosis line).
The constraint that decides the design: GET /api/transfer/overview and the
/ws/overview WebSocket are currently anonymous at the API layer, and the
WebSocket broadcasts one shared payload to every connected client. Today that
payload embeds each failed operation’s error_context/failure_error_message,
so the why is already broadcast to anyone listening.
Decision#
The boundary is structural, not a per-role strip. The overview payload (HTTP
and WebSocket) carries no error text for anyone: error_context,
failure_error_message, and unpack_error_context are removed from the failed-op
entries. What remains is what an Observer needs — package, location pair, stage,
status, retry count, ids, timestamps.
The why flows only through the already-admin-gated endpoints
(/api/admin/diagnose/{type}/{id}, /api/admin/diagnose/by-package/{name},
failure-history, and the live-check trigger/poll). The UI’s Diagnose action
(admin-only via auth/isAdmin) is the single gateway to a Diagnostic Report;
there is no inline Diagnosis, even for admins.
Considered options#
(a) Detail-free overview (chosen). The overview stays anonymous and broadcastable; the boundary is enforced by where
error_contextlives (behind the admin gate), not by who is listening. Cost: admins lose the inline breadcrumb in the failure panel and click Diagnose to see the why.(b) Role-aware overview. Authenticate
GET /overviewand/ws/overview, includeerror_contextfor admins, null it otherwise. Rejected: retrofits auth onto a hot anonymous endpoint and a broadcast WebSocket — role-aware stripping over WS needs per-connection filtering or two payload variants, a bug-prone surface for a diagnostic nicety. The leak would also remain one schema change away from reappearing.
Consequences#
The inline
FailureBreadcrumbrendered insideFailureAlertPanelis removed; the breadcrumb now lives only inside the Diagnose drawer //admin/diagnosepage (OperationDiagnosisRowalready renders it)./overviewand/ws/overviewneed no auth changes — the reason this option was chosen.Removing
error_contextfromTransferOverviewand its failed-op entries is a payload change; the ops-db-ui consumer must move why-display into the admin-gated Diagnose path in lockstep.The boundary holds only as long as no other anonymous endpoint re-exposes
error_context. New failure-surfacing endpoints must keep error text behind the admin gate.