8.1 KiB
8.1 KiB
Tasks — enterprise-browser-storage-browser
Every checkbox MUST reflect work actually done in this change. Do not retroactively tick boxes for work that was already in main when this change opened. Do not tick a box for a test that doesn't exist or doesn't pin the requirement it claims to verify. Retroactive ticking is the failure mode this template guards against.
1. Spec authoring
- 1.1 Read
../suaveplan/enterprise/storage-browser.mdend-to-end - 1.2 Read
openspec/specs/storage/spec.md - 1.3 Read
openspec/AGENTS.mdSections 13 and 14 - 1.4 Draft
proposal.mdfromopenspec/templates/proposal.md - 1.5 Fill in
## Source mappingtable — every requirement cites a line range OR appears in the "no source line" table with justification - 1.6 Draft
specs/storage/spec.mdfromopenspec/templates/spec-delta.md - 1.7 Every requirement in the spec delta carries a
**Verified by:**line naming concreteit(...)titles
2. Implementation
- 2.1 Scaffold
packages/browser/storage/storage-browser/with directory tree perproposal.md - 2.2 Write
package.jsonv0.0.0,"sideEffects": false- Dependencies:
@suaveplan/storage workspace:^,@suaveplan/crypto workspace:^,@suaveplan/events workspace:^,@suaveplan/error workspace:^,@suaveplan/types workspace:^,@suaveplan/logger workspace:^,@suaveplan/broadcast-channel workspace:^,@suaveplan/schema-registry workspace:^,zod catalog:forms,@opentelemetry/api catalog:observability,tslib catalog:build - DevDependencies:
vitest catalog:testing,@vitest/coverage-istanbul catalog:testing,fake-indexeddb (^6.0.0) — must be added to catalog:testing before implementation,@playwright/test catalog:testing,@suaveplan/testing workspace:^ - Subpath exports:
".","./indexeddb","./localstorage","./register","./types"
- Dependencies:
- 2.3 Write
tsconfig.json,vitest.config.ts(pool: forks,fileParallelism: false) - 2.4 Implement
src/error-codes.ts:STORAGE_QUOTA_EXCEEDED,STORAGE_KEY_NOT_FOUND,STORAGE_ENCRYPTION_FAILED,STORAGE_COMPRESSION_FAILED,STORAGE_CONCURRENCY_CONFLICT;registerStorageBrowserErrorCodes()called eagerly - 2.5 Implement
src/types/types.ts:StorageEntry,StorageMetadata,BatchOperation,StorageEvent,ListOptions,IndexedDBStorageConfig,LocalStorageStorageConfig; writetypes.md - 2.6 Implement
src/indexeddb/store/store.ts: IDBopenDB, upgrade handler, CRUD transactions (get/set/delete/clear/list) - 2.7 Implement
src/indexeddb/ttl/ttl.ts: proactive sweep viarequestIdleCallback+expiresAtcursor; batch-delete expired rows - 2.8 Implement
src/indexeddb/migrations/migrations.ts:MigrationRunneraccepting step-wise callbacks by schema version - 2.9 Implement
src/indexeddb/adapter/indexeddb.ts:IndexedDBStoragecomposing store + TTL + migrations;batch(ops)in single IDB transaction; optimistic concurrency viaupdatedAtcompare-and-set; OTel metrics + BroadcastChannel invalidation - 2.10 Implement
src/localstorage/store/store.ts: Base64+JSON envelope, namespace prefixing, CRUD - 2.11 Implement
src/localstorage/ttl/ttl.ts: TTL expiry on read + periodic sweep - 2.12 Implement
src/localstorage/adapter/localstorage.ts:LocalStorageStoragecomposing store + TTL; OTel metrics + BroadcastChannel invalidation - 2.13 Implement
src/wrappers/encrypted/encrypted.ts:EncryptedStoragewrapping anyAbstractStorage; AES-GCM via@suaveplan/crypto; throwSTORAGE_ENCRYPTION_FAILEDon key error - 2.14 Implement
src/wrappers/compressed/compressed.ts:CompressedStoragewithCompressionStreamgzip above configurable threshold; throwSTORAGE_COMPRESSION_FAILEDon stream error - 2.15 Implement
src/sync/broadcast/broadcast-sync.ts:BroadcastStorageSyncemittingset/delete/clearon a typed channel - 2.16 Implement
src/observable/observe-storage/observe-storage.ts:observeStorage(storage, key): AsyncIterable<StorageEvent>backed by BroadcastChannel - 2.17 Implement
src/register.ts:registerIndexedDBStorage()andregisterLocalStorageStorage()— explicit factory registration, intentionally not a side-effect - 2.18 Wire OTel metrics: counter
storage.<operation>_total{backend}, histogramstorage.op_ms{backend,operation}, counterstorage.ttl_evictions_total
3. Tests
- 3.1 Unit tests at
src/indexeddb/store/store.test.ts: CRUD, concurrent transactions (fake-indexeddb) - 3.2 Unit tests at
src/indexeddb/ttl/ttl.test.ts: sweep deletes expired, leaves fresh - 3.3 Unit tests at
src/indexeddb/migrations/migrations.test.ts: versioned upgrade callbacks - 3.4 Unit tests at
src/indexeddb/adapter/indexeddb.test.ts: full CRUD, TTL, batch, concurrency conflict, cross-tab invalidation event, quota exceeded - 3.5 Spec-conformance tests at
src/indexeddb/adapter/indexeddb.spec-conformance.test.ts: type-level conformance, OTel metric assertions with real MeterProvider, strict-mode behaviours - 3.6 Unit tests at
src/localstorage/store/store.test.ts: Base64 round-trip, namespace isolation - 3.7 Unit tests at
src/localstorage/ttl/ttl.test.ts: expiry on read, sweep - 3.8 Unit tests at
src/localstorage/adapter/localstorage.test.ts: full CRUD, TTL, namespace, broadcast events - 3.9 Unit tests at
src/wrappers/encrypted/encrypted.test.ts: encrypted round-trip, raw storage sees ciphertext - 3.10 Unit tests at
src/wrappers/compressed/compressed.test.ts: large payload compressed, small payload passes through - 3.11 Unit tests at
src/sync/broadcast/broadcast-sync.test.ts: cross-tab invalidation event, clear event propagation - 3.12 Unit tests at
src/observable/observe-storage/observe-storage.test.ts: iterator yields on remote mutation, iterator completes on abort - 3.13 Unit tests at
src/register.test.ts: import does not register, explicit registration works - 3.14 Unit tests at
src/error-codes.test.ts: all codes registered - 3.15 Integration test at
tests/integration.test.ts: both adapters via sameAbstractStorageinterface; encrypted + compressed wrappers stacked over IndexedDB; batch operations atomicity. ≤500 lines. - 3.16 Playwright E2E at
e2e/storage-browser.spec.ts: Chromium, WebKit, Firefox; cross-tab invalidation; quota-exceeded guard surfacesSTORAGE_QUOTA_EXCEEDED; encrypted payload not readable in raw IDB - 3.17 Every
it(...)carries{ timeout: 5000 }(or 30000 for genuinely async)
4. Documentation
- 4.1 Sibling
.mdfor every implementation.ts(≥200 words, basic + advanced examples, full API reference) - 4.2 Root
README.mdwith subpath table, cross-tab guide, wrapper composition, links to every co-located.md - 4.3 Update
CLAUDE.mdpackage listing if this is a new package
5. Pre-archive verification (the 5-gate triple)
- 5.1
bun run check— Biome 0 errors / 0 warnings / 0 info across the whole monorepo - 5.2
bunx turbo lint typecheck test --filter=@suaveplan/storage-browser— green - 5.3
bunx turbo test:coverage --filter=@suaveplan/storage-browser— 100/100/100/100 - 5.4
bun scripts/openspec-conformance.ts @suaveplan/storage-browser— exit 0, noerrorfindings - 5.5
bunx turbo build --filter=@suaveplan/storage-browser— green
6. Pre-archive 7-row checklist (AGENTS.md Section 13)
- 6.1 Generics threaded;
expectTypeOfassertions on every literal-type claim - 6.2 Zod schemas wired at every declared boundary
- 6.3 Every error code in
error-codes.tsthrown by at least one production path - 6.4 Strict-mode behaviors tested both on and off
- 6.5 OTel instruments emitted from production paths and asserted with a real in-memory
MeterProvider - 6.6 Lifecycle dedup tested where claimed (in-flight Promise, idempotent set/load)
- 6.7 No retroactive tick — every box above reflects work done in this change
7. Archive
- 7.1 Fold spec delta into
openspec/specs/storage/spec.md - 7.2 Move
openspec/changes/enterprise-browser-storage-browser/→openspec/archive/<yyyy-mm-dd>-enterprise-browser-storage-browser/ - 7.3 Refresh
MANIFEST.mdif package set or deps changed