The fetch-error and file-receipt-not-proven lines are gone: a failure folds into the one fetch line as cause=Class/status, never a message.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
chat_fetch_request.v1 [request_id, persona, room, event_id] and chat_fetch_receipt.v1
[request_id, outcome, room_id, image, receipt] with a closed 14-word outcome enum. The mouth
reads live membership, the full room state, and the event itself; takes content.url from the
event; fetches through fetchImage (one optional deadline signal added); decides info.sha256
against the computed hash before images.put; posts the contract's org.gamecult.file_received
as her own user (thread reply, else plain m.reference), idempotence read from Matrix.
One 15 s deadline owns the fetch; throwIfAborted and released() are the first step inside the
gate, as send does. Event id, room, and the sender-controlled album root must be path-safe
Matrix ids or nothing is built from them. Golden fixtures persona-chat-v7.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>