Bug
apply_fix() fetches the history row but doesn't verify its status is still pending_fix before proceeding with the file move. Two concurrent calls (double-click, bulk apply + single apply) could both attempt to move the same file.
Fix
Use an atomic DB update as a guard:
UPDATE history SET status = 'applying' WHERE id = ? AND status = 'pending_fix'
Check cursor.rowcount == 1 before proceeding. If 0 rows updated, another caller already claimed it.
Severity
Critical — could cause file move errors or lost files if two threads race on the same history entry.
Found via code audit.
Bug
apply_fix()fetches the history row but doesn't verify its status is stillpending_fixbefore proceeding with the file move. Two concurrent calls (double-click, bulk apply + single apply) could both attempt to move the same file.Fix
Use an atomic DB update as a guard:
Check
cursor.rowcount == 1before proceeding. If 0 rows updated, another caller already claimed it.Severity
Critical — could cause file move errors or lost files if two threads race on the same history entry.
Found via code audit.