Context
File uploads are initiated from multiple parts of the system (content, pages, profiles, imports, etc.).
Historically, this leads to upload logic being reimplemented per module, causing:
- duplicated progress UI
- inconsistent error handling
- fragile state tied to routes or components
- unclear ownership of retries, cancellations, and recovery
Uploads are inherently long-running, failure-prone, and infrastructure-like, and therefore unsuitable to be managed at the feature level.
Decision
Introduce a single, centralized UploadEngine responsible for the full upload lifecycle.
All feature modules initiate uploads by calling:
UploadEngine.start({...})
After initiation, modules relinquish all responsibility for upload tracking, progress, retries, or error handling.
Consequences
- Upload behavior is consistent across the system
- Feature modules remain simple and intent-focused
- Uploads can safely survive route changes and reloads
- Upload logic becomes infrastructure-grade and independently evolvable
- A single global UI can reflect upload state without duplication
Notes
- This ADR establishes ownership, not implementation.
- Subsequent ADRs define initiation semantics, UI responsibilities, and state authority.