8.8 KiB
Capability Spec Delta: drive (drive)
Package: @suaveplan/drive
Status: PROPOSED
Every requirement below carries a
**Verified by:**line at authoring time. The named tests are planned; they MUST exist and pass verbatim before this delta is folded intoopenspec/specs/drive/spec.md.
ADDED Requirements
Requirement: Drive.createReadStream accepts a range-options bag
Drive.createReadStream SHALL be overloaded to accept either a bare AbortSignal (existing form) or a RangeReadOptions bag with optional offset, length, and signal. The bare-signal form MUST continue to return a whole-file stream. When the options form is passed, the drive MUST forward { offset, length, signal } through the plugin middleware chain via the middleware context's range field. The implementation MUST runtime-discriminate via instanceof AbortSignal.
Scenario: bare signal still returns whole-file stream
- WHEN
drive.createReadStream("file.bin", abortSignal)is called on a 200 KiB file - THEN the returned stream emits the entire 200 KiB payload and respects
abortSignalfor cancellation
Scenario: options form forwards offset and length
- WHEN
drive.createReadStream("file.bin", { offset: 1024, length: 4096 })is called - THEN the middleware context carries
range = { offset: 1024, length: 4096 }and the returned stream emits exactly bytes[1024, 5120)of the source
Scenario: zero-length range yields an empty stream
- WHEN
drive.createReadStream("file.bin", { offset: 12345, length: 0 })is called - THEN the returned stream closes immediately with zero enqueued bytes
Verified by: src/drive/drive.test.ts::"createReadStream(path, signal) preserves whole-file behaviour" AND src/drive/drive.test.ts::"createReadStream(path, { offset, length }) emits exactly the requested slice" AND src/drive/drive.test.ts::"createReadStream(path, { length: 0 }) returns an immediately closed stream"
Requirement: Invalid range options throw DRIVE.RANGE_INVALID synchronously
Drive.createReadStream(path, options) SHALL validate options.offset and options.length synchronously before constructing the ReadableStream. Either field, when present, MUST be a finite non-negative integer (Number.isInteger(x) && x >= 0 && Number.isFinite(x)). On violation, the method MUST throw DriveError(DRIVE.RANGE_INVALID, ...) BEFORE returning. The error's context SHALL include the offending field name and value.
Scenario: negative offset throws synchronously
- WHEN
drive.createReadStream("file.bin", { offset: -1 })is called - THEN the call throws
DriveErrorwithcode === "DRIVE.RANGE_INVALID"andcontext.field === "offset", and noReadableStreamis created
Scenario: non-integer length throws synchronously
- WHEN
drive.createReadStream("file.bin", { length: 1.5 })is called - THEN the call throws
DriveErrorwithcode === "DRIVE.RANGE_INVALID"andcontext.field === "length"
Scenario: NaN / Infinity rejected
- WHEN
drive.createReadStream("file.bin", { offset: Number.NaN })is called ORdrive.createReadStream("file.bin", { length: Number.POSITIVE_INFINITY })is called - THEN each call throws
DriveError(DRIVE.RANGE_INVALID, ...)synchronously
Verified by: src/drive/drive.test.ts::"createReadStream throws RANGE_INVALID for negative offset" AND src/drive/drive.test.ts::"createReadStream throws RANGE_INVALID for non-integer length" AND src/drive/drive.test.ts::"createReadStream throws RANGE_INVALID for NaN or Infinity"
Requirement: Out-of-bounds range surfaces DRIVE.RANGE_OUT_OF_BOUNDS
When the underlying source exposes a known size at stream-start (via the chunks-plugin manifest, a storage stat, or a nativeRange-capable storage that reports size), Drive.createReadStream MUST raise DriveError(DRIVE.RANGE_OUT_OF_BOUNDS, ...) synchronously for offset > size or offset + length > size. When size is unknown at start-time, the stream MUST accept the request, emit available bytes, and on close MUST surface DRIVE.RANGE_OUT_OF_BOUNDS via controller.error if the byte count emitted is less than the requested length. The error MUST carry the originating CHUNKS.RANGE_OUT_OF_BOUNDS (when applicable) as cause.
Scenario: offset past EOF rejected synchronously when size is known
- WHEN the underlying file is 1024 bytes and
drive.createReadStream("file.bin", { offset: 2048 })is called via a chunks-plugin-mediated path - THEN the call throws
DriveError(DRIVE.RANGE_OUT_OF_BOUNDS, ...)synchronously withcausecarryingCHUNKS.RANGE_OUT_OF_BOUNDS
Scenario: offset+length past EOF rejected synchronously when size is known
- WHEN the file is 1024 bytes and
drive.createReadStream("file.bin", { offset: 900, length: 500 })is called via the chunks plugin - THEN the call throws
DriveError(DRIVE.RANGE_OUT_OF_BOUNDS, ...)synchronously
Scenario: short-fall on stream end when size was unknown at start
- WHEN the storage cannot report size,
drive.createReadStream("file.bin", { offset: 0, length: 10_000 })is called, and the source closes after 4000 bytes - THEN the stream errors with
DriveError(DRIVE.RANGE_OUT_OF_BOUNDS, ...)andcontext.emittedBytes === 4000
Verified by: src/drive/drive.test.ts::"createReadStream throws RANGE_OUT_OF_BOUNDS when offset exceeds known size" AND src/drive/drive.test.ts::"createReadStream throws RANGE_OUT_OF_BOUNDS when offset+length exceeds known size" AND src/file-operations/streams.range.test.ts::"stream errors with RANGE_OUT_OF_BOUNDS on short-fall when size is unknown"
Requirement: nativeRange storage capability is honoured
DriveStorage SHALL accept an optional capabilities.nativeRange?: boolean flag. When true, Drive.createReadStream(path, { offset, length, signal }) MUST forward { offset, length } to storage.createReadStream directly. When false (or absent), the drive MUST wrap the storage stream in a slicing transform that drops bytes before offset and stops emitting after length bytes. Both paths MUST produce identical observable output.
Scenario: storage with nativeRange receives offset/length
- WHEN
storage.capabilities.nativeRange === trueanddrive.createReadStream("file.bin", { offset: 1024, length: 4096 })is invoked - THEN
storage.createReadStreamis called exactly once with{ offset: 1024, length: 4096, signal }and no slicing transform is interposed
Scenario: storage without nativeRange is wrapped in slicing transform
- WHEN
storage.capabilities?.nativeRangeisundefinedorfalseand the same call is made - THEN
storage.createReadStreamis called with{ signal }only, and the returned stream is wrapped so the consumer observes exactly bytes[1024, 5120)
Verified by: src/file-operations/streams.range.test.ts::"nativeRange storage receives offset and length directly" AND src/file-operations/streams.range.test.ts::"non-nativeRange storage is wrapped in a slicing transform"
Requirement: Range cancellation propagates via AbortSignal
Drive.createReadStream(path, options) MUST propagate options.signal (or the bare signal in the back-compat form) through the chunks-plugin / mesh / storage pull chain. On abort, in-flight chunk fetches MUST be cancelled, the stream MUST close with controller.error(AbortError), and (over drive+mesh://) the mesh transport MUST emit a cd:error envelope with code: "ABORTED".
Scenario: mid-stream abort cancels chunk fetches
- WHEN
drive.createReadStream("file.bin", { offset: 0, length: 1_048_576, signal })is called andsignal.abort()is invoked after the first chunk emits - THEN the stream closes with an
AbortError, no further chunks are fetched, and the chunks-plugin loop exits at the nextthrowIfAbortedcheckpoint
Verified by: src/file-operations/streams.range.test.ts::"abort mid-range stream cancels in-flight chunk fetches"
Requirement: DRIVE_CODES registry adds RANGE_INVALID and RANGE_OUT_OF_BOUNDS
DRIVE_CODES SHALL include "RANGE_INVALID" and "RANGE_OUT_OF_BOUNDS" declared via the existing defineCodes("DRIVE", [...] as const) call. Object.isFrozen(DRIVE_CODES) MUST remain true. Every code value MUST start with DRIVE..
Scenario: registry exposes the new codes
- WHEN the test imports
DRIVE_CODESfrom@suaveplan/drive - THEN
DRIVE_CODES.RANGE_INVALID === "DRIVE.RANGE_INVALID"ANDDRIVE_CODES.RANGE_OUT_OF_BOUNDS === "DRIVE.RANGE_OUT_OF_BOUNDS"ANDObject.isFrozen(DRIVE_CODES) === true
Verified by: src/error-codes.spec-conformance.test.ts::"DRIVE_CODES exposes RANGE_INVALID and RANGE_OUT_OF_BOUNDS" AND src/error-codes.spec-conformance.test.ts::"Object.isFrozen(DRIVE_CODES) is true"