brain_edit: snapshot taken outside the lock and rollback after unlock can overwrite a concurrent edit #196

Open
opened 2026-10-05 21:36:57 +00:00 by mathias · 0 comments
Owner

Source: PR #194 review (non-blocking 7), 2026-10-05. This predates #194.

brainEdit (internal/mcp/tools_notes.go) does three things in sequence:

  1. It snapshots the note before notes.Edit takes the edit lock.
  2. notes.Edit edits the note under the lock.
  3. If the provenance stamp then fails, it writes the snapshot back after the lock is released.

If another pod edits the same note between steps 1 and 3, the rollback overwrites that edit, and both callers have been told they succeeded or that their edit was rolled back.

Fix: hold the edit lock across snapshot, edit, stamp and rollback, for example by moving the stamp-and-rollback into notes.Edit or exposing a locked variant. Alternatively, roll back only if the note's current hash equals the post-edit hash.

Done when: a two-process test interleaving an edit with a stamp failure in another process loses neither edit.


Created via git-mcp on behalf of @mathias

**Source:** PR #194 review (non-blocking 7), 2026-10-05. This predates #194. `brainEdit` (`internal/mcp/tools_notes.go`) does three things in sequence: 1. It snapshots the note **before** `notes.Edit` takes the edit lock. 2. `notes.Edit` edits the note under the lock. 3. If the provenance stamp then fails, it writes the snapshot back **after** the lock is released. If another pod edits the same note between steps 1 and 3, the rollback overwrites that edit, and both callers have been told they succeeded or that their edit was rolled back. **Fix:** hold the edit lock across snapshot, edit, stamp and rollback, for example by moving the stamp-and-rollback into `notes.Edit` or exposing a locked variant. Alternatively, roll back only if the note's current hash equals the post-edit hash. **Done when:** a two-process test interleaving an edit with a stamp failure in another process loses neither edit. --- _Created via git-mcp on behalf of @mathias_
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/hyperguild#196