From 483998dec1dc129d0625777190082d365b315c4a Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 20 May 2026 15:42:21 +0200 Subject: [PATCH] =?UTF-8?q?feat(02-02):=20wire-format=20=E2=80=94=20extend?= =?UTF-8?q?=20PortMessage=20with=20CREATE=5FDOWNLOAD=5FURL/DOWNLOAD=5FURL/?= =?UTF-8?q?REVOKE=5FDOWNLOAD=5FURL=20(D-P2-01)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PortMessageType union grows 4 → 7 entries adding the D-P2-01 Blob URL migration triplet (CREATE_DOWNLOAD_URL, DOWNLOAD_URL, REVOKE_DOWNLOAD_URL). - PortMessage interface gains optional dataBase64, mimeType, url fields following the same optional-tagged-union pattern as the existing segments? field. Wire format reuses the D-12 base64 precedent from src/shared/binary.ts (chrome.runtime.Port JSON-serializes payloads). - Docstring above the union explains the SW↔offscreen mint/revoke lifecycle and points to .planning/phases/02-stabilize-export-pipeline/ 02-CONTEXT.md D-P2-01 for the full architectural rationale. - No SessionMetadata changes — meta.urls migration is Plan 02-03 territory. --- src/shared/types.ts | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) 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