fix(ui): pose stream WebSocket 401s when RUVIEW_API_TOKEN is set (#1461) (#1462)

websocket.service.js (used by the pose/event streams) opened a bare
`new WebSocket(url)` with no ADR-272 ticket exchange, unlike
sensing.service.js which already mints a ticket per connect. Since a
browser cannot set an Authorization header on a WebSocket upgrade, and
the server rejects a long-lived bearer passed as a query string
(CWE-598), the pose stream 401'd whenever auth was on — visible in the
Live Demo tab as "Failed to create WebSocket connection".

Fix: createWebSocketWithTimeout() now strips any `token` query param a
caller put on the URL (pose.service.js does this) and exchanges the
stored bearer for a single-use `?ticket=` via withWsTicket(), done at
this one choke point so every consumer (pose, events, training) and
every reconnect attempt gets a fresh ticket.

Second, smaller bug: pose-fusion/js/main.js auto-connected to a
hardcoded `ws://localhost:8765/ws/sensing`, but the Docker image serves
the sensing WebSocket on :3001 (the same 3000->3001 mapping
sensing.service.js already encodes) — the auto-connect dialed a port
nothing listens on. Reuses that port mapping and tickets both the
auto-connect and the manual "Connect" button.

Bumped the pose-fusion.html cache-buster (v=13 -> v=14) so browsers
actually fetch the updated main.js.

Adds ui/services/websocket.service.test.mjs (4 executed Node tests,
stubbed WebSocket/fetch/localStorage) covering: no-auth passthrough,
ticket exchange + bearer-never-in-URL, stray ?token= stripping, and the
pre-ADR-272 404 fallback. Wired into the CI "Run UI unit tests" step.

Reported with a verified fix in #1461 by wsc7r4zcj4-collab; this PR
implements the same fix against current main with an added regression
test.

Closes #1461
This commit is contained in:
rUv
2026-07-28 10:59:00 -04:00
committed by GitHub
parent e6062977c9
commit a70ca90525
5 changed files with 129 additions and 7 deletions
+1 -1
View File
@@ -204,7 +204,7 @@ jobs:
node-version: '22'
- name: Run UI unit tests
run: node --test ui/sw.test.mjs ui/services/ws-ticket.test.mjs
run: node --test ui/sw.test.mjs ui/services/ws-ticket.test.mjs ui/services/websocket.service.test.mjs
# Unit and Integration Tests
# Python pytest matrix — runs against the archived v1 Python tree.