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

5.5 KiB

Capability Spec Delta: drive-uri (fix-storage-uri-error-passthrough)

Package: @suaveplan/drive-uri Status: PROPOSED

Every requirement carries a **Verified by:** line at authoring time. This delta MODIFIES five scenarios across three requirements from add-drive-uri (still in openspec/changes/, not yet archived). The **Note —** revisited in fix-storage-uri-error-passthrough... annotation at the top of the drive-uri add-drive-uri delta is also retired by this change. (The companion **Note —** buffered-read signal threading annotation stays, since add-signal-to-storage-like has not landed.)

MODIFIED Requirements

Requirement: drive:// plugin parses authority as driveId and delegates to Drive.read

The driveUriPlugin(options) factory SHALL return a UriPlugin with scheme === "drive". Its parse SHALL extract the URI authority as driveId and the remainder as a slash-prefix-trimmed key. The returned plugin SHALL forward key to the consumer-supplied Drive via Drive.read(key, { signal }) (or Drive.createReadStream on open()). The plugin SHALL throw DRIVE_URI.DRIVE_ID_MISMATCH when the URI's driveId does not equal the driveId declared in options.

The StorageUriResolver SHALL surface this throw directly per the pass-through rule (see fix-storage-uri-error-passthrough spec delta for storage-uri).

Scenario: URI dispatches to Drive.read

  • WHEN resolver.read("drive://primary/folder/file.bin") is called and the resolver holds driveUriPlugin({ drive, driveId: "primary" })
  • THEN drive.read("folder/file.bin", { signal }) is invoked exactly once and its return value is the resolver's result

Scenario: driveId mismatch surfaces DRIVE_URI.DRIVE_ID_MISMATCH directly

  • WHEN resolver.read("drive://other/x") is called and the plugin is configured with driveId: "primary"
  • THEN the call rejects with DriveUriError having code === "DRIVE_URI.DRIVE_ID_MISMATCH", uri === "drive://other/x", expected === "primary", actual === "other" (the resolver passes the DriveUriError through unchanged per the storage-uri pass-through rule; no STORAGE_URI.* envelope is added)

Scenario: build round-trips driveId and key

  • WHEN plugin.build("folder/file.bin", { driveId: "primary" }) is called
  • THEN the returned string equals "drive://primary/folder/file.bin"

Verified by: src/plugins/drive/drive.test.ts::"dispatches a drive:// URI to Drive.read" AND src/plugins/drive/drive.test.ts::"throws DRIVE_ID_MISMATCH when URI driveId differs from configured driveId" AND src/plugins/drive/drive.test.ts::"build round-trips driveId and key into a drive:// URI"


Requirement: Template fetch and hydration failures map to distinct DRIVE_URI codes

When options.templateProvider.fetchTemplate rejects, the plugin SHALL re-wrap the rejection as DRIVE_URI.TEMPLATE_NOT_AVAILABLE with the original error preserved on cause. When Drive.hydrateFrom rejects (any DTP_* code), the plugin SHALL re-wrap the rejection as DRIVE_URI.TEMPLATE_INVALID with the original on cause. The two failures MUST NOT be conflated — operator response differs (network/availability vs. integrity).

The StorageUriResolver SHALL surface both DriveUriErrors directly per the pass-through rule.

Scenario: fetchTemplate rejection becomes TEMPLATE_NOT_AVAILABLE

  • WHEN resolver.read("drive+template://templA/x") is called and templateProvider.fetchTemplate rejects with new Error("404")
  • THEN the call rejects with DriveUriError having code === "DRIVE_URI.TEMPLATE_NOT_AVAILABLE" AND cause.message === "404"

Scenario: hydrateFrom rejection becomes TEMPLATE_INVALID

  • WHEN resolver.read("drive+template://templA/x") is called and drive.hydrateFrom rejects with a SuaveplanError carrying code === "DTP.TEMPLATE_EXPIRED"
  • THEN the call rejects with DriveUriError having code === "DRIVE_URI.TEMPLATE_INVALID" AND cause.code === "DTP.TEMPLATE_EXPIRED"

Verified by: src/plugins/drive-template/drive-template.test.ts::"wraps fetchTemplate rejection as TEMPLATE_NOT_AVAILABLE" AND src/plugins/drive-template/drive-template.test.ts::"wraps hydrateFrom rejection as TEMPLATE_INVALID"


Requirement: Writes via drive:// schemes are rejected

The three plugins SHALL reject set (write) calls with DRIVE_URI.WRITE_UNSUPPORTED. The rejection SHALL carry the original URI and scheme on the error so operators can see misuse rate via drive_uri.writes_total{scheme, outcome: "error"}.

The StorageUriResolver SHALL surface this throw directly per the pass-through rule — err.code === "DRIVE_URI.WRITE_UNSUPPORTED" reaches the caller without a STORAGE_URI.WRITE_UNSUPPORTED envelope.

Scenario: write against drive:// rejects with DRIVE_URI.WRITE_UNSUPPORTED

  • WHEN resolver.write("drive://primary/x", new Uint8Array([1, 2, 3])) is called
  • THEN the call rejects with DriveUriError having code === "DRIVE_URI.WRITE_UNSUPPORTED", uri === "drive://primary/x", scheme === "drive"

Scenario: writes_total counter increments on the rejection

  • WHEN resolver.write("drive+mesh://swarmA/x", bytes) is called
  • THEN drive_uri.writes_total{scheme: "drive+mesh", outcome: "error"} is incremented by 1

Verified by: src/plugins/drive/drive.test.ts::"rejects writes with DRIVE_URI.WRITE_UNSUPPORTED" AND src/otel/otel.test.ts::"increments writes_total on rejected writes"