Skip to content

OUT-4093 | Stop reading localStorage in the assignee cache - #1434

Merged
priosshrsth merged 2 commits into
mainfrom
anit/out-4093-securityerror-failed-to-read-the-localstorage-property-from
Aug 24, 2026
Merged

OUT-4093 | Stop reading localStorage in the assignee cache#1434
priosshrsth merged 2 commits into
mainfrom
anit/out-4093-securityerror-failed-to-read-the-localstorage-property-from

Conversation

@priosshrsth

Copy link
Copy Markdown
Collaborator

Fixes the Sentry SecurityError: Failed to read the 'localStorage' property from 'Window' (OUT-4093, TASKS-9X) by deleting the code that read localStorage rather than guarding it. Net -25 lines in forageStorage.ts.

migrateAssignees() touched window.localStorage, which throws on property access when Chrome blocks third-party storage in our iframe. It shipped in OUT-2348 eleven months ago tagged "remove this after a while" and only moved a cache, so unmigrated users just re-fetch over the network.

What to look at:

  • forageStorage.ts — the hasStorageAccess()/requestStorageAccess() gate is gone. It reports access to unpartitioned cookies, but the cache is IndexedDB; MDN documents it returning false where third-party access is actually fine, which fed into a requestStorageAccess() that is auto-denied without a user gesture (there is none in AssigneeCacheGetter's mount effect). It disabled the cache for the users it was meant to protect. The existing try/catch already degrades to a network fetch.
  • forageStorage.test.ts — stubs globalThis.window because jest-environment-jsdom isn't installed. The toHaveBeenCalledWith assertions are load-bearing: without them the tests pass vacuously via the typeof window === 'undefined' early return.

Verified: yarn tsc clean; grep -rn localStorage src/ empty, so no path can still throw this; 3 new tests pass. The 10 failures in withErrorHandler/authenticate reproduce on a clean main and are unrelated.

Not verified: the cache actually populating in a real Chrome iframe with third-party cookies blocked. That upside rests on documentation, not observation — the crash fix does not.

Supersedes #1407, which guarded the migration instead of removing it.

priosshrsth and others added 2 commits August 24, 2026 09:15
Accessing window.localStorage throws SecurityError when Chrome blocks
third-party storage for the embedded iframe, and migrateAssignees read it
unguarded. The migration shipped in OUT-2348 eleven months ago and only
moved a cache; anything unmigrated by now just re-fetches over the network.

Fixes TASKS-9X

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
hasStorageAccess() reports access to unpartitioned *cookies*; the cache
lives in IndexedDB, so it was the wrong signal. MDN documents it returning
false in browsers that don't block third-party access by default, which sent
us into requestStorageAccess() — automatically denied without a user gesture,
and there is none during AssigneeCacheGetter's mount effect. Net effect: the
gate disabled the cache for the users it was meant to protect, and threw on
Chrome 111, which predates the API.

The surrounding try/catch already degrades to a network fetch when storage is
genuinely denied, which is what MDN recommends instead of the gate.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@linear-code

linear-code Bot commented Aug 24, 2026

Copy link
Copy Markdown

OUT-4093

@vercel

vercel Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tasks-app Ready Ready Preview Aug 24, 2026 9:23am

Request Review

@greptile-apps

greptile-apps Bot commented Aug 24, 2026

Copy link
Copy Markdown

Greptile Summary

The PR removes the obsolete localStorage-to-localforage migration and the Storage Access API gate from the assignee cache, allowing storage failures to degrade safely to network fetching.

  • Removes the remaining direct localStorage access from assignee cache initialization.
  • Reads and writes localforage directly behind existing error handling.
  • Narrows the cache setter type and adds tests for denied or empty storage.

Confidence Score: 5/5

The PR appears safe to merge, with assignee cache failures continuing to fall back to the existing network-fetch path.

The removed migration only warmed an optimization cache, current cache callers use compatible data types, and failed localforage reads or writes remain contained without preventing network population of assignees.

Important Files Changed

Filename Overview
src/app/_cache/AssigneeCacheGetter.tsx Removes the legacy migration call while preserving the IndexedDB read and network-backed population flow.
src/app/_cache/forageStorage.ts Removes localStorage migration and Storage Access API calls, retaining graceful read/write failure handling.
src/app/_cache/forageStorage.test.ts Adds focused tests confirming denied storage operations and empty cache reads resolve safely.

Reviews (1): Last reviewed commit: "OUT-4093 | Drop the Storage Access API g..." | Re-trigger Greptile

@priosshrsth priosshrsth self-assigned this Aug 24, 2026

@SandipBajracharya SandipBajracharya left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. Just verifying: if we return empty array then the app fetches from the assignees from backend right?

@priosshrsth
priosshrsth merged commit 1327cf7 into main Aug 24, 2026
4 checks passed
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.

2 participants