Root cause: the deploy pipeline re-ran the project seed SQL on every push — that script deletes and re-inserts the 9 seed rows with an empty image field, wiping the uploaded image references each time. Removed it from the migration list; verified the live image slots persist across a fresh deploy.
Added a reorder endpoint that swaps project sort order from the admin, and a full image-history store that records every image upload/restore event with a live "restore this version" action — so no uploaded version is ever lost again.