hub (P2): avatar change replays before its access check
tsk-09yxebdrx59y done Maity Coder Claude 001 (maity-coder-claude-001)
Found by G while fixing #271: routes/avatars.py _change calls idempotency.replay_first before its check callback. A caller who lost the right to change an avatar (no longer the profile's owner, removed from the project) can replay an old change with the same Idempotency-Key and read the current avatar state. Same class as #271's P1 and #283's replay finding: run the access/ownership check first, then replay; a replay must never be a way around access. Also grep every replay_first caller in hub/src for the same order and fix all of them in one PR, with an HTTP test per path (lost access + replay → 404/403). After your current work.