Skip to content

fix(browser): sign the live-view stream socket, not just the auth socket - #1190

Merged
philmerrell merged 2 commits into
developfrom
fix/browser-live-view-unsigned-stream-socket
Sep 19, 2026
Merged

philmerrell merged 2 commits into
developfrom
fix/browser-live-view-unsigned-stream-socket

Conversation

@philmerrell

Copy link
Copy Markdown
Contributor

What

connect reads httpExtraSearchParams only from observers. We passed it at the top level, where it is silently ignored — so the stream socket opened with no query string at all, unsigned, and the service refused it.

Measured

Running the shipped DCV 1.13.2 bundle against a stubbed WebSocket:

placement resulting socket
top level (ours) wss://…/live-view/ws — UNSIGNED
observers (AWS's) wss://…/live-view/ws?X-Amz-Algorithm=… — signed

This is exactly what the browser console showed all along: repeated failures to /live-view/ws carrying no parameters. I had read those as fallout from the earlier auth failure; they were a second, independent bug.

authenticate is the opposite — it reads the callback from the top level — which is precisely what made the top-level form look correct for both. The two entry points genuinely differ, and nothing in the surface hints at it.

firstFrame/disconnect move into observers with it, since the SDK honours observers or callbacks and not both.

Cross-checked against AWS's own BrowserLiveView, read from the published package rather than guessed: it uses observers: { httpExtraSearchParams } too.

Correction to #1189

#1189 claimed the doubled-SigV4-parameter theory was the cause. Running the real SDK disproves it: it produces exactly one X-Amz-Signature whether or not the URL still carries its query, because it replaces the query rather than appending. #1189 is behaviourally neutral, not a fix. The 403-on-doubled-params probe was real, but we were never sending that form.

Tests

Asserts the connect config shape: httpExtraSearchParams present in observers, absent at top level, and no callbacks alongside. Mutation-checked — restoring the top-level form fails it. Suite 873 pass, tsc --noEmit clean.

Still open

authenticate intermittently fails with code 10 before connect is reached. One hypothesis worth testing after this lands: the unsigned /ws retry loop leaves the SDK's network monitor wedged ("No transition available") and poisons subsequent attempts. Not yet proven.

🤖 Generated with Claude Code

philmerrell and others added 2 commits September 19, 2026 14:59
`connect` reads `httpExtraSearchParams` ONLY from `observers`. We passed it
at the top level, where it is silently ignored — so the stream socket opened
with no query string at all, unsigned, and the service refused it.

Measured by running the shipped 1.13.2 bundle against a stubbed WebSocket:

  top-level  -> wss://.../live-view/ws                  (UNSIGNED)
  observers  -> wss://.../live-view/ws?X-Amz-Algorithm= (signed)

That is exactly what the browser console showed: repeated failures to
`/live-view/ws` carrying no parameters. `authenticate` is the opposite — it
reads the callback from the top level — which is what made the top-level
form look right. The two entry points genuinely differ.

`firstFrame`/`disconnect` move into `observers` with it, because the SDK
honours observers or callbacks and not both.

This is also what AWS's own BrowserLiveView component does; its config was
read from the published package rather than guessed.

Mutation-checked: restoring the top-level form fails the new assertion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`.connprobe.mjs` was a throwaway jsdom harness used to capture the DCV
SDK's WebSocket URL. Its cleanup `rm` sat in the same command line as a
node process that never exited, so `git add -A` swept it into the branch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant