Skip to content

history: a privacy wipe can skip the files that hold user text #321

Description

@send

remove_recovery_artifacts (engine/crates/lex-core/src/user_history/recovery.rs)
iterates a fixed array of paths and does return Err(e) on the first
non-NotFound failure — before reaching the persist::quarantined_files
loop that removes the .corrupt-* files.

clear_impl calls this as part of the privacy wipe. The .corrupt-* files hold
a full serialized history, i.e. the user's typed readings and surfaces. So a
failure removing an earlier member — a stubborn .v1.bak under EACCES, say —
leaves those on disk untouched. The error is surfaced (clear defers and returns
it), so it is not silent, but the wipe is incomplete in a way it need not be.

Fix

Make the function deferred-error: attempt every member, remember the first
error, return it at the end — matching the discipline clear_impl itself
already uses ten lines below. Ordering matters too: the members that hold user
text should not sit behind ones that do not.

Add a test that a stubborn earlier member does not prevent the .corrupt-*
sweep.

Related: write_atomic does not clean up its own tmp

Same family, likely the same fix session. persist::write_atomic leaves
<path>.tmp behind whenever write_all / sync_all / rename fails after
File::create, and nothing sweeps it at startup. A real instance is sitting in
my own profile right now — user_history.lxud.wal.tmp, 6.5 KB, dated 2026-04-11
— which is a WAL fragment, i.e. it does contain input text, and no wipe or
recovery path removes it. Either write_atomic should unlink its tmp on the
failure paths, or the startup sweep should cover <member>.tmp uniformly
instead of the two checkpoint-specific names it lists today.

Found during the /simplify and /lexime-review passes on #320 (#312) and
deliberately not bundled there — an unrelated behavior change in a persistence
PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions