Repository navigation
Conversation
…oken Since 3.10.0 the service worker only treated a 401 as final when the body was wrapped in `data`, which only the verify controller does. A token the auth middleware rejects (expired, revoked, entitlement removed) comes back from the error handler unwrapped, so the extension kept the dead session, never asked the user to sign in again, and record sync failed with 401s. A 401 no longer clears a token that Chrome Sync replaced while the request was in flight, so a rotation on another install does not sign everyone out.
Any UI API picklist-values failure other than "not supported in UI API" threw and replaced the whole view/edit modal with a generic "make sure the record id is valid" error. The record form now falls back to the describe's picklist values, and the modal shows the real error when loading fails.
Monaco 0.55+ keeps its workers in vs/assets, which the extension copy step skipped, so every editor fell back to running language services on the main thread. The TypeScript worker is left out because no extension editor uses JavaScript or TypeScript and it is 6.7MB.
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
Cross-install token synchronization and packaged Monaco worker startup still need browser-level validation.
No open issues 🎉
What changed in this PR
Fixes extension authentication recovery, record-form loading resilience, and Monaco worker packaging.
Changes:
- Recognizes middleware token rejections while preserving tokens replaced during verification.
- Falls back to describe picklist values and displays actual record-loading errors.
- Packages Monaco workers, excluding the unused TypeScript worker.
| File | Description |
|---|---|
| scripts/copy-monaco-assets.mjs | Copies required Monaco worker assets. |
| libs/shared/ui-record-form/src/lib/ui-record-form-utils.ts | Falls back on UI API failures. |
| libs/shared/ui-record-form/src/lib/__tests__/ui-record-form-utils.spec.ts | Tests picklist fallback behavior. |
| libs/shared/ui-core/src/record/ViewEditCloneRecord.tsx | Displays underlying loading errors. |
| apps/jetstream-web-extension/src/extension-scripts/service-worker.ts | Handles token rejection and concurrent replacement. |
| apps/jetstream-web-extension/src/extension-scripts/__tests__/service-worker.spec.ts | Covers middleware errors and token replacement. |
Review effort: Balanced
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three fixes, one commit each. Two came out of triaging the production extension's
chrome://extensionserrors page; the record modal one is from a user report.1. The extension never signs out when Jetstream rejects its token
handleVerifyAuthonly treated a 401 as final when the body was{ data: { success: false } }, which only the verify controller produces. A token the auth middleware rejects (expired, revoked, entitlement removed) never reaches the controller: the API error handler answers{ error: true, success: false, message }, so the service worker filed it as transient, kept the dead session, and retried on every check. The user never saw the sign-in screen, and record sync kept failing with 401s ([DB] Error initializing db Error: Unauthorized). Regression from 5a3c66e, shipped in 3.10.0.Prod API logs, 10-10 → 10-17: ~1,000 "Access token is invalid for device" rejections across 30 devices, 602
/web-extension/data-sync/push401s (470 from one device over 8 days), and 399 verify 401s against 96 200s. One device was rejected for "Browser extension is not enabled" and kept working, so this also closes an entitlement gap.jsonResponsehelper always wrapped bodies indata, which is why tests never caught this; new tests use the error handler's real body.2. View/Edit Record modal: "There was a problem loading the record information"
getPicklistValuesForRecordAndRecordTyperethrew any UI API failure except "not supported in UI API", which replaced the whole modal with a generic "make sure the record id is valid" error (missing records are handled separately, so that hint was misleading). It now falls back to the describe's picklist values on any failure, and the modal shows the real error message. Also applies to Create Records and the web app.3. Monaco workers missing from the extension
Monaco 0.55+ keeps its workers in
min/vs/assets/, which the extension's copy step skipped, soimportScripts404'd and every editor ran language services on the main thread ("Could not create web worker(s)"). The error tracker ignores/js/monaco/vs/, so it never surfaced. The copy now includesassets/minus the 6.7MB TypeScript worker (no extension editor uses JS/TS); +2.6MB. Separate from #2153's Canvas CSP fix.Testing
jetstream-web-extension,shared-ui-record-form,ui-coretests + typecheck pass; oxlint clean.pnpm build:web-extensionpackagesvs/assets/{editor,json,css,html}.worker-*.jsmatching the hasheseditor.main.jsreferences.Expected after release
The ~30 devices currently stuck on a dead session will see the extension's sign-in screen once.
Not in this PR
defaultApiVersionby design (chore: read the Salesforce API version from one shared constant #2151), and the picklist fallback keeps the modal working on an older org anyway.TOKEN_AUTO_REFRESH_DAYSwould fix that; left as a product decision.