Skip to content

Add atomic_write utility and apply to all config/state file saves#92

Merged
an0nn30 merged 3 commits intomainfrom
chore/atomic-writes
Mar 27, 2026
Merged

Add atomic_write utility and apply to all config/state file saves#92
an0nn30 merged 3 commits intomainfrom
chore/atomic-writes

Conversation

@an0nn30
Copy link
Copy Markdown
Owner

@an0nn30 an0nn30 commented Mar 27, 2026

What does this PR do?

Adds an atomic_write(path, data) utility that writes to a .tmp file then renames to the target — preventing corruption from crashes or power loss during writes. Applied to all config persistence:

  • conch_core: save_user_config() and save_persistent_state() now use atomic_write()
  • conch_remote: save_config() for servers.json now uses a local atomic_write helper
  • conch_tauri: set_config() in plugin TauriHostApi now uses conch_core::config::atomic_write()

Previously only vault.enc used atomic writes. Now all persisted files are protected.

Type of change

  • Bug fix

Testing

  • Builds without errors
  • No regressions — all workspace tests pass

7 new tests verifying: correct content, no leftover .tmp, overwrite behavior, empty data.

Notes for reviewer

  • conch_remote has its own local atomic_write since it doesn't depend on conch_core
  • tempfile = "3" added as dev-dependency to conch_core for test isolation

an0nn30 added 2 commits March 27, 2026 12:16
Test defaults, serde round-trips, TOML deserialization with complete,
partial, and empty inputs, and optional field handling across all three
config modules. Adds 18 new tests.
Replace direct fs::write() with a tmp-file + rename pattern in
save_user_config, save_persistent_state, remote save_config, and
plugin set_config to prevent corruption from crashes or power loss.
Add atomic_write utility to conch_core::config and a local copy in
conch_remote. Include unit tests for the new utility.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 35a4d58477

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +35 to +37
let tmp = path.with_extension("tmp");
fs::write(&tmp, data)?;
fs::rename(&tmp, path)?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve existing file permissions during atomic writes

This helper now replaces config/state files via write(tmp) + rename, which creates a new inode with default umask-derived permissions instead of preserving the existing file mode. In paths that previously used fs::write (e.g., save_user_config, save_persistent_state, and plugin config saves), a file that was intentionally restricted (such as 0600 or read-only) can be silently widened or overwritten on the next save, which is a security/behavior regression on multi-user systems. Consider copying permissions from the existing target to the temp file (or setting them explicitly) before the rename.

Useful? React with 👍 / 👎.

@an0nn30
Copy link
Copy Markdown
Owner Author

an0nn30 commented Mar 27, 2026

Fixed in 6b929ee — both atomic_write implementations (conch_core and conch_remote) now copy permissions from the existing target file to the temp file before the rename on Unix. Uses std::os::unix::fs::PermissionsExt behind #[cfg(unix)]. If the target file does not yet exist, default umask-derived permissions are used (same as before).

@an0nn30 an0nn30 merged commit 3d428d1 into main Mar 27, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant