Skip to content

Settings persistence: atomic store (fixes power-loss corruption), clamps, and safe reads - #70

Merged
GalaxyRuler merged 8 commits into
mainfrom
codex/reliability-hardening-phase5
Jul 12, 2026
Merged

Settings persistence: atomic store (fixes power-loss corruption), clamps, and safe reads#70
GalaxyRuler merged 8 commits into
mainfrom
codex/reliability-hardening-phase5

Conversation

@GalaxyRuler

Copy link
Copy Markdown
Owner

Before Submitting This PR

Please confirm you have done the following:

  • I have searched existing issues and pull requests (including closed ones) to ensure this isn't a duplicate
  • I have read CONTRIBUTING.md

Human Written Description

The settings file kept getting corrupted — a couple of times after a hard shutdown the app came up with everything reset, because the store plugin writes settings with a plain truncate-and-overwrite and a power loss mid-write leaves a half-written (or zero-byte) file. That's the same class of bug people have reported upstream. I also wanted the privacy-sensitive toggles (history off, recordings off) to actually be on disk the instant you flip them, not whenever a debounce timer happens to fire. So this makes settings writes atomic and durable, and tightens up a few settings that could be set to nonsense values.

Related Issues/Discussions

Bug-fix work (top priority per CONTRIBUTING). Fixes settings-file corruption on power loss (same root cause as tauri-apps/plugins-workspace#3085) and hardens the settings/persistence layer.

Fixes #
Discussion:

Testing

TDD throughout; full Rust library suite passes 688/688. Key coverage:

  • Atomic store: a behavioral test builds a real store through the patched plugin, saves, and asserts exactly one file remains (no temp droppings) with valid JSON — i.e. the atomic temp-file+fsync+rename path actually runs. A lockfile test asserts the store dependency is pinned to the atomic fork, not crates.io.
  • Clamps: each numeric setting (recording-buffer, feedback volume, correction threshold, paste delay) is clamped at both the setter and the read site — including NaN and out-of-range inputs.
  • Safe reads: settings reads no longer panic on a missing binding and no longer write during a read; migration writes happen once under the write lock.
  • cargo deny (advisories/bans/licenses/sources) passes with the fork source allow-listed.

Screenshots/Videos (if applicable)

N/A (backend/persistence changes).

AI Assistance

  • AI was used (please describe below)

If AI was used:

  • Tools used: OpenAI Codex (implementation, test-first) and Claude (planning, per-change code review, dependency-policy gate fix).
  • How extensively: implemented against a reviewed plan; every change code-reviewed before inclusion.

What's in this PR

  • Atomic settings persistence: tauri-plugin-store is pinned to a small fork whose save() writes to a same-directory temp file, fsyncs, then atomically renames — so a crash or power loss can never leave a corrupt/zero-byte settings file. Privacy-critical writes (history/recordings/credentials, reset paths) now flush through this atomic path explicitly instead of relying on the debounced autosave.
  • Numeric clamps: recording-buffer (bounded so a mistyped value can't stall the stop path), feedback volume, correction threshold, and paste delay are clamped at setter + read site.
  • Settings correctness: read-only settings reads (no writes mid-read), safe binding fallback instead of a panic, the "capture nearby text" preference is now honored, and shortcut-registration failures surface to the UI instead of log-only.
  • Transcription load safety: poison-tolerant locks, serialized model loads, explicit Whisper load parameters instead of process-global state, and a distinct "already transcribing" error.

Stacks on the reliability train (#69, already merged).

🤖 Generated with Claude Code

GalaxyRuler and others added 6 commits July 12, 2026 01:01
The atomic tauri-plugin-store fork (pinned in [patch.crates-io]) needs its git
source in deny.toml's sources.allow-git, same as the existing rodio/tauri/vad-rs
forks. Closes the check:rust-dependency-policy gate for Phase 5.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

GalaxyRuler and others added 2 commits July 12, 2026 05:39
…ivacy-safe fallback

Phase 5's read-only get_settings path flagged New (clean-install) reads with a
'deferred to startup' persistence_error, and settings_for_non_command_read
fail-closed on it -> history/recordings OFF on every fresh install. Early
get_settings reads run before the startup loader persists, so the packaged
first-launch smoke (a pre-existing shipped contract) saw retention disabled.

A clean first-run default is safe to report on a read: defaults are history/
recordings ON and the startup loader persists them moments later. Fail-closed
is retained for Recovered (unparseable user data, unknown intent) and for a
REAL persist failure (load_settings_from_store path; those tests unchanged).

Reproduced + verified with a clean-profile run of scripts/native-smoke; added a
regression test asserting a clean-store read reports default retention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…binding

The two registration-failure tests hardcoded ctrl+space / ctrl+shift+space and
failed on macOS where the default binding is Cmd-based. Derive the expected
detail from the binding under test so the assertion is platform-correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@GalaxyRuler
GalaxyRuler merged commit 3e9fb24 into main Jul 12, 2026
15 checks passed
@GalaxyRuler
GalaxyRuler deleted the codex/reliability-hardening-phase5 branch July 12, 2026 03:41
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