You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#145 added idempotent retry of the most recently committed chunk: a client whose chunk-PUT response was lost can replay the same chunk with the previous token and the server returns the cached response without re-writing or double-counting. This unblocked transparent in-session retry in postguard-js (encryption4all/postguard-js#47).
What's still missing is cross-refresh / cross-process resume. Today, if the user reloads the page, navigates away and back, or the browser tab crashes mid-upload, all in-flight state is lost on the client even though the server's last_chunk cache and the on-disk file are still intact (assuming the session hasn't been evicted past its idle TTL).
#117 and #136 both flagged this. @dobby-coder's audit at #136 (comment) sketched two designs; we picked idempotent retry for #145. This issue tracks the second one.
Proposed design
A new authenticated GET endpoint that returns the current upload state so a client can rehydrate after losing its in-memory state:
GET /fileupload/{uuid}/status
Authorization: Bearer <recovery_token>
200 OK
{
\"uploaded\": <bytes>,
\"cryptify_token\": \"<current rolling token>\",
\"prev_token\": \"<previous rolling token, may be null if no chunk committed yet>\",
\"prev_uploaded\": <byte offset of last committed chunk, may be null>
}
recovery_token is issued at upload_init time alongside the first cryptifytoken, returned in a separate response field (e.g. recovery_token). The client stores it in IndexedDB along with the upload UUID.
The client uses prev_token + prev_uploaded to feed the existing idempotent-retry path on the very next chunk PUT, so the server's rolling-token chain stays intact even if the browser missed the response.
Cross-refresh resume only makes sense if the upload session itself survives a server restart. Today FileState is in-memory only (#116), so a Procolix redeploy or pod crash already wipes the session regardless of whether the client could remember the UUID. This issue should be picked up after the Postgres-backed sessions land (#116, #134) — otherwise we're shipping client recovery for a server that can't actually recover.
Out of scope for this issue
The client-side IndexedDB persistence and rehydrate-on-reload flow in postguard-js — tracked separately at encryption4all/postguard-js#X (filed alongside this).
Resumable downloads — also tracked separately in postguard-js (cryptify's FileServer already supports Range, so it's a pure SDK concern).
Acceptance criteria
GET /fileupload/{uuid}/status returns the schema above for live sessions
Endpoint requires the recovery_token issued at init; missing/invalid → 401
Background
#145 added idempotent retry of the most recently committed chunk: a client whose chunk-PUT response was lost can replay the same chunk with the previous token and the server returns the cached response without re-writing or double-counting. This unblocked transparent in-session retry in postguard-js (encryption4all/postguard-js#47).
What's still missing is cross-refresh / cross-process resume. Today, if the user reloads the page, navigates away and back, or the browser tab crashes mid-upload, all in-flight state is lost on the client even though the server's
last_chunkcache and the on-disk file are still intact (assuming the session hasn't been evicted past its idle TTL).#117 and #136 both flagged this. @dobby-coder's audit at #136 (comment) sketched two designs; we picked idempotent retry for #145. This issue tracks the second one.
Proposed design
A new authenticated GET endpoint that returns the current upload state so a client can rehydrate after losing its in-memory state:
recovery_tokenis issued atupload_inittime alongside the firstcryptifytoken, returned in a separate response field (e.g.recovery_token). The client stores it in IndexedDB along with the upload UUID.prev_token+prev_uploadedto feed the existing idempotent-retry path on the very next chunk PUT, so the server's rolling-token chain stays intact even if the browser missed the response.upload_session_not_foundbody from feat(upload): structured 404 body + configurable session TTL #144) when the session has been evicted or never existed.Why this needs Phase 2 first
Cross-refresh resume only makes sense if the upload session itself survives a server restart. Today
FileStateis in-memory only (#116), so a Procolix redeploy or pod crash already wipes the session regardless of whether the client could remember the UUID. This issue should be picked up after the Postgres-backed sessions land (#116, #134) — otherwise we're shipping client recovery for a server that can't actually recover.Out of scope for this issue
FileServeralready supportsRange, so it's a pure SDK concern).Acceptance criteria
GET /fileupload/{uuid}/statusreturns the schema above for live sessionsrecovery_tokenissued at init; missing/invalid → 401upload_session_not_foundbody (matches feat(upload): structured 404 body + configurable session TTL #144)upload_initresponse includes therecovery_token(additive — old clients ignore it)Refs
usage_dbis currently unused) #134 (this repo, blocking work)