Resolved.
Made approve/reject atomic. Added two new model methods that do the state check and the update in a single SQL statement:
public static function approveIfQuarantined(int $id, int $by): bool
public static function rejectIfQuarantined(int $id, string $reason): bool
Each runs UPDATE file_uploads SET status = 'approved' WHERE id = :id AND status = 'quarantine' and returns rowCount() === 1. The controller now only proceeds with the audit log / flash / unlink when it won the race.
Also applied M-12 (missing basename() on stored_name in reject and deleteFile) in the same pass — defence in depth against a poisoned DB row.
Race scenario now: two admins click Reject simultaneously → exactly one passes the atomic UPDATE, unlinks the file, and logs the audit entry; the other sees "File is no longer in quarantine." No double unlink, no approved-but-deleted split-brain.
Also resolves M-12.
Locking this thread.