Skip to content

Commit 048a69b

Browse files
priosshrsthclaude
andcommitted
OUT-4093 | Drop the Storage Access API gate on the assignee cache
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) <noreply@anthropic.com>
1 parent 6f8145c commit 048a69b

2 files changed

Lines changed: 48 additions & 17 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const mockGetItem = jest.fn()
2+
const mockSetItem = jest.fn()
3+
4+
jest.mock('localforage', () => ({
5+
__esModule: true,
6+
default: {
7+
config: jest.fn(),
8+
getItem: (...args: unknown[]) => mockGetItem(...args),
9+
setItem: (...args: unknown[]) => mockSetItem(...args),
10+
},
11+
}))
12+
13+
import { getAssignees, setAssignees } from '@/app/_cache/forageStorage'
14+
15+
const denied = () => new DOMException('Access is denied for this document.', 'SecurityError')
16+
17+
describe('assignee cache', () => {
18+
beforeAll(() => {
19+
globalThis.window = {} as Window & typeof globalThis
20+
})
21+
afterAll(() => {
22+
delete (globalThis as { window?: unknown }).window
23+
})
24+
beforeEach(() => jest.clearAllMocks())
25+
26+
it('returns an empty list when storage access is denied', async () => {
27+
mockGetItem.mockRejectedValue(denied())
28+
29+
await expect(getAssignees('lookup-key')).resolves.toEqual([])
30+
expect(mockGetItem).toHaveBeenCalledWith('assignees.lookup-key')
31+
})
32+
33+
it('swallows write failures when storage access is denied', async () => {
34+
mockSetItem.mockRejectedValue(denied())
35+
36+
await expect(setAssignees('lookup-key', [])).resolves.toBeUndefined()
37+
expect(mockSetItem).toHaveBeenCalledWith('assignees.lookup-key', [])
38+
})
39+
40+
it('returns an empty list when nothing is cached', async () => {
41+
mockGetItem.mockResolvedValue(null)
42+
43+
await expect(getAssignees('lookup-key')).resolves.toEqual([])
44+
})
45+
})

src/app/_cache/forageStorage.ts

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,19 @@ export async function getAssignees(lookupKey: string): Promise<IAssigneeCombined
1212
if (typeof window === 'undefined') return []
1313

1414
try {
15-
if (!(await document.hasStorageAccess())) {
16-
console.info('Browswer has no storage access')
17-
await document.requestStorageAccess()
18-
}
19-
2015
return (await localforage.getItem<IAssigneeCombined[]>(`assignees.${lookupKey}`)) ?? []
2116
} catch (error: unknown) {
22-
console.error(
23-
"Storage access not granted. Under Chrome's Settings > Privacy and Security, make sure 'Third-party cookies' is allowed.",
24-
)
17+
console.info('Assignee cache unavailable, falling back to network', error)
2518
return []
2619
}
2720
}
2821

29-
export async function setAssignees(lookupKey: string, value: any) {
22+
export async function setAssignees(lookupKey: string, value: IAssigneeCombined[]) {
3023
if (typeof window === 'undefined') return
3124

3225
try {
33-
if (!(await document.hasStorageAccess())) {
34-
console.info('Browswer has no storage access')
35-
await document.requestStorageAccess()
36-
}
37-
3826
return await localforage.setItem(`assignees.${lookupKey}`, value)
3927
} catch (error: unknown) {
40-
console.error(
41-
"Storage access not granted. Under Chrome's Settings > Privacy and Security, make sure 'Third-party cookies' is allowed.",
42-
)
28+
console.info('Assignee cache write skipped, storage unavailable', error)
4329
}
4430
}

0 commit comments

Comments
 (0)