Advertise TUS Expiration extension and emit Upload-Expires header (spec-compliance follow-up)
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 368
Description
## Background
The storage-proxy TUS implementation after the BA-3974 fix stack advertises only `Tus-Resumable: 1.0.0` plus `Tus-Extension: checksum` (added by BA-6158). However, it already implements server-side behavior that maps to the TUS Expiration extension — Valkey-backed session metadata expires by a 24h TTL refreshed on every successful PATCH — but does not advertise the extension and does not emit the standard `Upload-Expires` response header that a spec-compliant client expects.
This issue tracks closing that spec-compliance gap. The race-correctness scope of BA-3974 is unaffected; this is a follow-up focused on protocol conformance and client interoperability.
## Current state (after BA-3974 stack)
- Core (HEAD + PATCH): implemented, advertised
- Checksum: implemented (sha256), advertised via BA-6158
- Expiration: behavior present (Valkey TTL = 24h, sliding via every PATCH), but NOT advertised and no Upload-Expires header
- Creation: partially supported via non-standard POST /folder/file/upload (manager API), not advertised
- Termination: not implemented, not advertised
- Concatenation: not implemented, not advertised
## Work needed (minimum scope to close this issue)
### 1. Advertise the Expiration extension
The Valkey-backed session TTL already implements exactly what the Expiration extension describes. Advertise it.
- In `tus_options`: set `Tus-Extension: checksum,expiration`
- Add `Upload-Expires` to `Access-Control-Allow-Headers` and `Access-Control-Expose-Headers`
### 2. Emit Upload-Expires response header
PATCH and HEAD responses must include `Upload-Expires: `. Simplest source: `now + REDIS_TUS_TTL` since the TTL is refreshed on every successful PATCH. For HEAD, can either query Valkey `TTL` for the exact remaining seconds or emit `now + REDIS_TUS_TTL` as a conservative upper bound.
### 3. (Optional) 410 Gone for expired sessions
Currently a request hitting an expired session returns 404 `TusSessionNotFoundError`. The spec recommends 410 Gone for expired sessions. Distinguishing 'never created' from 'expired' requires a tombstone marker in Valkey with longer TTL or inference from the JWT issue time. Low ROI; can be deferred to a separate follow-up.
## Out of scope (separate follow-ups)
- 410 Gone on expired sessions (item 3 above).
- Adding a standard Creation extension endpoint (currently uses a non-standard manager API).
- Termination extension (DELETE).
- Concatenation extension (partial/final, parallel uploads).
## Acceptance criteria
- `Tus-Extension` header advertises `expiration` in addition to whatever is already advertised.
- PATCH and HEAD responses include a valid `Upload-Expires` HTTP-date header reflecting the Valkey TTL.
- `Access-Control-Allow-Headers` and `Access-Control-Expose-Headers` list `Upload-Expires`.
- Unit tests verify the header values.
## References
- TUS 1.0.0 spec: [https://tus.io/protocols/resumable-upload](https://tus.io/protocols/resumable-upload)
- Parent epic: BA-6153
- Related fix stack: BA-6155 / BA-6156 / BA-6157 / BA-6158 / BA-6159
JIRA Issue: BA-6272
Contributor guide
Research direction
Start at `tus_options`, the PATCH and HEAD handlers, and `REDIS_TUS_TTL`; inspect the existing unit tests for TUS responses. Done means the expiration extension is advertised, PATCH and HEAD emit valid `Upload-Expires` dates, CORS headers expose it, and unit tests verify the header values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, redis
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100