Skip to content

[audit] Durable writes not crash-atomic (tmp+rename without fsync / partial commit) #6555

Description

@7jrxt42BxFZo4iAnN4CX

Source: static audit of main@384439634. Candidates are static and not reproduced — confirm each before changing code.
Template: agent-task (agent-ready, docs/ISSUE_TRIAGE.md). Labels: bug, agent-ready.

Goal / Why

State, session, ledger, goal, and job records are written with non-unique temp names, without fsync, or as multi-step commits. A crash, power loss, or a second writer can then leave a truncated file or a half-applied batch that later code reads as valid — losing claims, decisions, or session history, or reviving deleted records. The fix is one atomic durable-write contract per record set: unique temp name, fsync, rename, and batch/transaction semantics for multi-file commits. Non-atomic Windows replacement and mirror-write ordering belong to the same contract.

Confirmed static findings in this class: 8 (reassessed severity noted per line).

Scope / Plan

  1. Re-read each candidate below at the cited file:line on current main; drop anything already fixed or misread.
  2. One owner for atomic durable writes: unique temp file, fsync, rename, and batch/transaction semantics per record set.
  3. Add the smallest regression/gate that would catch a re-introduction (focused test, budget script, or grep guard).

Key files

  • crates/tui/src/tools/subagent/mod.rs
  • crates/tui/src/tui/views/fleet_detail.rs
  • crates/tui/src/runtime_threads.rs
  • crates/tui/src/tui/session_picker.rs
  • crates/cli/src/update.rs
  • web/scripts/sync-latest-release.mjs
  • integrations/bridge-core/src/lib.mjs
  • integrations/weixin-bridge/src/index.mjs

Acceptance criteria

  • Every listed candidate is either fixed with a test, or downgraded with a written reason in the PR.
  • No new instance of this class is introduced (guarded by the test/budget).
  • Existing behavior for unrelated paths is unchanged.

Verification

cargo check -p codewhale-tui -p codewhale-cli
cargo test  -p codewhale-tui --lib
cargo clippy --workspace --all-targets --locked -- -D warnings
( cd web && npm run check )
( cd integrations/bridge-core && npm run test )

Out of scope

  • Findings that belong to another systemic class or to the localized backlog.
  • Re-architecture beyond the listed sites.

Related existing work (do not duplicate)

#4634/#4635 (pin artifact/journal identity), #6432 (exclusive rename publication), #5491 (persist before execution), #6354

Candidate findings (8)

  • D02-01 · D02 — agent/subagent runtime · crates/tui/src/tools/subagent/mod.rs:3423 — shared read lock and process-local sequence allow overlapping writers; the last rename wipes claims/decisions/tasks.
    audit severity: critical; reassessed: critical
  • U09-01 · U09 — Dashboards, Fleet/settings/status/help · crates/tui/src/tui/views/fleet_detail.rs:641 — ordinary Save/rename overwrites an external newer Fleet source without source-version check.
    audit severity: high; reassessed: major
  • D02-10 · D02 — agent/subagent runtime · crates/tui/src/tools/subagent/mod.rs:8030 — terminal acknowledgement published before durable commit; crash leaves child Running/Interrupted.
    audit severity: major; reassessed: major
  • T08-06 · T08 — Runtime threads, tasks, automation, goals · crates/tui/src/runtime_threads.rs:8357 — partial seed crash leaves turns/items without thread publication; startup restores partial state.
    audit severity: major; reassessed: major
  • U08-09 · U08 — Setup, approvals, hotbar, session/config · crates/tui/src/tui/session_picker.rs:97 — full session store sync load; errors become empty, preview cache stale after rename.
    audit severity: major; reassessed: major
  • R02-05 · R02 — CLI, build-support, release/update · crates/cli/src/update.rs:1904 — Windows replacement non-atomic, rollback errors ignored; crash leaves target missing.
    audit severity: major; reassessed: major
  • W02-09 · W02 — Website API, Cloudflare/KV, generators · web/scripts/sync-latest-release.mjs:41 — --check false-green on outage; target write before mirror validation creates partial state.
    audit severity: major; reassessed: major
  • X01-07 · X01 — npm, SDK, VS Code, bridges, verifier · integrations/bridge-core/src/lib.mjs:156, integrations/weixin-bridge/src/index.mjs:778 — cursor/message committed before side effect; fixed .tmp no fsync, crash can lose prompt.
    audit severity: high; reassessed: high

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

    bugSomething isn't workingneeds-triageNew external report awaiting maintainer triage; repro, logs and version output help

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions