REUSE: share the browser download action and object URL cleanup #730

Open
opened 2026-10-02 13:06:37 +00:00 by kayg · 3 comments
Owner

Context

Static rev-consistency review for #427 on origin/dev at c4a61e8cf090170f35b1bed3350d9de20c83ecd5. The reuse gate requires one owner for duplicated helpers.

Evidence

  • apps/web/src/lib/files/transfer.ts:195-218 owns downloadItems. It creates/clicks a download anchor and, for a Blob, makes an object URL and schedules its revocation after 60 seconds.
  • apps/web/src/lib/files/RecentView.svelte:283-287 repeats the direct-file anchor sequence instead of calling downloadItems.
  • apps/web/src/lib/files/PublicLinkPage.svelte:210-226 repeats both the direct anchor sequence and Blob URL + 60-second revocation sequence. Its password headers and public-link URL construction are specific to the public link and must stay with that caller.
  • apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:47-55 also constructs a Blob URL and download anchor, with a different revocation delay. This caller handles sensitive recovery text; a shared save primitive must not log bytes or send them to the server.

Expected and shared fix

Route Recent file downloads through the existing downloadItems. Extract only the repeated browser-save action to one shared helper that accepts a prepared URL or Blob and a file name. Keep authenticated endpoint selection, public-link password headers and recovery-file contents with their existing owners. Keep download data out of logs.

Test idea

Use DOM/URL spies to check one click, the requested name and object URL cleanup after the shared retention time. Verify that the direct URL path allocates no Blob URL. Check Recent downloads, a password-protected public link and a recovery-file save through their callers. Check that authentication headers remain on the public fetch and do not enter the save helper.

Searched open and closed issues for download helper, and inspected the full issue title list. Existing download issues cover sync transfers, byte access or specific public-link options. None covers this browser-save helper duplication.

## Context Static rev-consistency review for #427 on `origin/dev` at `c4a61e8cf090170f35b1bed3350d9de20c83ecd5`. The reuse gate requires one owner for duplicated helpers. ## Evidence - `apps/web/src/lib/files/transfer.ts:195-218` owns `downloadItems`. It creates/clicks a download anchor and, for a Blob, makes an object URL and schedules its revocation after 60 seconds. - `apps/web/src/lib/files/RecentView.svelte:283-287` repeats the direct-file anchor sequence instead of calling `downloadItems`. - `apps/web/src/lib/files/PublicLinkPage.svelte:210-226` repeats both the direct anchor sequence and Blob URL + 60-second revocation sequence. Its password headers and public-link URL construction are specific to the public link and must stay with that caller. - `apps/web/src/lib/auth/components/RecoveryKeyWords.svelte:47-55` also constructs a Blob URL and download anchor, with a different revocation delay. This caller handles sensitive recovery text; a shared save primitive must not log bytes or send them to the server. ## Expected and shared fix Route Recent file downloads through the existing `downloadItems`. Extract only the repeated browser-save action to one shared helper that accepts a prepared URL or Blob and a file name. Keep authenticated endpoint selection, public-link password headers and recovery-file contents with their existing owners. Keep download data out of logs. ## Test idea Use DOM/URL spies to check one click, the requested name and object URL cleanup after the shared retention time. Verify that the direct URL path allocates no Blob URL. Check Recent downloads, a password-protected public link and a recovery-file save through their callers. Check that authentication headers remain on the public fetch and do not enter the save helper. ## Duplicate search Searched open and closed issues for `download helper`, and inspected the full issue title list. Existing download issues cover sync transfers, byte access or specific public-link options. None covers this browser-save helper duplication.
Author
Owner

Starting the reuse pass for #727, #729, #730 and #799 on branch job/reuse.

Starting commit/base: 2f4482ded066d9c5d9c59130377907f7fd2916c9, the same commit as job/merge-round-7a. I will merge origin/dev and re-merge job/merge-round-7a once before final gates.

Starting the reuse pass for #727, #729, #730 and #799 on branch `job/reuse`. Starting commit/base: `2f4482ded066d9c5d9c59130377907f7fd2916c9`, the same commit as `job/merge-round-7a`. I will merge `origin/dev` and re-merge `job/merge-round-7a` once before final gates.
Author
Owner

Implementation evidence for #730: the old implementation failed the caller-reuse regression because browserDownload.ts was absent, and its runtime helper checks received null/undefined. Recent now routes single-item downloads through downloadItems. Files uses saveBrowserDownload for both prepared URLs and ZIP Blobs. Public links keep { headers } on fetch and pass only the response Blob to the helper. RecoveryKeyWords passes a text Blob; neither caller exposes its contents to logs or helper headers.

The shared helper creates an object URL only for Blob input, clicks one named anchor, removes it, and revokes its URL after the shared 60,000 ms retention. The direct URL test confirms it allocates and revokes no object URL.

Focused test output, verbatim:

 Test Files  1 passed (1)
      Tests  3 passed (3)

Commit: afb013244.

Implementation evidence for #730: the old implementation failed the caller-reuse regression because `browserDownload.ts` was absent, and its runtime helper checks received `null`/`undefined`. Recent now routes single-item downloads through `downloadItems`. Files uses `saveBrowserDownload` for both prepared URLs and ZIP Blobs. Public links keep `{ headers }` on `fetch` and pass only the response Blob to the helper. RecoveryKeyWords passes a text Blob; neither caller exposes its contents to logs or helper headers. The shared helper creates an object URL only for Blob input, clicks one named anchor, removes it, and revokes its URL after the shared 60,000 ms retention. The direct URL test confirms it allocates and revokes no object URL. Focused test output, verbatim: ```text Test Files 1 passed (1) Tests 3 passed (3) ``` Commit: `afb013244`.
Author
Owner

Finished on branch job/reuse at head b5544daeda. Added the shared browser download helper and migrated Recent downloads, PublicLink, and RecoveryKeyWords. Focused regression tests passed (3/3), and bun run check passed with 0 errors and 0 warnings. The full serialized web suite ran 3,563.01s and failed only on 7 timeouts under host load (1,075/1,082 tests passed); details and exact output are in the final #727 report. Required production screenshot matrix could not run because the media sandbox guard detected 6,188 local threads (limit 4,096). No Rust source changed, so Rust crate gates were not applicable. No merge or push performed.

Finished on branch job/reuse at head b5544daedac6d8027a323167d9b188a5262d6eb5. Added the shared browser download helper and migrated Recent downloads, PublicLink, and RecoveryKeyWords. Focused regression tests passed (3/3), and bun run check passed with 0 errors and 0 warnings. The full serialized web suite ran 3,563.01s and failed only on 7 timeouts under host load (1,075/1,082 tests passed); details and exact output are in the final #727 report. Required production screenshot matrix could not run because the media sandbox guard detected 6,188 local threads (limit 4,096). No Rust source changed, so Rust crate gates were not applicable. No merge or push performed.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#730
No description provided.