Skip to content

fix(ui): show warning when live updates disabled due to missing web:read-pulse scope#8262

Merged
lotas merged 2 commits intotaskcluster:mainfrom
nitishagar:fix/8070-subscription-scope-warning
Feb 17, 2026
Merged

fix(ui): show warning when live updates disabled due to missing web:read-pulse scope#8262
lotas merged 2 commits intotaskcluster:mainfrom
nitishagar:fix/8070-subscription-scope-warning

Conversation

@nitishagar
Copy link
Contributor

@nitishagar nitishagar commented Feb 7, 2026

Summary

  • Add a visible warning banner when the GraphQL WebSocket connection is closed due to missing web:read-pulse scope
  • Track subscription connection errors in the App component and propagate to Main for display
  • Add server-side test verifying WebSocket rejection when scope is missing

Fixes #8070
Fixes #8261

Problem

When a user (or anonymous visitor) lacks the web:read-pulse scope, the GraphQL WebSocket connection is silently closed. The UI continues displaying stale data with no indication — task timers count up indefinitely, task states never refresh. The only way to discover this is by inspecting WebSocket traffic in browser devtools.

Solution

ui/src/App/index.jsx: In the existing connectionCallback that already catches InsufficientScopes errors, added this.setState({ subscriptionError: error }) to surface the error to the UI. Passes subscriptionError as a prop to Main.

ui/src/App/Main.jsx: Renders a persistent warning Snackbar (amber/warning variant) when subscriptionError is present. The banner is dismissible per session and resets on page refresh or user change (since Main remounts via its key prop).

services/web-server/test/graphql/tasks_graphql_test.js: Added test that verifies the WebSocket connection is properly rejected with InsufficientScopes when the web:read-pulse scope is missing. Confirms the server contract the UI fix depends on.

Test plan

  • Open a TaskGroup page without logging in — warning banner appears
  • Banner message: "Live updates are not available because you are missing the web:read-pulse scope. Task information on this page may be out of date. Try signing in or refreshing the page."
  • Clicking X dismisses the banner for the session
  • Refreshing the page shows the banner again
  • Logging in with web:read-pulse scope and refreshing — no banner
  • Pages without subscriptions (e.g., /auth/roles) do not show the banner
  • Existing web-server subscription tests still pass

@nitishagar nitishagar requested a review from a team as a code owner February 7, 2026 16:07
@nitishagar nitishagar requested review from lotas, matt-boris and petemoore and removed request for a team February 7, 2026 16:07
@nitishagar nitishagar force-pushed the fix/8070-subscription-scope-warning branch from df54bd6 to afa2625 Compare February 8, 2026 07:06
@lotas
Copy link
Contributor

lotas commented Feb 9, 2026

This looks good, thanks for adding PR for this.
Can you please check why web-server test is failing? That new test is probably missing something, maybe websocket server is not running?

@nitishagar nitishagar force-pushed the fix/8070-subscription-scope-warning branch from afa2625 to 50a1a4c Compare February 17, 2026 10:56
@nagarwal-godaddy
Copy link

Thanks for the review @lotas!

Good catch on the failing test. The WebSocket server was running fine — the issue was that the test was using subscriptionClient.onError() to detect the connection rejection, but subscriptions-transport-ws only fires onError for WebSocket transport-level errors (socket onerror), not for GraphQL GQL_CONNECTION_ERROR messages. The server's scope rejection is delivered via connectionCallback instead, so neither onConnected nor onError ever fired, causing the test to hang until timeout.

Fixed by switching to the connectionCallback option in the SubscriptionClient constructor.

I also added a separate commit to fix #8261 (webpack-dev-server ECONNRESET crash when proxying the /subscription endpoint) by adding onError and onProxyReqWs handlers to the proxy config.

};

handleSubscriptionWarningClose = () => {
this.setState({ subscriptionWarningDismissed: true });
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is a good option, if permissions are missing we would show this error in a Snackbar.
User might click close/dismiss and we would save in state that it was dismissed.
So user will not be shown this again (until page is hard refreshed I think)
Probably not an issue for this kind of error 👍

Copy link
Contributor

@lotas lotas left a comment

Choose a reason for hiding this comment

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

Thank you for both fixes!

@lotas lotas merged commit 2f83177 into taskcluster:main Feb 17, 2026
73 checks passed
@nitishagar nitishagar deleted the fix/8070-subscription-scope-warning branch February 19, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants