- KVStorageEncrypted: AES-GCM per value (fresh IV, storage key as AAD), keys stay
readable; decrypts and re-emits pushed changes and passes subscriptions through, so it
can be a composite source. generateKey / exportKey / importKey / deriveKey (PBKDF2).
- KVStorageHttpServer: allowOrigins (CORS), including cache-control for SSE preflights.
- Chromium tests (Vitest browser mode + Playwright) against a real cross-origin server:
conformance for IndexedDB, encrypted, HTTP and composite stores; signed requests and
SSE; two devices syncing, offline writes surviving a reload. New CI job.
- Composite fixes found by those tests: sync() during a running sync schedules one more
(changes between the first scan and the stream connecting were missed); a queued write
the source refuses is dropped, restored and reported (onError) instead of blocking the
queue forever.
- README with examples, mirrored in test/readme.test.ts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qxbkp4tA7G5SCWjzWuxmE
- Every KV storage emits change events (base class owns writeMany/removeMany/
writeIfAbsent; implementations provide protected apply* methods)
- KVStorageHttpServer streams changes over SSE (GET /events) with a resumable
history; KVStorageHttp.watch() subscribes and resumes via Last-Event-ID
- KVStorageIndexedDB for local persistence
- KVStorageComposite keeps replicas of a source in sync: local reads, resume
instead of full sync, offline outbox replayed in order, echo tracking
- Values may contain bigint/Uint8Array (Extended JSON over the network)
- Vendor sse-session, event-emitter and extended-json (no runtime deps)
- Freeze child nodes so shadowed state on children fails loudly
- CI on Node 22, 24 and 26
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qxbkp4tA7G5SCWjzWuxmE
- BaseKVStorage / BaseEventStorage / BaseDocumentStorage define the API once;
implementations provide only raw primitives (client and server share an API)
- Drop KV indexes, query planner, unique indexes; document stores take index fields
- Escape every char <= '/' so child keys stay contiguous; skip-scan is now simple
- Event-sourced documents = event storage + any document store for projections
- New folder layout (kv-storage, event-storage, document-storage, utils); tests only in test/
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qxbkp4tA7G5SCWjzWuxmE