Offline read cache for recent entries/motifs #122

Closed
opened 2026-07-15 19:53:44 +00:00 by claude-bot · 1 comment
Contributor

Feature idea (audit Phase 5, rank #5) · Effort: medium

Why
The PWA offline story is capture-only (IndexedDB queue); reading is online-only (the service worker deliberately doesn't cache /api/*). A mobile researcher on the go can't review recent work offline.

Proposal
Add a narrow, auth-aware cache of recently-viewed entries/motifs for offline reading - explicitly NOT a blanket /api cache (must respect the security invariant that authenticated API responses aren't cached by the service worker). Store in IndexedDB, keyed to the logged-in user, cleared on logout.

Why it was likely missed
"Offline" was scoped narrowly to capture, to avoid caching authenticated data.

Acceptance criteria

  • Recently-viewed entries/motifs are readable offline.
  • The service worker still does not cache /api/*; the cache is app-managed and cleared on logout.

Filed from the 2026-07-15 codebase audit. Full report: docs/.internal/report-2026-07-15.md (gitignored).

**Feature idea** (audit Phase 5, rank #5) · Effort: medium **Why** The PWA offline story is capture-only (IndexedDB queue); reading is online-only (the service worker deliberately doesn't cache `/api/*`). A mobile researcher on the go can't review recent work offline. **Proposal** Add a narrow, auth-aware cache of recently-viewed entries/motifs for offline reading - explicitly NOT a blanket `/api` cache (must respect the security invariant that authenticated API responses aren't cached by the service worker). Store in IndexedDB, keyed to the logged-in user, cleared on logout. **Why it was likely missed** "Offline" was scoped narrowly to capture, to avoid caching authenticated data. **Acceptance criteria** - [ ] Recently-viewed entries/motifs are readable offline. - [ ] The service worker still does not cache `/api/*`; the cache is app-managed and cleared on logout. --- _Filed from the 2026-07-15 codebase audit. Full report: `docs/.internal/report-2026-07-15.md` (gitignored)._
Author
Contributor

Done — shipped in v9.3.0 (PR #142, merge c69897c).

app/src/lib/offlineCache.ts — a separate, app-managed IndexedDB database (tealeaves-read-cache), records keyed by type:id and stamped with the current user id. Entry/Motif detail pages cacheItem on successful view and fall back to getCachedRecord when a fetch fails offline, rendering the cached copy with an "Offline — cached copy from …" banner. clearReadCache() runs on logout (Shell.handleLogout). Pruned to ~100 records/type. Cache failures are swallowed so they can never break a page.

Acceptance: recently-viewed entries/motifs readable offline · the service worker still does not cache /api/* (this is app-managed, not a SW cache) and the cache is cleared on logout. Unit tests cover cross-user isolation, the prune cap, clear-on-logout, and graceful behavior when IndexedDB is unavailable.

Done — shipped in **v9.3.0** (PR #142, merge `c69897c`). `app/src/lib/offlineCache.ts` — a separate, app-managed IndexedDB database (`tealeaves-read-cache`), records keyed by `type:id` and stamped with the current user id. Entry/Motif detail pages `cacheItem` on successful view and fall back to `getCachedRecord` when a fetch fails offline, rendering the cached copy with an "Offline — cached copy from …" banner. `clearReadCache()` runs on logout (`Shell.handleLogout`). Pruned to ~100 records/type. Cache failures are swallowed so they can never break a page. **Acceptance:** ✅ recently-viewed entries/motifs readable offline · ✅ the service worker still does **not** cache `/api/*` (this is app-managed, not a SW cache) and the cache is cleared on logout. Unit tests cover cross-user isolation, the prune cap, clear-on-logout, and graceful behavior when IndexedDB is unavailable.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/TeaLeaves#122
No description provided.