mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-10-26 06:19:49 +00:00
cf324741dc
* fix(store): delete issued grants before tabs in account deletion (BUG-3288) A revoke of a grant that removes the grantee's last access to a workspace takes the grant row, then the grantee's tab row there. DeleteAccountAtomic deleted the tabs of its owned workspaces first and the grants it issued later, so a revoke of one of those grants racing the granter's account deletion deadlocked on Postgres (40P01). The deletion now deletes the issued grants first, so both transactions take the grant row first. delete_account_writer_lockorder_test.go probes eight writers against an account deletion: a free race, plus two constructed interleavings that park the deletion mid-transaction. Both grant-revoke legs were red before this change in all three modes. The deleting user as a share-link viewer fails on a foreign key instead (23503), which is BUG-3289 and is not in this probe. Claude-Session: https://claude.ai/code/session_016PXRzXhokr61CLbbu3Txj9 * test(store): the probe's writers must succeed or lose one declared way (BUG-3288) Codex round 1: the parked harness accepted any non-deadlock writer error, so a writer that failed before reaching the contested rows passed. Each writer now declares the one error it may lose with (measured on Postgres), and the writer check no longer forgives sql.ErrNoRows. Claude-Session: https://claude.ai/code/session_016PXRzXhokr61CLbbu3Txj9 * test(store): match the probe's writer losses on sentinels, not wrapper text (BUG-3288) Codex round 2: the grantee-side revoke's allowance matched "lock user", which a deadlock taking that lock also carries. Losses are now predicates: sql.ErrNoRows for a row the deletion removed, and for the assignment leg the membership refusal or an FK violation. The free race also accepts sql.ErrNoRows, since the deletion can commit before the writer reads its row (always on SQLite, which the previous head failed on in make test); the parked legs stay strict. Claude-Session: https://claude.ai/code/session_016PXRzXhokr61CLbbu3Txj9