Add images and lineups to cloud strategies from the web beta (#184)

* Add images and lineups to cloud strategies from the web beta

Bytes are now the unit of cloud media upload. The queue finds a job's
bytes through one MediaBytesSource: the image file on desktop, or bytes
held in memory on web. On web a picked image is saved to a Hive box
(IndexedDB) before its upload job is written, so a refresh mid-upload
keeps it; the saved copy is dropped once the upload is attached, and a
launch prunes restored bytes that no job needs.

While it uploads, a placed or lineup image paints from those bytes
(StrategyImageSource.PendingImageBytes), then from the cloud URL once the
page snapshot carries it. reconcilePageMedia no longer asks for an image
folder on web.

The lineup picker asks file_picker for bytes, since the browser never
hands over a path. The web beta policy now offers adding images and
lineups; the canvas drop target also checks the desktop-only file drop
flag so the policy stays true. Sign-out copy mentions local strategies
only where there is a local library. The R2 doc gains the exact CORS
rule the web beta origins need, as a required dashboard step.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Record that the web beta CORS rule is applied on icarus-media

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Scope, age and release web pending image bytes safely

Pending image bytes are now stored per account, strategy and asset, the
same scope as the media upload job, so one account's upload or cleanup
never reads or deletes another account's bytes. Records are versioned
and carry when they were saved.

A launch only prunes bytes with no job that are over a week old: another
tab of the browser may still be editing a lineup draft whose job is only
written on save. Lineup drafts are let go when removed or when the dialog
closes unsaved, and images over 15 MB are refused before anything is
kept.

The in-memory copy of an uploaded image is dropped once both the attach
has landed and the page serves the cloud URL, in either order. Lineup
tiles and images are keyed by asset, so a removed image's frame never
shows on the image that moves into its slot.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Keep queued lineup images when the dialog closes mid-save

Save now hands the lineup's drafts to the upload queue before the
outbox write is awaited, and the dialog cannot be closed (Escape, the
barrier, or its close button) while Save is queuing. Before, closing it
during that await let the queued job's only bytes go. If queuing fails,
the drafts become drafts again.

A pick that finishes after the dialog closed now lets its bytes go
instead of registering a draft nobody will clean up.

The R2 doc states the 7-day draft prune plainly and notes the unreleased
first box format and desktop's missing size check.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
b0e5399927Dara Adedeji committed on 9/25/2026, 10:34:18 AM· committed by GitHubparente5baf16
22 files changedLine totals unavailable