Skip to content

fix(addon): authenticate teardown cleanup so the add-on removes orphaned upload parts#989

Open
aaspinwall wants to merge 2 commits into
mainfrom
feat/addon-teardown-auth-on-984
Open

fix(addon): authenticate teardown cleanup so the add-on removes orphaned upload parts#989
aaspinwall wants to merge 2 commits into
mainfrom
feat/addon-teardown-auth-on-984

Conversation

@aaspinwall

Copy link
Copy Markdown
Collaborator

What changed?

The best-effort teardown cleanup that removes already-written multipart parts when a user closes the tab/popup mid-upload (Uploader.teardownCleanup in packages/send/frontend/src/lib/upload.ts) now authenticates with the OIDC Bearer token instead of relying on a cookie.

  • doUpload pre-captures the access token at upload start (via the same dynamic-import-of-auth-store pattern lib/api.ts uses), because getAccessToken() is async and can't be awaited at the pagehide unload event.
  • teardownCleanup attaches Authorization: Bearer <token> on its keepalive fetch, keeping credentials: 'include' as the web cookie fallback.
  • Adds a regression test asserting that a pagehide during an in-flight multipart upload issues an authenticated keepalive POST /api/uploads/cleanup with the Bearer header.

AI disclosure: Substantially agent-written by Claude Code (Anthropic, Opus 4.8) under human direction — the human set the scope, chose to base the change on #984, and reviewed the diff (including a senior-review pass whose findings were applied). ~2 files, +114/−7.

Why?

The Send web app authenticates with cookies, but the Thunderbird add-on authenticates via an OIDC Bearer token bridge and has no usable backend cookie in its extension-popup origin. So the cookie-only teardown fetch 401'd in the add-on — meaning the orphaned-part cleanup from #965 was effectively web-only, and cancel/tab-close mid-upload stranded bytes in the bucket for add-on users. This makes cancel/close cleanup behave identically in both surfaces, so we maintain one upload workflow.

Limitations and Notes

Applicable Issues

Relates to #887 (multipart orphaned-storage cleanup).

Screenshots

No UI change.

aaspinwall and others added 2 commits July 9, 2026 16:47
…" stall)

Rework the client-side upload path so large files start uploading promptly
and no longer hit Firefox's 2 GB Blob limits.

- Stream the source via blob.stream() from offset 0 and produce hashed,
  zipped parts lazily (streamZippedParts). Uploading now starts after the
  first 100 MB window instead of after the whole file is hashed (#980), and
  no high-offset slice/arrayBuffer read is issued, which is what fails on
  files >2 GB (#981). Each uploaded part blob is released after it lands so
  a multi-GB file doesn't stay fully resident.

- Assemble zipBlob output from JSZip's streaming chunks so it never builds a
  single >2 GB Blob member — the "can't construct the Blob" crash in
  formatBlob for typeless >2 GB files (#981). The archive bytes are
  byte-identical to the previous generateAsync output, so there is no
  download/format change.

- Add a dedicated 'hashing' ProcessStage + banner label so the UI reflects
  the real phase instead of overloading 'idle' as "Hashing…".

Backwards compatible: identical wire format (per-part raw-bytes hash, zip
parts, part numbering), no schema or API change. Covered by unit tests
(streamZippedParts window/hash/round-trip, zipBlob byte-identical) and an
end-to-end Firefox upload→download→checksum of 1/2/3 GB files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…parts

The best-effort pagehide cleanup that removes already-written multipart
parts when the user closes the tab/popup mid-upload issued a raw keepalive
fetch with cookie auth only. That works in the Send web app but not in the
Thunderbird add-on, which authenticates via an OIDC Bearer token bridge and
has no usable backend cookie — so the cleanup 401'd and orphaned parts were
stranded in the add-on only.

Pre-capture the OIDC access token at upload start (getAccessToken is async
and can't be awaited at unload) via the same dynamic-import pattern api.ts
uses, and attach it as a Bearer header on the teardown fetch, keeping
credentials:'include' as the web cookie fallback. Now cancel/close cleanup
behaves identically in both contexts.

Adds a regression test asserting a pagehide during an in-flight multipart
upload issues an authenticated keepalive POST to /api/uploads/cleanup.

Rebased onto #984 (streaming large-file uploads); the test uses that PR's
streamZippedParts producer model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Base automatically changed from fix/stream-large-file-uploads to main July 14, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant