Files
2026-05-27 23:29:53 +01:00

5.2 KiB

Tasks: enterprise-browser-cache-browser

Change ID: enterprise-browser-cache-browser Package: @suaveplan/cache-browser Target path: browser/storage/cache-browser Prerequisite packages on Verdaccio: @suaveplan/cache, @suaveplan/events, @suaveplan/error, @suaveplan/types, @suaveplan/broadcast-channel


0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create directory tree per proposal.md.
  • package.json v0.0.0:
    • "sideEffects": ["./dist/register.js"] — only the register entry has side effects
    • Subpath exports: ".", "./localstorage", "./sessionstorage", "./indexeddb", "./register", "./types"
    • dependencies: @suaveplan/cache workspace:^, @suaveplan/events workspace:^, @suaveplan/error workspace:^, @suaveplan/types workspace:^, @suaveplan/broadcast-channel workspace:^, zod catalog:forms, @opentelemetry/api catalog:observability, tslib catalog:build
    • devDependencies: vitest catalog:testing, @vitest/coverage-istanbul catalog:testing, fake-indexeddb catalog:testing, @playwright/test catalog:testing, @suaveplan/testing workspace:^
  • tsconfig.json, vitest.config.ts (pool: forks, fileParallelism: false for browser tests).

2. Error codes

  • CACHE_QUOTA_EXCEEDED, CACHE_SERIALIZATION_FAILED, INDEXEDDB_NOT_AVAILABLE.
  • registerCacheBrowserErrorCodes() — call eagerly.

3. Serializer + eviction interfaces (src/utils/)

  • serialization/: Serializer<T> interface, defaultSerializer, defaultDeserializer, isSerializable, safeDeserialize. Tests + md.
  • quota/: quota utils. Tests + md.
  • storage-events/: StorageEventHandler. Tests + md.
  • src/eviction/lru-eviction/, lfu-eviction/, ttl-first-eviction/: each implements EvictionStrategy. Tests + md.

4. IndexedDB cache (src/indexeddb/)

Split into four sub-modules ≤300 lines each:

  • store/store.ts: CRUD via IDB transactions, get/set/delete/clear/list.
  • ttl/ttl.ts: expiresAt index, proactive sweep via requestIdleCallback.
  • quota/quota.ts: quota check before write; CACHE_QUOTA_EXCEEDED on fail.
  • events/events.ts: broadcast-channel invalidation hooks.
  • indexeddb/indexeddb.ts: orchestrator composing above.
  • getMetrics(): returns CacheMetrics (size, hitCount, missCount, evictionCount) — no private-property access in tests.
  • Tests: CRUD, TTL expiry, quota guard, cross-tab invalidation (via broadcast-channel), batch ops. All test files ≤500 lines.
  • Write .md per module.

5. LocalStorage cache (src/localstorage/)

Split similarly: store/, ttl/, quota/, events/, localstorage/.

  • Cross-tab invalidation via StorageEventHandler + optional broadcastChannel.
  • getMetrics() introspection.
  • Tests ≤500 lines. Write .md per module.

6. SessionStorage cache (src/sessionstorage/)

Split: store/, ttl/, sessionstorage/.

  • getMetrics() introspection.
  • Tests ≤500 lines. Write .md per module.

7. Register entry (src/register.ts)

  • Call CacheFactory.register('localStorage', () => new LocalStorageCache(...)) etc.
  • This file is the only side-effect entry; matches sideEffects array.

8. OTel metrics

  • Wire counters + histograms in each cache implementation's CRUD methods.

9. Playwright E2E (e2e/cache-browser.spec.ts)

  • Three browser contexts (Chromium, WebKit, Firefox via Playwright).
  • Assert: IndexedDB CRUD, LocalStorage TTL, cross-tab invalidation (two tabs, one writes, other reads updated value), quota-exceeded eviction.

10. Integration test (tests/integration.test.ts)

  • All three caches via the same Cache interface.
  • Eviction strategies (LRU, LFU, TTL-first) under simulated quota pressure.
  • Serializer swap: replace JSON with a custom Serializer<User>.

11. Docs + verify

  • Write .md per module (≥200 words, API reference, examples).
  • Write README.md with subpath table, serializer guide, eviction strategy table, cross-tab section.
  • bunx turbo lint typecheck test --filter=@suaveplan/cache-browser — green.
  • bunx turbo test:coverage — 100%.
  • No @ts-expect-error in src/ or tests.
  • sideEffects declaration correctly reflects only register.ts.
  • Playwright E2E green on Chromium, WebKit, Firefox.
  • bun scripts/publish.ts --package @suaveplan/cache-browser.
  • Archive to openspec/archive/2026-04-24-enterprise-browser-cache-browser/.