Files
2026-05-27 23:29:53 +01:00

5.3 KiB

Tasks — storage-file

Every checkbox MUST reflect work actually done in this change.

1. Spec authoring

  • 1.1 Read ../suaveplan/enterprise/storage-file.md end-to-end
  • 1.2 Read openspec/specs/storage/spec.md and confirm capability boundary
  • 1.3 Read openspec/AGENTS.md Sections 13 and 14
  • 1.4 Draft proposal.md from openspec/templates/proposal.md
  • 1.5 Fill in ## Source mapping table — every requirement cites a line range OR appears in the "no source line" table with justification
  • 1.6 Draft specs/storage-file/spec.md from openspec/templates/spec-delta.md
  • 1.7 Every requirement in the spec delta carries a **Verified by:** line naming concrete it(...) titles

2. Scaffolding

  • 2.1 Create packages/storage/storage-file/ mirroring packages/storage/storage-s3/ conventions
  • 2.2 Write package.json v0.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 (all workspace:^ / catalog:)
  • 2.4 Wire devDeps: @suaveplan/testing, @types/node, @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
  • 2.6 Write tests/setup/polyfills.ts and README.md skeleton

3. Implementation

  • 3.1 src/error-codes.ts — defineCodes("STORAGE_FILE", [...]) with 8 codes, StorageFileError class, key discriminant
  • 3.2 src/types/node-fs-storage.types.ts + .schemas — NodeFsStorageOptions interface + Zod schema
  • 3.3 src/types/fs-adapter.types.ts — NodeFsLike structural interface (mkdir, readFile, writeFile, rename, unlink, readdir, stat, access, open, createReadStream, createWriteStream)
  • 3.4 src/node-fs/node-fs.ts — defaultNodeFs() factory wrapping node:fs/promises + node:fs streams
  • 3.5 src/key-sanitizer/key-sanitizer.ts — sanitizeKey(key) strict boundary
  • 3.6 src/retry-helper/retry-helper.ts — withFsRetry(fn, options) consuming @suaveplan/retry.retry with transient classifier
  • 3.7 src/otel/otel.ts — meters/histograms/counters/tracer, recordOp(op, outcome, durationMs, bytes?)
  • 3.8 src/streams/streams.ts — createNodeReadStream and createNodeWriteStream mapping node:fs streams to Web Streams with AbortSignal
  • 3.9 src/node-fs-storage/node-fs-storage.ts — NodeFsStorage extends AbstractStorage with all abstract methods, atomic writes, AbortSignal, capabilities matrix
  • 3.10 src/registry/registry.ts — declare module "@suaveplan/storage" + registerNodeFsProvider()
  • 3.11 src/index.ts — explicit named re-exports per §6a

4. Tests

  • 4.1 src/key-sanitizer/key-sanitizer.test.ts — valid, traversal, absolute, null bytes, control chars, overlong, separator normalisation
  • 4.2 src/node-fs/node-fs.test.ts — adapter forwards to real fs.mkdtemp-rooted directory
  • 4.3 src/retry-helper/retry-helper.test.ts — classifier, backoff timing, exhaustion
  • 4.4 src/otel/otel.test.ts — metrics observed via real in-memory MeterProvider
  • 4.5 src/streams/streams.test.ts — round-trip, large payload, AbortSignal mid-stream
  • 4.6 src/node-fs-storage/node-fs-storage.test.ts — full CRUD + metadata + list + clear + getSize + getPartial + atomic write rollback + retry path
  • 4.7 src/node-fs-storage/node-fs-storage.spec-conformance.test.ts — type conformance, capabilities, OTel instruments emitted, registry idempotency
  • 4.8 src/registry/registry.test.ts — registers file slot, factory dispatch
  • 4.9 Every it(...) carries { timeout: 5000 } (or 30000 for genuinely async)

5. Documentation

  • 5.1 Sibling .md for every implementation .ts (≥200 words, basic + advanced examples, full API reference)
  • 5.2 README.md links every module under ## Modules

6. Gates

  • 6.1 bun run check
  • 6.2 bunx turbo lint typecheck test --filter=@suaveplan/storage-file
  • 6.3 bunx turbo test:coverage --filter=@suaveplan/storage-file (100/100/100/100)
  • 6.4 bun scripts/openspec-conformance.ts @suaveplan/storage-file
  • 6.5 bunx turbo build --filter=@suaveplan/storage-file

7. Pre-archive 9-row checklist

  • 7.1 Generics threaded; structural injectable seams (NodeFsLike, TimersLike)
  • 7.2 Zod schemas wired at every declared boundary
  • 7.3 Every error code thrown by at least one production path
  • 7.4 OTel instruments emitted from production paths; asserted via real in-memory MeterProvider
  • 7.5 Atomic writes verified (temp-file removed on success, removed on failure)
  • 7.6 No export * in feature-module barrels (§6a)
  • 7.7 No direct vitest / bun:test imports in tests (§7)
  • 7.8 No banned patterns in src/ (TODO/FIXME/ts-ignore/.skip/.only)
  • 7.9 README + sibling .md files complete

8. Archive

  • 8.1 Fold spec delta into openspec/specs/storage-file/spec.md
  • 8.2 Move openspec/changes/storage-file/ → openspec/archive/<yyyy-mm-dd>-storage-file/
  • 8.3 Refresh MANIFEST.md via bun scripts/folder-reorg/generate-manifest.ts
  • 8.4 Update CLAUDE.md package listing under storage family