What to build
Staged overlay temporary files are leaked on every activation-transaction error. The temp file is not cleaned up when the activation fails, leaving orphaned data that accumulates over time.
Acceptance criteria
- Ensure temp files are cleaned up on activation transaction error. 2. Add test covering activation failure path. 3. Verify no temp files remain after failed activation.
Blocked by
None (parallel work, no blocking)
Original report
Found by an adversarial correctness/security review of #130 (ship-recurring-gmail-draft-proof). Low severity, no authority impact.
crates/openspine-kernel/src/pipeline/artifact_activation.rs:196-220 writes and fsyncs tmp_path, then:
let committed = state.store.commit_artifact_activation(...)?;
if !committed { let _ = std::fs::remove_file(&tmp_path); return Ok(()); }
The ? skips cleanup on every Err, and commit_artifact_activation never returns Ok(false) (it ends tx.commit()?; Ok(true) at crates/openspine-kernel/src/store/activation.rs:441-442), so the only cleanup branch is dead while the live failure path leaks. Refusals on this path are routine: "evaluated approval has no standing-rule manifest" (activation.rs:203-206), the stale-verdict refusal (:231-232), and the review-not-pending refusal (:378-381). Repeated refusals accumulate *.tmp.<ulid> files in the overlay directory without bound.
No authority impact: load_yaml_dir filters on ext == "yaml" || ext == "yml" (artifact_loader.rs:313-317), so leaked files are never loaded.
Suggested fix
Match on the commit result and remove tmp_path on Err as well as on the (dead) !committed branch.
What to build
Staged overlay temporary files are leaked on every activation-transaction error. The temp file is not cleaned up when the activation fails, leaving orphaned data that accumulates over time.
Acceptance criteria
Blocked by
None (parallel work, no blocking)
Original report
Found by an adversarial correctness/security review of #130 (
ship-recurring-gmail-draft-proof). Low severity, no authority impact.crates/openspine-kernel/src/pipeline/artifact_activation.rs:196-220writes andfsyncstmp_path, then:The
?skips cleanup on everyErr, andcommit_artifact_activationnever returnsOk(false)(it endstx.commit()?; Ok(true)atcrates/openspine-kernel/src/store/activation.rs:441-442), so the only cleanup branch is dead while the live failure path leaks. Refusals on this path are routine:"evaluated approval has no standing-rule manifest"(activation.rs:203-206), the stale-verdict refusal (:231-232), and the review-not-pending refusal (:378-381). Repeated refusals accumulate*.tmp.<ulid>files in the overlay directory without bound.No authority impact:
load_yaml_dirfilters onext == "yaml" || ext == "yml"(artifact_loader.rs:313-317), so leaked files are never loaded.Suggested fix
Match on the commit result and remove
tmp_pathonErras well as on the (dead)!committedbranch.