fix(mobile): accept only a full digest shape as an already-digested tab id

This commit is contained in:
Jinwoo-H
2026-09-07 14:36:06 -04:00
parent 2785354322
commit e7a4aa1377
2 changed files with 16 additions and 1 deletions
+13
View File
@@ -221,6 +221,19 @@ describe('session tab strip cache', () => {
expect(loaded?.activeTabId).toBe(digested)
})
it('digests a wire id that merely starts with the digest prefix', async () => {
const key = getSessionTabStripCacheKey('host-1', 'wt-1')
const id = 'cached:/Users/someone/private-file.md'
saveCachedSessionTabStrip(key, {
tabs: [{ id, type: 'file', title: 'x', agentId: null }],
activeTabId: id
})
await vi.advanceTimersByTimeAsync(300)
expectDigestedIds(readCachedSessionTabStrip(key)?.tabs.map((tab) => tab.id) ?? [], 1)
expect(String(asyncStorage.setItem.mock.calls.at(-1)?.[1])).not.toContain('private-file')
})
it('keeps only a known agent id, since the hook-reported one is free text', async () => {
const key = getSessionTabStripCacheKey('host-1', 'wt-1')
saveCachedSessionTabStrip(key, {
+3 -1
View File
@@ -27,6 +27,8 @@ const WRITE_DEBOUNCE_MS = 250
// the stored blob stays small.
const WORKSPACE_DIGEST_LENGTH = 32
const TAB_DIGEST_PREFIX = 'cached:'
// The whole shape, not the prefix: a wire id that merely starts with the prefix is still wire text.
const DIGESTED_TAB_ID = /^cached:[0-9a-f]{32}$/
type StoredWorkspace = { key: string; preview: MobileSessionTabStripPreview }
type StoredFile = { workspaces: StoredWorkspace[] }
@@ -150,7 +152,7 @@ function digestWorkspaceId(worktreeId: string): string {
// Prefixed so a raw id can never be mistaken for one already digested, and so a live tab's
// id can never collide with a stored row's by construction.
function digestTabId(tabId: string): string {
return tabId.startsWith(TAB_DIGEST_PREFIX) ? tabId : `${TAB_DIGEST_PREFIX}${digestHex(tabId)}`
return DIGESTED_TAB_ID.test(tabId) ? tabId : `${TAB_DIGEST_PREFIX}${digestHex(tabId)}`
}
function digestHex(value: string): string {