Commit Graph

6 Commits

Author SHA1 Message Date
gsxdsm
c31090efb5 fix(dashboard): unstick Active Agents panel cards from "Connecting..."
Agents in `active` state without a current taskId had no SSE to attach
to, but the card still rendered "Connecting..." — implying a network
state that never resolves. Branch on taskId first: idle agents show
"Idle — no task assigned"; running-without-task shows "Starting...".

Also fix a related SSE multiplexer race: subscribers joining a channel
that had already opened never got an onOpen callback (EventSource only
fires `open` once), so they sat at isConnected=false forever whenever
another component was already streaming the same URL. Fire onOpen on a
microtask for late-joiners.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 14:23:58 -07:00
Aron Prins
8d985c468c fix(dashboard): close SSE EventSources on page unload to prevent freeze
After ~3 refreshes, the dashboard would hang on "Initializing dashboard..."
with all /api/* fetches stalling. Root cause: Chrome keeps HTTP/1.1 sockets
in its keep-alive pool across page navigations even after EventSource is
garbage-collected. Once 6 (the per-origin limit) are held, every new fetch
queues indefinitely and the app can't finish booting.

Fix, layered:

1. sse-bus.ts — pagehide/beforeunload listeners close all active channels
   and send a sendBeacon to /api/events/disconnect so the server forces
   the socket closed (socket.destroy) rather than waiting for the browser
   to notice. Uses a sessionStorage clientId to correlate.

2. api.ts — createResilientEventSource (used by planning / mission / slice
   stream endpoints) registers every handle in a module-level set and
   closes them all on pagehide/beforeunload. sse-bus doesn't see these
   streams, so it needs its own teardown.

3. sse.ts — server-side connection bookkeeping. Tracks managed SSE
   connections by clientId, supports client-triggered disconnect via
   POST /api/events/disconnect, stale-timer cleanup, and supersedes
   older streams when a client reconnects.

4. server.ts — exposes /api/events/disconnect and /api/events/keepalive
   under a dedicated 300 req/min rate limit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 11:09:29 +02:00
gsxdsm
c0f9260998 feat(dashboard): bearer-token auth with browser persistence + MIT license
Pre-release polish. Two related changes bundled because they both land the
project on public-release footing:

Dashboard auth
- fn dashboard now gates the HTTP API + terminal/badge WebSockets behind a
  bearer token by default. Token resolution order: --token flag,
  FUSION_DASHBOARD_TOKEN env, FUSION_DAEMON_TOKEN env (back-compat), or an
  auto-generated fn_<32 hex>. --no-auth disables. The startup banner prints
  a click-to-open URL with ?token=<token> embedded.
- Auth middleware now also accepts fn_token=<token> as a query-string
  fallback so EventSource and WebSocket clients (which can't set custom
  headers) still authenticate.
- setupTerminalWebSocket / setupBadgeWebSocket now refuse unauthenticated
  upgrades with a proper 401 + socket close.
- Frontend: new auth.ts module captures ?token= off the URL into
  localStorage (key fn.authToken), strips it from the visible URL via
  replaceState, and installs a window.fetch wrapper that injects
  Authorization: Bearer <token> on every same-origin /api/* request.
  EventSource/WebSocket URL builders (api.ts, sse-bus.ts, useTerminal,
  useBadgeWebSocket) route through appendTokenQuery().

MIT license
- LICENSE file at repo root.
- license: "MIT" on root package.json and every packages/*/package.json,
  plus description/bugs metadata on the CLI package.

Docs
- docs/cli-reference.md documents --token / --no-auth / FUSION_DASHBOARD_TOKEN
  and the click-to-open auth flow.
- docs/getting-started.md, docs/docker.md, README.md point at the new flow
  and the CLI reference section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 20:12:00 -07:00
Fusion
b80cae1b5a feat(FN-1850): aggregate projects across connected nodes
- Add /api/projects/across-nodes to merge local projects with online remote node project lists
- Expose fetchProjectsAcrossNodes and ProjectInfoWithSource, and switch useProjects to consume cross-node data
- Update ProjectOverview and ProjectCard with node badges, node count stats, and a node filter dropdown plus responsive styles
- Add server and dashboard test coverage for cross-node aggregation, filtering, and hook behavior changes
- Include a changeset for @gsxdsm/fusion minor release and preserve stale-channel SSE reconnect guards during merge
2026-04-18 03:08:00 -07:00
Fusion
01aeb449d7 fix(FN-2048): prevent stale SSE reconnects after channel teardown
- Add a closed flag to sse-bus channel state so teardown permanently disables reconnect scheduling
- Guard useTasks onReconnect callbacks against stale effect instances when toggling views
- Add regression tests for sse-bus and useTasks to ensure closed/unmounted channels do not reconnect
- Document the leak root cause and closed-flag pattern in .fusion/memory.md
2026-04-18 02:53:49 -07:00
Fusion
39e833b91e feat(FN-2014): merge fusion/fn-2014 2026-04-17 14:31:43 -07:00