Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
# 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<Uint8Array | undefined>
set(key: string, value: Uint8Array, ttlMs?: number): Promise<void>
delete(key: string): Promise<boolean>
has(key: string): Promise<boolean>
list(prefix?: string): Promise<string[]>
clear(): Promise<void>
ttl(key: string): Promise<number | undefined>
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<MemoryCacheOptions>
```
### 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`.

View File

@@ -0,0 +1,82 @@
# Tasks: enterprise-server-cache-memory
**Change ID**: enterprise-server-cache-memory
**Package**: `@suaveplan/cache-memory`
**Target path**: `server/data/cache-memory`
**Prerequisite packages on Verdaccio**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/logger`
---
## 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` layout.
- [ ] Write `package.json` at `0.1.0`, `"sideEffects": false`, exports map for `"."`, `adapter`, and `lru`.
- [ ] Add dependencies: `@suaveplan/error workspace:^`, `@suaveplan/types workspace:^`, `@suaveplan/logger workspace:^`, `zod catalog:forms`, `@opentelemetry/api catalog:observability`, `tslib catalog:build`.
- [ ] Add devDependencies: `vitest catalog:testing`, `@vitest/coverage-istanbul catalog:testing`, `fast-check catalog:testing`, `@suaveplan/testing workspace:^`.
- [ ] `tsconfig.json` extending `library.json`; `vitest.config.ts` using `createTestConfig()`.
- [ ] Scripts: `lint`, `typecheck`, `test`, `test:coverage`, `build`, `docs:check`.
## 2. Types and errors
- [ ] Define `MemoryCacheOptions`, `CacheStats`, `MemoryCacheOptionsSchema` in `src/types/cache-memory.types.ts`.
- [ ] Write `cache-memory.types.md` (≥200 words, both examples, API reference).
- [ ] `src/error-codes.ts`: `MemoryCacheErrorCode`, metadata, `registerMemoryCacheErrorCodes()`, eager call.
## 3. LRU data structure
- [ ] Implement `src/lru/lru-cache/lru-cache.ts`:
- Doubly-linked list + Map, O(1) get/set/delete.
- `LruCache<V>` with `maxSize`, `get(k)`, `set(k, v)`, `delete(k)`, `has(k)`, `keys()`, `size`.
- On capacity exceeded: evict LRU (tail) entry; increment eviction counter.
- No external deps.
- [ ] Write `lru-cache.test.ts`: LRU ordering, capacity eviction, re-access promotes entry, delete middle node, size tracking.
- [ ] Write `lru-cache.md` (≥200 words).
## 4. Memory cache adapter
- [ ] Implement `MemoryCacheAdapter` in `src/adapter/memory-cache-adapter/memory-cache-adapter.ts`:
- Owns an `LruCache<{ value: Uint8Array; expiresAt?: number }>`.
- `get(key)`: check expiry using `clock.now()` (or `Date.now()` when no clock); on expiry call `delete(key)` and return `undefined`; increment hit/miss counter.
- `set(key, value, ttlMs?)`: store entry with `expiresAt = clock.now() + ttlMs` when TTL supplied; evict if `maxSize` exceeded (handled by LRU internally).
- `delete(key)`: remove entry; return `true` if existed.
- `has(key)`: get + check expiry; return bool.
- `list(prefix?)`: iterate keys, skip expired, filter by prefix.
- `clear()`: reset LRU; reset stats.
- `ttl(key)`: `expiresAt - clock.now()` or `undefined`.
- `size()`: current entry count.
- `stats()`: return `CacheStats` snapshot.
- OTel: counter `cache_memory.ops_total` (operation, hit); histogram `cache_memory.duration_ms`.
- [ ] Export `createMemoryCacheAdapter(options?)`.
- [ ] Write `memory-cache-adapter.types.ts` with internal types.
- [ ] Write `memory-cache-adapter.test.ts` (≤500 lines): all CRUD, TTL expiry with FakeClock, LRU eviction order, stats accuracy, concurrent access (synchronous — no real concurrency needed), logger invocations.
- [ ] Write `memory-cache-adapter.md` (≥200 words, simple + advanced, full API reference).
## 5. Property-based tests
- [ ] Write `tests/property.test.ts` (≤500 lines, `{ timeout: 30000 }` on each):
- **Get/set round-trip**: for arbitrary keys + values, `set` then `get` returns the same bytes.
- **Delete removes**: after `set` + `delete`, `get` returns `undefined`.
- **TTL expiry consistency**: entries with `ttlMs = 0` never returned on next `get` with advanced clock.
- **LRU ordering**: inserting N+1 entries into a size-N cache results in the oldest-accessed entry being evicted.
- **Stats accuracy**: `hits + misses === total get calls` for arbitrary call sequences.
## 6. OTel + docs
- [ ] Counter `cache_memory.ops_total`; histogram `cache_memory.duration_ms` as specified.
- [ ] All `.md` files per layout; root `README.md` with quick-start, FakeClock testing example, API table, deps table.
## 7. Verify and publish
- [ ] `bunx turbo lint --filter=@suaveplan/cache-memory` — zero errors.
- [ ] `bunx turbo typecheck --filter=@suaveplan/cache-memory` — zero errors.
- [ ] `bunx turbo test --filter=@suaveplan/cache-memory` — all tests pass.
- [ ] `bunx turbo test:coverage --filter=@suaveplan/cache-memory` — 100%.
- [ ] Confirm `"sideEffects": false` set; no `TODO`/`any`/`.skip` in `src/`.
- [ ] `bun scripts/publish.ts --package @suaveplan/cache-memory`.
- [ ] Update `CLAUDE.md`; archive to `openspec/archive/2026-04-24-enterprise-server-cache-memory/`.