Upload pause images through cloud-router to shared tusd
## Goal summary Replace pause-image URL registration with a file-upload flow. Cloud-router receives the image, uploads it to the shared pause-image tusd server through the CR proxy, then registers the resulting fetchable URL with the room. The box/local-streamer does not upload the source image. ## Proposed behavior / user flow - In the room Pause panel, an authorized operator enters a name and selects an image file instead of supplying a URL and SHA-256 value. - The dashboard submits the file to cloud-router and shows upload/registration progress and errors. - Cloud-router validates the request, uploads the bytes to the configured shared tusd server, computes SHA-256, and only then publishes the existing `SetPauseImage { name, url, sha256 }` command. - Local-streamer keeps the established download/cache behavior and reports the registered name through `RoomStatus`; pause selection and deletion remain unchanged from the operator's perspective. - If cloud-router is not configured for pause-image storage, return a clear service/configuration error rather than accepting an unusable registration. ## Major implementation areas - Configure cloud-router with the dedicated shared pause-image tusd server ID. Use the same CR proxy credential and route shape already issued to boxes for recording uploads; this server ID identifies/authenticates the shared pause-image tusd target. - Replace the existing authenticated `PUT /api/rooms/{meeting_room_id}/pause-images/{name}` JSON URL contract with a bounded image upload. This is intentionally breaking; do not retain a parallel URL-based endpoint. - Validate supported image type, name, and size; upload to tusd; then dispatch the existing room command using the proxy's fetchable URL and cloud-router's computed digest. - Update OpenAPI, cloud-router/deployment environment documentation, and compose examples. - Extend the dashboard request helper to support file bodies and replace the URL/SHA form in `RoomToolsRail.vue` with a file picker and useful pending/error state. - Keep the NATS protocol and local-streamer image registry/download path unchanged. ## Existing code/patterns to reuse or extend - Reuse `RequireRoomsManage`, `ensure_registered`, `send_setup_command`, and the current pause-image route/command flow in `cloud-router/src/handlers/pause_image.rs`. - Extract/reuse the existing reqwest-based tus 1.0 client in `local-streamer/src/upload/tus.rs` through shared workspace code rather than introducing a second tus implementation or dependency. - Preserve the current `SetPauseImage` URL + optional SHA-256 wire contract and local-streamer's verified download/cache behavior. - Follow the existing box upload proxy credential conventions and optional env-backed service configuration patterns. ## Duplication risks / refactor opportunities - The tus protocol headers, relative `Location` handling, auth, and errors should have one shared implementation usable by recording and pause-image uploads. - Keep upload validation constants/types shared where practical so cloud-router's accepted payload cannot exceed what local-streamer can safely cache. ## Important edge cases / failure modes - Reject empty/unsafe names, empty files, unsupported or mismatched media types, oversized payloads, and malformed configuration before publishing to the room. - Do not send `SetPauseImage` when tus creation/PATCH fails or completes short; surface authentication, network, and storage failures distinctly enough for operators. - Ensure the URL given to local-streamer is a readable object URL, not merely a tus PATCH/HEAD resource, and remains reachable from deployed boxes. - Uploading the same room/name replaces the room registration only after the new upload completes. - Deleting or replacing a pause image does not delete the object from tusd; orphan cleanup is outside this change. - Avoid unbounded buffering and do not log upload credentials or image bytes. ## Major refactors - Small shared-code extraction for the existing tus client is expected. No NATS protocol migration or local-streamer upload feature is needed. ## Validation approach - Unit/integration tests against the existing in-process mock tus server for creation, chunk completion, auth/storage failures, URL resolution, hashing, validation limits, and ensuring no command is published after upload failure. - API tests establish that the former JSON URL body is rejected and the new image upload succeeds. - Existing protocol round-trip and local-streamer pause-image tests continue to pass. - Dashboard build/lint plus a browser flow covering file selection, successful registration/status refresh, replacement, deletion, and visible failure states. - Run `cargo fmt --all`, `cargo check --workspace`, and relevant `cargo test` targets.
Checklist
0 of 0 completeNo checklist items.
- Area
- Streaming
- Project
- streaming-engines
- Kind
- Feature
- Priority
- Medium
- Task ID
tsk_smgx4ky3c8- Updated