Skip to content

feat(api): capture recovery_token and add resumeUpload for cross-restart resume - #66

Merged
rubenhensen merged 1 commit into
mainfrom
feat/upload-resume-recovery-token
May 13, 2026
Merged

feat(api): capture recovery_token and add resumeUpload for cross-restart resume#66
rubenhensen merged 1 commit into
mainfrom
feat/upload-resume-recovery-token

Conversation

@dobby-coder

@dobby-coder dobby-coder Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Wires the SDK side of cryptify's cross-refresh-resume protocol (cryptify#148 / cryptify#136) so consumers (Office addon, Thunderbird, website) can rehydrate an in-flight upload after a page refresh, tab crash, or process restart.

  • `initUpload` now reads the snake-case `recovery_token` from the JSON body and returns it on `FileState` as `recoveryToken`. Consumers persist `{uuid, recoveryToken}` in their own storage layer (roamingSettings / `browser.storage` / IndexedDB).
  • New `resumeUpload(cryptifyUrl, uuid, recoveryToken, signal?)` calls `GET /fileupload/{uuid}/status` with the `X-Recovery-Token` header. Returns `{ state: FileState; uploaded: number }`:
    • maps response `cryptify_token` → `state.token`, `prev_token` → `state.prevToken` (omitted before any chunk is committed), `uploaded` → byte offset to resume from
    • the returned state feeds straight into the existing `storeChunkWithRetry`, so the first chunk after resume can exercise the idempotent-retry path on a lost commit response
  • 404 `upload_session_not_found` is surfaced as `UploadSessionExpiredError` via the existing helper. Cryptify deliberately collapses "unknown UUID" and "wrong recovery_token" into the same response — callers should treat both as "start a new upload."
  • `FileState` and `resumeUpload` re-exported from the package root so consumers don't need to reach into `src/api`.

Out of scope (deliberately):

  • Persistence — consumer-owned per the issue.
  • A resume variant of `createUploadStream` — consumers feed the rehydrated state into the existing `storeChunkWithRetry` path.
  • Download-side Range — tracked at cryptify#153, server-side fix.

Closes #65.

Test plan

  • `npm ci && npm run typecheck` — clean
  • `npm test` — 86/86 passing (5 new tests for `resumeUpload`)
  • `npm run build` — clean

Reviewer quickstart: `git fetch origin && git checkout feat/upload-resume-recovery-token && npm ci && npm test`

…art resume

Wires the cross-refresh-resume protocol on the SDK side (cryptify#148):

- initUpload now reads the snake-case recovery_token field from the JSON
  body and returns it on FileState as recoveryToken.
- New resumeUpload(cryptifyUrl, uuid, recoveryToken) calls
  GET /fileupload/{uuid}/status with X-Recovery-Token, returning the
  rehydrated FileState and current byte offset. prev_token is mirrored
  to state.prevToken when present so the first chunk after resume can
  exercise the idempotent-retry path.
- 404 upload_session_not_found surfaces as UploadSessionExpiredError
  (collapses unknown-UUID and wrong-token cases per cryptify's
  info-hiding behaviour).
- FileState and resumeUpload re-exported from the package root so
  consumers (Office addon, Thunderbird, website) can own persistence.

Closes #65
@dobby-coder
dobby-coder Bot requested a review from rubenhensen May 13, 2026 14:56
@dobby-coder
dobby-coder Bot marked this pull request as ready for review May 13, 2026 14:56

@dobby-coder dobby-coder Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — cannot self-approve, but this is a clean implementation of the cryptify recovery-token resume protocol.

  • resumeUpload reuses throwSessionExpiredOrNetworkError, keeping 404 → UploadSessionExpiredError consistent with storeChunk / finalizeUpload.
  • snake-case → camelCase mapping at the API boundary; prevToken is conditionally set so pre-first-chunk shape stays clean for storeChunkWithRetry.
  • Tests cover the four paths that matter: no prev_token, with prev_token, structured 404 (expired/unknown collapsed), non-structured 404 / 401 → NetworkError. Local npm ci && npm test → 86/86 green; CI green.
  • Re-exports from src/index.ts keep consumers out of src/api. 👍

Out-of-scope items (persistence, resume variant of createUploadStream, download-side Range) are appropriately deferred per the PR body. Ready to merge from this agent's perspective.

@rubenhensen
rubenhensen merged commit 6205fc3 into main May 13, 2026
2 checks passed
@rubenhensen
rubenhensen deleted the feat/upload-resume-recovery-token branch May 13, 2026 15:42
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.7.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wire upload resume: capture recovery_token, implement GET /status for cross-restart resume

1 participant