The idempotency key was only readable as a multipart FIELD, and a field cannot
be read until the body is being parsed — which happens after the lock/release
pre-flight. So the replay was unreachable in exactly the case it exists for:
the photo commits → the response is lost on the way back (the flaky-wifi
failure the key was added for) → the host releases the gallery at the end of
the night → the phone's retry answers `gallery_released`.
The guest is told a photo that is sitting in the gallery was never sent. And
the remedy the client offers is destructive: `open_event` clears
`export_released_at` AND bumps `export_epoch`, retiring the whole keepsake
generation and forcing a multi-GB rebuild on a 2-vCPU box at midnight — to
re-send a photo that was never missing. Several guests on one flaky evening
make this likely to happen at least once.
The key is now also sent as `X-Client-Upload-Id`, which arrives with the
request line, so the answer is knowable before anything is decided about
locks. The multipart field stays for the concurrent case and as a fallback.
Placed ahead of the hourly rate limiter too, which was the same mistake one
layer up: a 40-photo burst with two retries apiece exhausted the guest's hour
on uploads that had all committed the first time.
The body is still drained rather than abandoned — replying before reading it
makes the proxy see a broken pipe and turn a clean 200 into a 502.
The spec carries its own control: a DIFFERENT photo is asserted to still be
refused with `gallery_released` after the release, so the replay cannot be
green merely because the gate was open.