Skip to content

State Tool: forward platform JWT + version User-Agent on the build-log-streamer WebSocket#3809

Draft
antoine-activestate wants to merge 1 commit into
masterfrom
antoines/ENG-1372
Draft

State Tool: forward platform JWT + version User-Agent on the build-log-streamer WebSocket#3809
antoine-activestate wants to merge 1 commit into
masterfrom
antoines/ENG-1372

Conversation

@antoine-activestate
Copy link
Copy Markdown
Contributor

@antoine-activestate antoine-activestate commented Jun 1, 2026

Summary

Makes the State Tool identify itself on the build-log-streamer WebSocket Upgrade so the server can authorize the stream and monitor connecting client versions.

  1. Platform JWT via Sec-WebSocket-Protocol. When authenticated, the client offers bearer.<jwt> alongside the real subprotocol build-log-streamer.activestate.com.v1 (which the server echoes back; its allow-list contains only the real one, so the token never appears in the upgrade response). The browser WebSocket API can't set custom request headers, so the dashboard carries the JWT the same way — both clients stay symmetric.
  2. Versioned User-Agent on the Upgrade (constants.UserAgent) so the server can see which State Tool versions are connecting.

Design note

The token is threaded as a plain string (prime.Auth().BearerToken() → runtime option → Connect), so pkg/runtime gains no dependency on the authentication package. Empty token = anonymous (unchanged behavior).

Test plan

  • go build + gofmt clean across touched packages.
  • Real-handshake test against an httptest WebSocket server asserting the offered subprotocols, the negotiated subprotocol (token never echoed back), and the User-Agent the server receives. go test -race clean.

Note

Full server-side JWT validation ships separately (infra repo); this client change degrades gracefully against the current server — an unknown subprotocol is ignored and anonymous still works.

Supersedes #3808 (closed when its branch was shortened to fix a macOS/Windows integration-test socket-path overflow).

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the State Tool’s build-log-streamer WebSocket connection to forward identifying/auth data during the HTTP Upgrade so the server can authorize streams and monitor client versions.

Changes:

  • Thread a platform JWT through runtime setup into build-log streaming, and offer it via Sec-WebSocket-Protocol as bearer.<jwt> alongside the real subprotocol.
  • Send the standard, versioned User-Agent on the WebSocket Upgrade request.
  • Add a new handshake-focused test that validates the server receives the expected Sec-WebSocket-Protocol and User-Agent headers.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pkg/runtime/setup.go Adds Opts.AuthToken and passes it into build-log streaming initialization.
pkg/runtime/options.go Introduces WithAuthToken runtime option for forwarding the platform JWT.
pkg/runtime/internal/buildlog/buildlog.go Stores the auth token on BuildLog and forwards it into the WS connect call.
pkg/platform/api/buildlogstream/streamer.go Updates Connect to set subprotocols (including optional bearer.<jwt>) and send the versioned User-Agent.
pkg/platform/api/buildlogstream/streamer_test.go Adds tests performing a real WS handshake and asserting request headers received by the server.
pkg/platform/api/api.go Extracts package-level UserAgent() for reuse by the WS dialer.
internal/runbits/runtime/runtime.go Wires prime.Auth().BearerToken() into runtime options via WithAuthToken.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/platform/api/buildlogstream/streamer_test.go
Comment thread pkg/platform/api/buildlogstream/streamer_test.go Outdated
Comment thread pkg/platform/api/buildlogstream/streamer_test.go Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Comment thread pkg/platform/api/buildlogstream/streamer_test.go
Comment thread pkg/platform/api/buildlogstream/streamer_test.go Outdated
Comment thread pkg/platform/api/buildlogstream/streamer_test.go
Comment thread pkg/platform/api/buildlogstream/streamer_test.go
Comment thread pkg/platform/api/buildlogstream/streamer_test.go
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

@antoine-activestate antoine-activestate marked this pull request as ready for review June 1, 2026 19:42
@mitchell-as mitchell-as self-requested a review June 1, 2026 19:43
Comment thread pkg/platform/api/buildlogstream/streamer.go Outdated
Comment thread pkg/platform/api/buildlogstream/streamer.go Outdated
Comment thread pkg/platform/api/api.go Outdated
Comment thread pkg/runtime/options.go Outdated
… WebSocket

The build-log-streamer WebSocket previously opened with only an Origin header, so the server had no way to authorize the stream. When the caller is authenticated, offer the platform JWT via Sec-WebSocket-Protocol as 'bearer.<jwt>' alongside the real 'build-log-streamer.activestate.com.v1' subprotocol the server echoes back (its allow-list contains only the real subprotocol, so the token never appears in the upgrade response). The browser WebSocket API can't set custom request headers, so the dashboard carries the JWT the same way -- both clients stay symmetric.

Also send the versioned State Tool User-Agent on the Upgrade so the server can see which client versions are connecting.

The token is threaded as a plain string from the runtime options into Connect, so pkg/runtime gains no authentication dependency; an empty token means anonymous (unchanged behavior). Includes a real-handshake test that asserts the offered subprotocols, the negotiated subprotocol, and the User-Agent the server receives.
@mitchell-as
Copy link
Copy Markdown
Collaborator

mitchell-as commented Jun 1, 2026

I enabled the "critical" integration tests. We don't care so much about the ARM tests because those are expected to fail (we don't have any ARM Platform projects). However, I am seeing some concerning failures:

State Tool for the most part runs unauthenticated. This is by design.

@antoine-activestate antoine-activestate changed the title ENG-1372: State Tool forwards platform JWT (+ versioned User-Agent) on build-log-streamer WS State Tool: forward platform JWT + version User-Agent on the build-log-streamer WebSocket Jun 1, 2026
@antoine-activestate
Copy link
Copy Markdown
Contributor Author

Dug into the three critical-suite failures — they're pre-existing, not introduced by this PR.

The scheduled (nightly) integration suite on master has been red for ≥16 consecutive nights (back through at least 2026-05-17). The most recent nightly — Jun 1 01:04 UTC, on unchanged master, before this PR's latest push — fails on the identical TestInstallIntegrationTestSuite/TestInstall with Build expr for the commit not found: Error retrieving commit … for project ActiveState-CLI/small-python, authentication may be required.

That's a buildplanner dependency-resolution failure (state install → stage commit), which runs upstream of the build-log streaming this PR touches. My only addition to that path is prime.Auth().BearerToken() — a pure getter with no side effects — and the unauthenticated path is unchanged (empty token → anonymous, as today). So this PR doesn't introduce these.

I'm raising the busted nightly as its own issue so it gets a dedicated fix (it looks platform-side — build-expr retrieval for the small-python test commit). The ARM failures are expected per your note.

@antoine-activestate antoine-activestate marked this pull request as draft June 2, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants