From 6aed0dd275d63e67cf4e3ecaf39e26163a8185e1 Mon Sep 17 00:00:00 2001 From: TheFlow Date: Fri, 24 Oct 2025 18:34:06 +1300 Subject: [PATCH] fix(cache): prevent caching of admin files and API responses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITICAL FIX: Automatic cache invalidation for admin JavaScript files. Root cause: Service worker and browser cache serving stale admin files even after deploying fixes. Users had to manually clear cache daily. Changes: 1. Service Worker (v0.1.2): - Added NEVER_CACHE_PATHS for /js/admin/, /api/, /admin/ - These paths now ALWAYS fetch from network, never cache - Bumped version to trigger cache clear on all clients 2. Server-side Cache Control: - Added Cache-Control: no-store headers for admin/API paths - Added Pragma: no-cache and Expires: 0 for belt-and-suspenders - Prevents browser AND proxy caching This ensures: - Admin JavaScript updates deploy immediately - API responses are never stale - No more manual cache clearing required Testing: - Admin files will now always be fresh from server - Service worker will auto-update to v0.1.2 on next visit - Browsers will respect no-cache headers going forward 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- public/service-worker.js | 19 ++++++++++++++++++- src/middleware/security-headers.middleware.js | 9 +++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/public/service-worker.js b/public/service-worker.js index 5d2f2390..47189d5c 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -5,10 +5,17 @@ * - PWA functionality */ -const CACHE_VERSION = '0.1.1'; +const CACHE_VERSION = '0.1.2'; const CACHE_NAME = `tractatus-v${CACHE_VERSION}`; const VERSION_CHECK_INTERVAL = 3600000; // 1 hour in milliseconds +// Paths that should NEVER be cached (always fetch fresh from network) +const NEVER_CACHE_PATHS = [ + '/js/admin/', // Admin JavaScript - always fresh + '/api/', // API calls + '/admin/' // Admin pages +]; + // Assets to cache immediately on install const CRITICAL_ASSETS = [ '/', @@ -61,6 +68,16 @@ self.addEventListener('fetch', (event) => { return; } + // NEVER CACHE: Admin files, API calls - always fetch fresh, never cache + if (NEVER_CACHE_PATHS.some(path => url.pathname.startsWith(path))) { + event.respondWith( + fetch(request).catch(() => { + throw new Error('Network required for admin/API resources'); + }) + ); + return; + } + // HTML files: Network-ONLY (never cache, always fetch fresh) // This ensures users always get the latest content without cache refresh if (request.destination === 'document' || url.pathname.endsWith('.html')) { diff --git a/src/middleware/security-headers.middleware.js b/src/middleware/security-headers.middleware.js index fd3ffdfd..9c4c5fe5 100644 --- a/src/middleware/security-headers.middleware.js +++ b/src/middleware/security-headers.middleware.js @@ -56,6 +56,15 @@ function securityHeadersMiddleware(req, res, next) { 'geolocation=(), microphone=(), camera=(), payment=()' ); + // Cache Control: NEVER cache admin files or API responses + if (req.path.startsWith('/admin/') || + req.path.startsWith('/js/admin/') || + req.path.startsWith('/api/')) { + res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); + res.setHeader('Pragma', 'no-cache'); + res.setHeader('Expires', '0'); + } + next(); }