Refuse restaging over a dest-gone image leave-temp (SBS-1073) - #300
Refuse restaging over a dest-gone image leave-temp (SBS-1073)#300btsouth wants to merge 2 commits into
Conversation
Same-uuid stage_full_image_file used fs::write on a fixed {uuid}.cubby.tmp,
which truncates an SBS-1030 leave-temp that may be the only remaining original.
Match backup: create_new, conflict on collision, leave those bytes untouched.
Co-authored-by: Tyler <tyler@southboundsoftware.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying cubby-clipboard with
|
| Latest commit: |
a64f6df
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://8498bd82.cubby-clipboard.pages.dev |
| Branch Preview URL: | https://cursor-sbs-1073-restage-leav.cubby-clipboard.pages.dev |
unwrap_err and {:?} require Debug. StagedImageFile does not implement it;
match the existing is_err / match-Err pattern so the new tests compile.
Co-authored-by: Tyler <tyler@southboundsoftware.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_e8b48b4a-d3b5-4f04-a447-6ff2a9a38185) |
|
This is marked ready, but the body still says "Do not merge." I am leaving it blocked until that instruction is explicitly cleared. |
|
Manual review is complete. The exclusive-create path preserves the existing temp, cleans a newly created partial write, and the integration coverage pins both live and expired recapture. No code findings. I am still honoring the "Do not merge" line; remove it when ready. |
What changed
Fixes SBS-1073: same-uuid
stage_full_image_fileusedfs::writeon the fixed{uuid}.cubby.tmpname. After an SBS-1030 dest-gone mid-replace, that temp is the only remaining original (expired revival retries Capture).fs::writetruncates on open, so the retry destroyed those bytes before a durable new copy existed.Backup already refuses this class of hazard with
create_new. Image staging uses a fixed temp name (dest-gone sweep computes dest asname.strip_suffix(".tmp")→{uuid}.cubby), so unique names / rename-aside would break SBS-1030 promotion. The matching safe pattern iscreate_new+ conflict failure: restaging leaves the leave-temp byte-identical and fails the recapture. Next launch still promotes the leftover viasweep_stale_image_temps.write_staged_image_templives inimage_stage.rssorustc --test src-tauri/src/image_stage.rscan pin the I/O contract on Linux.stage_full_image_fileand the expired-revive recapture path call it.Sibling overwrite sweep
Production write-then-replace temps:
image_persist::stage_full_image_file{uuid}.cubby.tmpfs::writecreate_newbackup::write_backup_temp.{pid}.{uuid}.tmpcreate_newdatabaserolling backup*.bak.{pid}.{uuid}.tmpfs::copyto a unique namecryptostorage keystorage.key.{pid}.{uuid}.tmpfs::writeto a unique namesettings_manager::savesettings.json.tmpfs::writeNo other writer targets
{uuid}.cubby.tmp.Verification
windows-latesttestjob (same flags as.github/workflows/ci.yml).Fail-without-fix
write_staged_image_temptemporarily implemented asfs::write.rustc --test src-tauri/src/image_stage.rs:The dest-gone case panicked at
restaging must refuse to open the existing leave-temp—fs::writereturnedOkand had already truncated the leave-temp.After
create_new(Linux,rustc --test)Crate-level tests in
image_persist.rsgo throughstage_full_image_file(encrypted bytes) andapply_existing_image_recaptureon an expired revive so a revert tofs::writethere still fails.Related dest-gone contracts still pass:
CI gate (GitHub
windows-latest, run 32670607424, commita64f6df)Same commands as
.github/workflows/ci.yml:All 12 checks on the PR head passed (
test,shipped-windows, fourCheck <arch> <features>legs, CodeQL).Do not merge.
Note
Use exclusive-create for staging temp files in
stage_full_image_fileimage_stage::write_staged_image_temp, which opens the staging temp path withOpenOptions::create_new(true)and refuses to overwrite an existing file, returning a conflict error with text "refusing to overwrite existing staging file"stage_full_image_filenow calls this helper instead ofstd::fs::write, so restaging over a dest-gone leave-temp fails instead of truncating itMacroscope summarized a64f6df.