You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The previous AuthStore::save called std::fs::write(&path, json)
directly. Two concurrent processes (e.g. two coven-code instances
finishing OAuth simultaneously, or a session save racing a /login
flush) could truncate auth.json mid-write and leave the file in a
torn state, or one of them could overwrite the other's credentials
in an interleaved fashion.
* New save_to(&Path) -> io::Result<()> writes the JSON to a sibling
tempfile (`.auth.json.tmp.{pid}.{thread-id}.{counter}`) and then
uses fs::rename to atomically swap it into place. On POSIX rename
is atomic; on Windows std::fs::rename uses MoveFileExW with
MOVEFILE_REPLACE_EXISTING.
* save() keeps its best-effort void return for backward compat and
delegates to save_to internally.
* Tempfile name uses a per-process atomic counter plus thread id so
it is unique even across 50 racing writers in the same process at
the same nanosecond.
* Two new tests:
- save_to_is_atomic_under_concurrent_writers: spawns 50 threads,
each saving a different credential. Asserts the final file is a
parseable AuthStore with exactly one entry surviving.
- save_to_does_not_leave_tempfile_behind: asserts the directory
contains only `auth.json` after a successful save.
Workspace tests: 1522 passing, 0 failing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments