# 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` 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`. --- ## 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/`.