# OpenSpec Change: enterprise-browser-cache-browser - **Change ID**: enterprise-browser-cache-browser - **Package**: `@suaveplan/cache-browser` - **Category**: browser - **Target path**: `browser/storage/cache-browser` - **Status**: IN PROGRESS - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/cache-browser.md` --- ## Summary Deliver `@suaveplan/cache-browser` on the genesis branch at enterprise quality. The package provides browser-side cache implementations (`LocalStorageCache`, `SessionStorageCache`, `IndexedDBCache`) plugging into `@suaveplan/cache`, plus quota utilities, pluggable serializers, cross-tab invalidation via `@suaveplan/broadcast-channel`, pluggable eviction strategies, and OTel metrics. Auto-registration contract and `sideEffects` declaration are aligned. --- ## Current-state audit (genesis) Fresh build — does not exist on genesis yet. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/cache` (`workspace:^`) | `Cache` interface, `CacheFactory` | | `@suaveplan/events` (`workspace:^`) | Storage-event multiplexer | | `@suaveplan/error` (`workspace:^`) | Typed cache errors | | `@suaveplan/types` (`workspace:^`) | `LoggerLike` | | `@suaveplan/broadcast-channel` (`workspace:^`) | Cross-tab invalidation | | `@suaveplan/crypto` (`workspace:^`) | Optional AES-GCM encryption transform | | `@suaveplan/schema-registry` (`workspace:^`) | Register cache config schemas | | `zod` (`catalog:forms`) | Config schemas | | `@opentelemetry/api` (`catalog:observability`) | Cache hit/miss/eviction metrics | | `tslib` (`catalog:build`) | Runtime helpers | Dev: `vitest`, `@vitest/coverage-istanbul`, `fake-indexeddb` (`catalog:testing`), `@playwright/test`, `@suaveplan/testing`. --- ## Preserved public API surface ```ts // Three cache implementations class LocalStorageCache implements Cache { constructor(config: LocalStorageCacheConfig) } class SessionStorageCache implements Cache { constructor(config: SessionStorageCacheConfig) } class IndexedDBCache implements Cache { constructor(config: IndexedDBCacheConfig) } // Subpath exports // @suaveplan/cache-browser/localstorage // @suaveplan/cache-browser/sessionstorage // @suaveplan/cache-browser/indexeddb // @suaveplan/cache-browser/register (explicit auto-registration) // Quota utilities function getStorageQuota(): Promise function isStorageNearQuota(threshold?: number): Promise function estimateStorageSize(): Promise function handleQuotaExceeded(cache: Cache, strategy: EvictionStrategy): Promise function isStorageAvailable(type: 'localStorage' | 'sessionStorage'): boolean // Serialization function defaultSerializer(value: T): string function defaultDeserializer(raw: string): T function isSerializable(value: unknown): boolean function safeDeserialize(raw: string): T | undefined // Storage events class StorageEventHandler { ... } const globalStorageEventHandler: StorageEventHandler // Config types interface LocalStorageCacheConfig { namespace: string; ttl?: number; serializer?: Serializer } interface SessionStorageCacheConfig { namespace: string; ttl?: number; serializer?: Serializer } interface IndexedDBCacheConfig { dbName: string; storeName: string; ttl?: number; schemaVersion?: number; serializer?: Serializer } ``` --- ## New additions for genesis ### 1. `sideEffects` contract Auto-registration moves to explicit `@suaveplan/cache-browser/register` subpath; `"sideEffects": false` is then accurate for all other entry points. The `register` subpath is a `sideEffects: ["./dist/register.js"]` entry. ### 2. Pluggable `Serializer` interface ```ts interface Serializer { serialize(value: T): string; deserialize(raw: string): T } ``` Default: JSON. Alternatives: `CborSerializer` (via `@msgpack/msgpack`), `StructuredCloneSerializer`. ### 3. `EvictionStrategy` interface ```ts interface EvictionStrategy { selectForEviction(entries: CacheEntry[]): CacheEntry[] } class LRUEviction implements EvictionStrategy { ... } class LFUEviction implements EvictionStrategy { ... } class TTLFirstEviction implements EvictionStrategy { ... } ``` ### 4. Cross-tab invalidation `LocalStorageCache` and `IndexedDBCache` accept an optional `broadcastChannel?: TypedBroadcastChannel` — on write/delete/clear, publishes invalidation events so other tabs update their in-memory views. ### 5. Split oversized files Each implementation splits into: `store.ts` (core CRUD), `ttl.ts` (expiry logic), `quota.ts` (quota guard), `events.ts` (storage-event wiring). All ≤300 lines. ### 6. Public introspection surface `cache.getMetrics(): CacheMetrics` replaces private-property reach-through in tests. ### 7. Error codes `CACHE_QUOTA_EXCEEDED`, `CACHE_SERIALIZATION_FAILED`, `INDEXEDDB_NOT_AVAILABLE`. ### 8. OTel metrics Counter `cache.hits_total{backend}`, counter `cache.misses_total{backend}`, counter `cache.evictions_total{strategy}`, histograms `cache.read_ms`, `cache.write_ms`. --- ## File layout ```text browser/storage/cache-browser/ package.json tsconfig.json vitest.config.ts src/ index.ts register.ts (explicit CacheFactory.register calls; sideEffects entry) error-codes.ts indexeddb/ store/ (store.ts, store.test.ts, store.md) ttl/ (ttl.ts, ttl.test.ts, ttl.md) quota/ (quota.ts, quota.test.ts, quota.md) events/ (events.ts, events.test.ts, events.md) indexeddb/ (indexeddb.ts — orchestrator, indexeddb.test.ts, indexeddb.md, indexeddb.types.ts) localstorage/ store/ ttl/ quota/ events/ localstorage/ (localstorage.ts, localstorage.test.ts, localstorage.md, localstorage.types.ts) sessionstorage/ store/ ttl/ sessionstorage/ (sessionstorage.ts, sessionstorage.test.ts, sessionstorage.md, sessionstorage.types.ts) utils/ quota/ (getStorageQuota, isStorageNearQuota, estimateStorageSize, handleQuotaExceeded, isStorageAvailable) serialization/ (defaultSerializer/Deserializer, isSerializable, safeDeserialize, Serializer interface) storage-events/(StorageEventHandler, globalStorageEventHandler) eviction/ lru-eviction/ lfu-eviction/ ttl-first-eviction/ types/ types/ (all shared types) tests/ integration.test.ts e2e/ cache-browser.spec.ts (Playwright: Chromium/WebKit/Firefox real storage) ``` --- ## Impact **Downstream**: `@suaveplan/analytics-browser`, `@suaveplan/pwa`, `@suaveplan/network-discovery-*`, any package using browser caching. **Prerequisites**: `@suaveplan/cache`, `@suaveplan/events`, `@suaveplan/error`, `@suaveplan/broadcast-channel` on Verdaccio.