import { describe, expect, it, vi } from "vitest"; import { BrowserFilePolicyRegistry, browserFilePolicyReference, } from "../../src/adapters/browser-files/browser-file-policy-registry.ts"; import { createDownloadDeliveryAdapter, type SaveFileHandle, } from "../../src/adapters/browser-files/download-delivery-adapter.ts"; import { CHECKSUM_HEADER, CONTROL_ENDPOINT, DATA_ORIGIN, DIGEST_HEADER, DOWNLOAD_HREF, DOWNLOAD_PATH, NOW, POLICY_HEADER, REQUEST_BINDING_SHA256, UPLOAD_SESSION_ID, collect, createHarness, downloadCapabilityPayload, downloadResponse, jsonResponse, responseWithUrl, uploadCapabilityPayload, } from "./presigned-transfer-fixture.ts"; describe("presigned DownloadDelivery integration", () => { it("connects an issued capability to DownloadDeliveryPort without caller digest input", async () => { const bytes = new TextEncoder().encode("verified"); const payload = downloadCapabilityPayload(bytes); const fetcher = vi.fn(async (input: RequestInfo | URL) => String(input) === CONTROL_ENDPOINT ? jsonResponse(payload) : downloadResponse(bytes.slice().buffer, payload), ) as unknown as typeof fetch; const { provider, executor } = createHarness({ fetcher }); const issued = await provider.issueDownload({ resourceId: "resource-1", signal: new AbortController().signal, }); expect(issued.ok).toBe(true); if (!issued.ok) return; const policy = browserFilePolicyReference( "download", "presigned-stream", ); const policies = new BrowserFilePolicyRegistry({ profiles: [ { reference: policy, download: { strategy: "PROMPT_AND_STREAM", mediaType: "application/octet-stream", safeExtension: ".bin", maxTransferBytes: 64, maxBufferedBytes: 8, integrity: "REQUIRED", }, }, ], hardLimits: { maxInspectionBytes: 64, maxRetainedFileBytes: 64, maxPreviewBytes: 64, maxObjectUrlBytes: 64, maxTransferBytes: 64, }, }); const written: number[] = []; const handle: SaveFileHandle = { async createWritable() { return new WritableStream({ write(chunk) { written.push(...chunk); }, }); }, }; const downloads = createDownloadDeliveryAdapter({ host: { handoff() {} }, policies, hardMaxObjectUrlBytes: 64, hardMaxTransferBytes: 64, browserManagedCapabilities: { resolve() { throw new TypeError("not used"); }, }, openAuthorizedSource: executor.downloadSources.open.bind(executor.downloadSources), showSaveFilePicker: async () => handle, userActivation: { isActive: true }, now: () => NOW, }); const result = await downloads.deliver({ policy, source: { kind: "AUTHORIZED_STREAM_RESOURCE", resourceId: "resource-1", capability: issued.value, }, suggestedFileName: "artifact.bin", signal: new AbortController().signal, onProgress() {}, }); expect(result).toMatchObject({ ok: true, value: { kind: "SAVED", integrity: "VERIFIED", bytesWritten: bytes.byteLength, }, }); expect(written).toEqual([...bytes]); }); /** * TR-RR-04. A presigned byte source owns a fetch reader and a capability * lease, and its port requires `close()`. The delivery consumer never called * it, so every outcome — success, validation failure, writer failure and * abort — leaked both. */ it.each([ { label: "success", mode: "SUCCESS" as const }, { label: "writer failure", mode: "WRITER_FAILURE" as const }, { label: "abort", mode: "ABORT" as const }, ])("closes the presigned source exactly once on $label", async ({ mode }) => { const bytes = new Uint8Array([1, 2, 3]); let closes = 0; const controller = new AbortController(); const source = { byteLength: bytes.byteLength, integrity: "VERIFIED_ON_SUCCESSFUL_EXHAUSTION" as const, capability: undefined as never, close() { closes += 1; }, async *stream() { if (mode === "ABORT") controller.abort(); yield { ok: true as const, value: bytes }; }, }; const capability = Object.freeze({ capabilityReceipt: "capability-close-1", method: "GET" as const, binding: { kind: "DOWNLOAD" as const, resourceId: "resource-1" }, mediaType: "application/octet-stream", byteLength: bytes.byteLength, maxBytes: bytes.byteLength, expectedSha256: "a".repeat(64), expiresAtEpochMs: NOW + 60_000, }); source.capability = capability as never; const closePolicy = browserFilePolicyReference( "download", "presigned-close", ); const policies = new BrowserFilePolicyRegistry({ profiles: [ { reference: closePolicy, download: { strategy: "PROMPT_AND_STREAM", mediaType: "application/octet-stream", safeExtension: ".bin", maxTransferBytes: 64, maxBufferedBytes: 8, integrity: "REQUIRED", }, }, ], hardLimits: { maxInspectionBytes: 64, maxRetainedFileBytes: 64, maxPreviewBytes: 64, maxObjectUrlBytes: 64, maxTransferBytes: 64, }, }); const handle: SaveFileHandle = { async createWritable() { return new WritableStream({ write() { if (mode === "WRITER_FAILURE") { throw new TypeError("writer exploded"); } }, }); }, }; const downloads = createDownloadDeliveryAdapter({ host: { handoff() {} }, policies, hardMaxObjectUrlBytes: 64, hardMaxTransferBytes: 64, browserManagedCapabilities: { resolve() { throw new TypeError("not used"); }, }, openAuthorizedSource: async () => ({ ok: true, value: source }) as never, showSaveFilePicker: async () => handle, userActivation: { isActive: true }, now: () => NOW, }); const deliveryResult = await downloads.deliver({ policy: closePolicy, source: { kind: "AUTHORIZED_STREAM_RESOURCE", resourceId: "resource-1", capability: capability as never, }, suggestedFileName: "artifact.bin", signal: controller.signal, onProgress() {}, }); void deliveryResult; expect(closes).toBe(1); }); /** * TR-02. A lease that resolved after the abort already ended the delivery * never reached the holder, so nothing closed it: the fetch reader and the * capability lease outlived the terminal result. */ it("closes a source lease that arrives after the delivery was aborted", async () => { const bytes = new Uint8Array([1, 2, 3]); let closes = 0; const controller = new AbortController(); let releaseOpen: | ((value: { ok: true; value: unknown }) => void) | undefined; const source = { byteLength: bytes.byteLength, integrity: "VERIFIED_ON_SUCCESSFUL_EXHAUSTION" as const, capability: undefined as never, close() { closes += 1; }, async *stream() { yield { ok: true as const, value: bytes }; }, }; const capability = Object.freeze({ capabilityReceipt: "capability-late-1", method: "GET" as const, binding: { kind: "DOWNLOAD" as const, resourceId: "resource-1" }, mediaType: "application/octet-stream", byteLength: bytes.byteLength, maxBytes: bytes.byteLength, expectedSha256: "a".repeat(64), expiresAtEpochMs: NOW + 60_000, }); source.capability = capability as never; const latePolicy = browserFilePolicyReference("download", "presigned-late"); const policies = new BrowserFilePolicyRegistry({ profiles: [ { reference: latePolicy, download: { strategy: "PROMPT_AND_STREAM", mediaType: "application/octet-stream", safeExtension: ".bin", maxTransferBytes: 64, maxBufferedBytes: 8, integrity: "REQUIRED", }, }, ], hardLimits: { maxInspectionBytes: 64, maxRetainedFileBytes: 64, maxPreviewBytes: 64, maxObjectUrlBytes: 64, maxTransferBytes: 64, }, }); const downloads = createDownloadDeliveryAdapter({ host: { handoff() {} }, policies, hardMaxObjectUrlBytes: 64, hardMaxTransferBytes: 64, browserManagedCapabilities: { resolve() { throw new TypeError("not used"); }, }, // Ignores the signal entirely and resolves only when the test says so. openAuthorizedSource: () => new Promise((resolve) => { releaseOpen = resolve as never; }) as never, showSaveFilePicker: async () => ({ async createWritable() { return new WritableStream({ write() {} }); }, }), userActivation: { isActive: true }, now: () => NOW, }); const delivering = downloads.deliver({ policy: latePolicy, source: { kind: "AUTHORIZED_STREAM_RESOURCE", resourceId: "resource-1", capability: capability as never, }, suggestedFileName: "artifact.bin", signal: controller.signal, onProgress() {}, }); await new Promise((resolve) => setTimeout(resolve, 0)); controller.abort(); const delivered = await delivering; expect(delivered.ok).toBe(false); // The lease arrives only now, long after the terminal result. releaseOpen?.({ ok: true, value: source }); await new Promise((resolve) => setTimeout(resolve, 0)); expect(closes).toBe(1); }); it("does not leave a late rejection unhandled after an abort", async () => { const unhandled: unknown[] = []; const onUnhandled = (reason: unknown) => unhandled.push(reason); process.on("unhandledRejection", onUnhandled); try { const controller = new AbortController(); let rejectOpen: ((reason: unknown) => void) | undefined; const rejectPolicy = browserFilePolicyReference( "download", "presigned-late-reject", ); const policies = new BrowserFilePolicyRegistry({ profiles: [ { reference: rejectPolicy, download: { strategy: "PROMPT_AND_STREAM", mediaType: "application/octet-stream", safeExtension: ".bin", maxTransferBytes: 64, maxBufferedBytes: 8, integrity: "REQUIRED", }, }, ], hardLimits: { maxInspectionBytes: 64, maxRetainedFileBytes: 64, maxPreviewBytes: 64, maxObjectUrlBytes: 64, maxTransferBytes: 64, }, }); const downloads = createDownloadDeliveryAdapter({ host: { handoff() {} }, policies, hardMaxObjectUrlBytes: 64, hardMaxTransferBytes: 64, browserManagedCapabilities: { resolve() { throw new TypeError("not used"); }, }, openAuthorizedSource: () => new Promise((_resolve, reject) => { rejectOpen = reject; }) as never, showSaveFilePicker: async () => ({ async createWritable() { return new WritableStream({ write() {} }); }, }), userActivation: { isActive: true }, now: () => NOW, }); const delivering = downloads.deliver({ policy: rejectPolicy, source: { kind: "AUTHORIZED_STREAM_RESOURCE", resourceId: "resource-1", capability: Object.freeze({ capabilityReceipt: "capability-late-2", method: "GET" as const, binding: { kind: "DOWNLOAD" as const, resourceId: "resource-1" }, mediaType: "application/octet-stream", byteLength: 3, maxBytes: 3, expectedSha256: "a".repeat(64), expiresAtEpochMs: NOW + 60_000, }) as never, }, suggestedFileName: "artifact.bin", signal: controller.signal, onProgress() {}, }); await new Promise((resolve) => setTimeout(resolve, 0)); controller.abort(); await delivering; rejectOpen?.(new Error("late open failure")); await new Promise((resolve) => setTimeout(resolve, 10)); expect(unhandled).toEqual([]); } finally { process.off("unhandledRejection", onUnhandled); } });});