6.0 KiB
6.0 KiB
Tasks — storage-http
Every checkbox MUST reflect work actually done in this change.
1. Spec authoring
- 1.1 Read
openspec/specs/storage/spec.mdand confirm capability boundary - 1.2 Read
openspec/AGENTS.md§0c, §13, §14 - 1.3 Read
openspec/archive/2026-05-12-storage-file/end-to-end as the closest precedent - 1.4 Read
openspec/archive/2026-04-24-enterprise-storage-s3/for network-backed adapter precedent (OTel + retry classification) - 1.5 Draft
proposal.mdfromopenspec/templates/proposal.md - 1.6 Draft
design.mdcovering file layout, status→code map, range fallback, ETag cache, uploader contract, tier purity - 1.7 Draft
specs/storage-http/spec.mdfromopenspec/templates/spec-delta.md - 1.8 Every requirement in the spec delta carries a
**Verified by:**line naming concrete plannedit(...)titles - 1.9 Build the numbered Requirement/Scenario implementation checklist (per §0c step 6)
2. Scaffolding
- 2.1 Create
packages/storage/storage-http/mirroringpackages/storage/storage-file/conventions - 2.2 Write
package.jsonv0.0.0,"sideEffects": false, subpath exports for every feature module - 2.3 Wire deps:
@suaveplan/error,@suaveplan/storage,@suaveplan/retry,@suaveplan/types,@opentelemetry/api,zod,tslib(allworkspace:^/catalog:) - 2.4 Wire devDeps:
@suaveplan/testing,@vitest/coverage-istanbul,fast-check,mitata,typescript,vite,vite-plugin-dts,vitest - 2.5 Write
tsconfig.json,tsconfig.lib.json,vite.config.ts,vitest.config.ts(viacreateTestConfig) - 2.6 Write
tests/setup/polyfills.tsandREADME.mdskeleton
3. Implementation
- 3.1
src/error-codes.ts—defineCodes("STORAGE_HTTP", [...])with 10 codes,StorageHttpErrorclass,key/httpStatus/urldiscriminants - 3.2
src/types/http-storage.types.ts—HttpStorageOptions,FetchLike,HttpUploader,EtagCacheOptionsinterfaces - 3.3
src/types/http-storage.schemas.ts—HttpStorageOptionsSchema(Zod) withbaseUrlhttp(s) + trailing-slash validation - 3.4
src/fetch-adapter/fetch-adapter.ts—defaultFetch()wrappingglobalThis.fetch,AbortSignalpropagation, network-reject →NETWORK_ERROR - 3.5
src/key-sanitizer/key-sanitizer.ts—sanitizeKeystrict boundary + default per-segmentencodeURIComponent - 3.6
src/range/range.ts—Rangeheader builder + 206/200/416 disambiguation - 3.7
src/etag-cache/etag-cache.ts— in-memory LRU keyed by sanitised key - 3.8
src/uploader/uploader.ts—HttpUploadercontract +presignedPutUploader(presigner)helper - 3.9
src/retry-helper/retry-helper.ts— transient status classifier +Retry-Afterhonour via@suaveplan/retry - 3.10
src/otel/otel.ts— meter/tracer wiring,recordOp(op, outcome, statusClass, ms, bytes?) - 3.11
src/http-storage/http-storage.ts—HttpStorage extends AbstractStoragewith all abstract methods, capabilities matrix,READ_ONLYenforcement, AbortSignal - 3.12
src/registry/registry.ts—declare module "@suaveplan/storage"+registerHttpProvider()(idempotent) - 3.13
src/index.ts— explicit named re-exports per §6a (noexport *in any non-root barrel)
4. Tests
- 4.1
src/key-sanitizer/key-sanitizer.test.ts— valid, traversal, absolute, null bytes, control chars, overlong (>2048), separator normalisation, per-segment encoding - 4.2
src/fetch-adapter/fetch-adapter.test.ts— forwards toglobalThis.fetch,AbortSignalpropagation, network-reject →NETWORK_ERROR - 4.3
src/range/range.test.ts— 206 verbatim, 200 fallback + counter increment, 416 →NOT_FOUND - 4.4
src/etag-cache/etag-cache.test.ts— LRU eviction, 304 returns cached body, 200 replaces entry - 4.5
src/uploader/uploader.test.ts—presignedPutUploaderround-trip; injected uploader invoked exactly once onset - 4.6
src/retry-helper/retry-helper.test.ts— transient classifier,Retry-Afterhonour underFakeClock, non-retry on 401 - 4.7
src/otel/otel.test.ts— metrics via real in-memoryMeterProvider; error span via in-memorySpanExporter - 4.8
src/http-storage/http-storage.test.ts— GET round-trip, 404 → undefined, HEAD exists/metadata, AbortSignal pre/mid, READ_ONLY onset/list/clear,setwith uploader invokesputonce - 4.9
src/http-storage/http-storage.spec-conformance.test.ts— type conformance, capabilities matrix, everySTORAGE_HTTPcode reachable, tier-purity grep - 4.10
src/registry/registry.test.ts—createStorage({ type: "http", … })returnsHttpStorage; idempotent re-registration - 4.11 Every
it(...)carries{ timeout: 5000 }(or 30000 for genuinely async) - 4.12 No imports from
vitestorbun:testin test files — all via@suaveplan/testing/runner(§7)
5. Documentation
- 5.1 Sibling
.mdfor every implementation.ts(≥200 words, basic + advanced examples, full API reference) - 5.2
README.mdlinks every module under## Modules - 5.3 README documents composition recipe:
storage-httpbehindstorage-fileNamespacedStoragefor cross-process disk cache
6. Gates
- 6.1
bun run check - 6.2
bunx turbo lint typecheck test --filter=@suaveplan/storage-http - 6.3
bunx turbo test:coverage --filter=@suaveplan/storage-http(100/100/100/100 Istanbul) - 6.4
bun scripts/lint/check-test-runner-imports.ts(rule 11) - 6.5 Tier-purity grep —
grep -rnE "from ['\"](node:|bun:)" packages/storage/storage-http/src/returns empty - 6.6
bun scripts/openspec-conformance.ts @suaveplan/storage-http
7. Manifest & archival
- 7.1 Add package to
MANIFEST.mdviabun scripts/folder-reorg/generate-manifest.ts - 7.2 Update
STATUS.md(genesis-original — add to "Completed" once shipped) - 7.3 Fold
specs/storage-http/spec.mdintoopenspec/specs/storage-http/spec.md - 7.4 Move
openspec/changes/add-storage-http/→openspec/archive/<yyyy-mm-dd>-add-storage-http/