diff --git a/public/sw.js b/public/sw.js index fd60ece14..499698631 100644 --- a/public/sw.js +++ b/public/sw.js @@ -51,6 +51,16 @@ const PAGE_CACHE = `healthlog-pages-${CACHE_VERSION}`; // next paint. Network-first restores read-after-write freshness while keeping // the offline fallback. const DATA_CACHE = `healthlog-data-${CACHE_VERSION}`; +// Keep this ownership contract aligned with +// `clearOfflineCachesForSessionEnd()` in `query-persister.ts`. Cache cleanup +// must cover every current/legacy HealthLog cache without deleting unrelated +// CacheStorage namespaces owned by another app on the same origin. +const HEALTHLOG_CACHE_NAME_RE = /^healthlog-(?:static|pages|data)-/; +const CURRENT_HEALTHLOG_CACHES = new Set([ + STATIC_CACHE, + PAGE_CACHE, + DATA_CACHE, +]); const MAX_STATIC_ENTRIES = 150; const MAX_PAGE_ENTRIES = 30; const MAX_DATA_ENTRIES = 60; @@ -136,7 +146,8 @@ self.addEventListener("activate", (event) => { keys .filter( (k) => - k !== STATIC_CACHE && k !== PAGE_CACHE && k !== DATA_CACHE, + HEALTHLOG_CACHE_NAME_RE.test(k) && + !CURRENT_HEALTHLOG_CACHES.has(k), ) .map((k) => caches.delete(k)), ), diff --git a/src/lib/pwa/query-persister.ts b/src/lib/pwa/query-persister.ts index 3fc3e2067..805b44f04 100644 --- a/src/lib/pwa/query-persister.ts +++ b/src/lib/pwa/query-persister.ts @@ -39,6 +39,10 @@ const STORE = "kv"; const KEY = "react-query"; const VERSION_KEY = "react-query-version"; const MAX_AGE_MS = 24 * 60 * 60 * 1000; // discard anything older than a day +// Keep this ownership contract aligned with `public/sw.js`. Session-end +// cleanup removes every current/legacy HealthLog cache family while leaving +// unrelated CacheStorage namespaces on the same origin untouched. +const HEALTHLOG_CACHE_NAME_RE = /^healthlog-(?:static|pages|data)-/; /** * Upper bound on the serialized snapshot. The allowlist already caps WHAT is @@ -326,11 +330,7 @@ export async function clearOfflineCachesForSessionEnd(): Promise { const keys = await caches.keys(); await Promise.all( keys - .filter( - (k) => - k.startsWith("healthlog-data-") || - k.startsWith("healthlog-pages-"), - ) + .filter((k) => HEALTHLOG_CACHE_NAME_RE.test(k)) .map((k) => caches.delete(k)), ); } catch {