dashboard: pass kinds= on the 4 unfiltered /api/dashboard/stream subscribers

Part 1 of the dashboard-event-stream-split epic: the server-side
kinds= allow-list already exists and flow.js already uses it
(hive-c0re/src/dashboard/state_snapshot.rs). tabs.js, builds.js,
core.js, and logs.js were the remaining 4 subscribers still taking
every wire kind unfiltered — pure subscription discipline, no new
endpoint needed, per the investigation on the tracking issue.

Each kinds= list is read directly off that page's own existing
MUTATION_HANDLERS/SSE_HANDLERS dispatch table (tabs.js also needs
sent, checked separately for the operator inbox) — a kind not in a
page's table was already a silent no-op today, so this only removes
wire/parse/dispatch-lookup cost for kinds a page never acted on, zero
behavior change.

Note for reviewers: the SharedWorker (stream-worker.js) multiplexes
by exact URL string, so pages that used to share one unfiltered
upstream connection when open simultaneously (e.g. dashboard.html +
builds.html in two tabs) will now each hold their own filtered
connection instead, since their kinds= differ. Each connection is
still a single cheap SSE stream carrying only what that page acts on
— net win over the shared-but-bloated connection this replaces.
This commit is contained in:
iris 2026-08-02 22:21:24 +02:00
commit f60e8a8470
4 changed files with 41 additions and 9 deletions

View file

@ -509,7 +509,15 @@ async function init() {
await refreshState();
const es = openStream('/api/dashboard/stream');
// kinds= matches SSE_HANDLERS below verbatim — narrows this from all
// 17 wire kinds down to the 4 this page acts on. This page was one
// of 4 unfiltered `/api/dashboard/stream` subscribers before this
// (subscription discipline, part 1 of the dashboard-event-stream-
// split issue).
const es = openStream(
'/api/dashboard/stream?kinds=tombstones_changed,container_state_changed,' +
'capabilities_changed,tool_groups_changed',
);
if (es) {
es.onmessage = (e) => {
let ev;