The browser upload flow was built around one selected file and one global
upload state. That made the existing chunk pool useful for a single file, but
users could not start several selected files at the same time.
Refactor the browser state into per-file upload items. Each selected file now
has its own upload record, completed-chunk set, abort controller, retry state,
progress row, and saved IndexedDB resume record. The picker accepts multiple
files, `Start all` and `Resume all` use a bounded file-level pool, and each file
keeps the existing bounded chunk pool. This keeps parallel uploads useful
without letting one large selection create unbounded request fan-out.
Keep the server API unchanged. Each file still receives a separate server upload
id, and server-side progress remains authoritative before any missing chunks are
scheduled. Terminal conflicts still stop the affected file without overwriting
completed data.
Update the user-facing markup, styles, project docs, and test checklist for the
multi-file scheduler. Add a server regression test that interleaves two uploads
and verifies the completed files contain exactly their own bytes.
Test Plan:
- just check
- git diff --check
Document the minimal design for a personal large-file upload app that can
resume after browser, network, or server interruptions. The plan keeps the
first version intentionally small: one Rust server, one static browser UI,
filesystem-backed upload metadata, raw chunk uploads, and no database or
third-party resumable upload protocol.
The deployment notes include nginx as the external TLS and access-control
layer, with the Rust server bound behind it and upload-specific proxy settings
called out.
Test Plan:
- git diff --cached --check
Refs: user request