-- Keep a client upload key CLAIMED when the deletion was a host takedown.
--
-- Migration 026 narrowed `upload_client_upload_id_key` to live rows so that a guest who deletes
-- their own photo and whose queue later retries gets a fresh upload instead of a permanent 409.
-- That rationale reasoned only about the GUEST deleting. `deleted_at` is also set by
-- `host_delete_upload`, and for that case the same rule undoes a moderation decision:
--
--   1. Guest uploads. The row commits and the photo appears in the feed, but the response is lost
--      on the way back (the flaky-wifi case this whole feature exists for), so the phone keeps the
--      queue item.
--   2. The host sees the photo and takes it down. `deleted_at` is stamped, the keepsake epoch is
--      bumped, and the archive is rebuilt without it.
--   3. Ten minutes later the phone reconnects and retries. The key is no longer claimed, the
--      INSERT succeeds, and the photo is BACK — in the feed, in the next keepsake, under a NEW
--      uuid that matches nothing in the host's moderation history, with nothing logged to say a
--      takedown was undone.
--
-- So the key stays claimed for a host takedown and is released only for a guest's own delete. The
-- retry then resolves to the duplicate path and is refused, which is the correct answer: the photo
-- was deliberately removed, and re-sending the bytes must not bring it back.
ALTER TABLE upload ADD COLUMN taken_down_by_host BOOLEAN NOT NULL DEFAULT FALSE;

-- KEEP THE PREDICATE IN LOCKSTEP WITH `Upload::create`'s ON CONFLICT clause (models/upload.rs).
-- A drift between the two is not a compile error here — queries are checked at runtime — it is a
-- 500 on every upload that carries a key, i.e. on exactly the retries this index exists to serve.
DROP INDEX IF EXISTS upload_client_upload_id_key;
CREATE UNIQUE INDEX upload_client_upload_id_key ON upload (client_upload_id)
    WHERE client_upload_id IS NOT NULL AND (deleted_at IS NULL OR taken_down_by_host);
