fix(isms): lock control-link edits before write (CS-701)
Why
Flagged on the production-deploy PR #3364 (P2): addControls/removeControl wrote the control-link rows first and only then called invalidateApprovalIfNeeded (which holds the per-document lock). So the link write ran outside the lock and could interleave with approve() before serialization kicked in.
Impact was limited ā control links are not part of the frozen version snapshot, so no published version could be corrupted ā but the mutation should still be serialized like every other content edit, and the lock-before-write pattern is the correct one.
Fix
Both control transactions now take lockDocument() as their first statement, before createMany/deleteMany. The conditional invalidateApprovalIfNeeded (real-change-only) is unchanged, and the advisory lock is transaction-scoped + re-entrant, so re-taking it there is a no-op. Added an ordering test asserting the lock precedes the write.
Tests
- 325 API ISMS tests passing, typecheck clean, on top of current
main.
Completes the ISMS concurrency hardening (#3366, #3367). Flagged in #3364.
š¤ Generated with Claude Code
https://claude.ai/code/session_012CweXoSSEP89mX93u3Bdcp
Summary by cubic
Lock control-link edits before writes so addControls/removeControl run inside the per-document lock and serialize with approve(). Implements CS-701.
- Bug Fixes
- Call
lockDocumentfirst in both transactions, beforecreateMany/deleteMany, to prevent interleaving withapprove(). - Keep
invalidateApprovalIfNeededconditional; the lock is re-entrant so re-taking it is a no-op. Added a test asserting the lock precedes the write.
- Call