diff --git a/src/shared/types.ts b/src/shared/types.ts index 5d4ae3a..72f9ba7 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -40,11 +40,27 @@ export interface Message { // SW can match a response to the in-flight request that issued it. // This retires the silent-cross-talk failure mode where a stale // BUFFER from a prior request would route into a newer Promise. +// +// D-P2-01 Blob URL migration triplet (P0-6 fix, Phase 02 Plan 02-02): +// - CREATE_DOWNLOAD_URL + DOWNLOAD_URL + REVOKE_DOWNLOAD_URL. +// SW posts CREATE_DOWNLOAD_URL with the archive bytes as base64; +// offscreen mints URL.createObjectURL and responds with DOWNLOAD_URL; +// SW calls chrome.downloads.download(url); when chrome.downloads +// .onChanged reports 'complete' or 'interrupted', SW posts +// REVOKE_DOWNLOAD_URL so offscreen can free the URL. The base64 +// wire-format reuses the D-12 precedent from src/shared/binary.ts — +// chrome.runtime.Port JSON-serializes payloads, so Blob → empty +// object; base64 round-trips cleanly. See +// .planning/phases/02-stabilize-export-pipeline/02-CONTEXT.md +// D-P2-01 for the full architectural rationale. export type PortMessageType = | 'PING' | 'PONG' | 'REQUEST_BUFFER' - | 'BUFFER'; + | 'BUFFER' + | 'CREATE_DOWNLOAD_URL' // SW → offscreen: "here is a Blob as base64; mint a URL for it" + | 'DOWNLOAD_URL' // offscreen → SW: "here is the minted blob:URL" + | 'REVOKE_DOWNLOAD_URL'; // SW → offscreen: "you can revoke this URL now" export interface PortMessage { type: PortMessageType; @@ -52,6 +68,10 @@ export interface PortMessage { // each REQUEST_BUFFER call and only resolves on BUFFER responses that // echo the same id. PING/PONG do not carry a requestId — they are // pure liveness signals. + // Also used by the D-P2-01 triplet: CREATE_DOWNLOAD_URL → DOWNLOAD_URL + // pair carries a per-mint requestId so concurrent mints (theoretically + // possible across two SAVE flows) cannot cross-talk. REVOKE_DOWNLOAD_URL + // is fire-and-forget — no requestId required. requestId?: string; // Wire-format (D-12 base64 transfer + D-13 segment lifecycle): // segments travel as TransferredVideoSegment[] because @@ -61,6 +81,17 @@ export interface PortMessage { // + seed keyframe). The receive side reconstructs VideoSegment[] // via src/shared/binary.ts. segments?: TransferredVideoSegment[]; + // D-P2-01 (P0-6 fix): archive bytes as base64 + MIME type for Blob + // reconstruction in the offscreen document on CREATE_DOWNLOAD_URL. + // Reuses src/shared/binary.ts blobToBase64/base64ToBlob helpers; same + // wire-format precedent as the BUFFER segment transfer. + dataBase64?: string; + mimeType?: string; + // D-P2-01: the minted blob:URL string on DOWNLOAD_URL (offscreen → SW) + // OR the URL to free on REVOKE_DOWNLOAD_URL (SW → offscreen). The + // string is a `blob:chrome-extension:///` URL minted by + // URL.createObjectURL in the offscreen document origin. + url?: string; } // In-memory segment shape used by mergeVideoSegments after the SW