# OpenSpec Change: enterprise-server-cache-memory - **Change ID**: enterprise-server-cache-memory - **Package**: `@suaveplan/cache-memory` - **Category**: server/data - **Target path**: `server/data/cache-memory` - **Status**: PROPOSED - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/cache-memory.md` --- ## Summary Deliver `@suaveplan/cache-memory` on the genesis branch from scratch at enterprise quality. The package provides a zero-dependency, in-process LRU + TTL cache adapter implementing the same interface contract as `@suaveplan/cache-redis`. It is the primary testing stand-in and the default cache for single-server deployments. Genesis ships with a doubly-linked-list LRU eviction algorithm, injectable `Clock` for deterministic time testing, Zod-validated options, OTel counters/histograms, structured logging, and 100% test coverage via property-based tests. --- ## Current-state audit (genesis) Does not exist on genesis — fresh build. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/error` (`workspace:^`) | Typed error codes for `CACHE_MEMORY.*` | | `@suaveplan/types` (`workspace:^`) | `StorageLike`, `LoggerLike`, `Clock` | | `@suaveplan/logger` (`workspace:^`) | Structured logs | | `zod` (`catalog:forms`) | Options validation | | `@opentelemetry/api` (`catalog:observability`) | Counters + histograms | | `tslib` (`catalog:build`) | Runtime helpers | --- ## Public API surface ### Adapter ```ts class MemoryCacheAdapter { constructor(options?: MemoryCacheOptions) get(key: string): Promise set(key: string, value: Uint8Array, ttlMs?: number): Promise delete(key: string): Promise has(key: string): Promise list(prefix?: string): Promise clear(): Promise ttl(key: string): Promise size(): number stats(): CacheStats } function createMemoryCacheAdapter(options?: MemoryCacheOptions): MemoryCacheAdapter ``` ### Options + types ```ts interface MemoryCacheOptions { maxSize?: number // max number of entries, default: 1000 defaultTtlMs?: number // default TTL when none supplied; undefined = no expiry clock?: Clock // injectable for testing logger?: LoggerLike } interface CacheStats { hits: number misses: number evictions: number size: number hitRate: number } const MemoryCacheOptionsSchema: z.ZodSchema ``` ### Error codes ```ts type MemoryCacheErrorCode = | 'CACHE_MEMORY_INVALID_KEY' | 'CACHE_MEMORY_CAPACITY_EXCEEDED' function registerMemoryCacheErrorCodes(): void ``` --- ## File layout ```text server/data/cache-memory/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts constants/ index.ts types/ cache-memory.types.ts cache-memory.types.md adapter/ memory-cache-adapter/ memory-cache-adapter.ts memory-cache-adapter.md memory-cache-adapter.types.ts memory-cache-adapter.test.ts index.ts lru/ lru-cache/ lru-cache.ts lru-cache.md lru-cache.test.ts index.ts tests/ property.test.ts ``` --- ## Impact Downstream consumers: testing utilities, unit-test doubles for packages that depend on `cache-redis`. Universal helper — no Node.js IO, pure in-process. **Prerequisites on Verdaccio**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/logger`.