c0re: also reject apply_commit when flake.lock is stale (#317)

This commit is contained in:
damocles 2026-05-25 23:26:58 +02:00 committed by Mara
commit 008aad0bc5
2 changed files with 161 additions and 5 deletions

View file

@ -633,12 +633,28 @@ async fn submit_apply_commit(
.approvals
.set_fetched_sha(id, &sha)
.map_err(|e| anyhow::anyhow!("persist fetched_sha: {e:#}"))?;
// #317 dedup gate: parse the just-fetched flake.lock and reject if
// the agent declared two inputs that resolve to the same upstream
// (a missing `follows` directive). Runs after `set_fetched_sha` so
// the failed approval row carries the sha that broke — handy when
// the manager needs to inspect the bad commit.
// #317 pre-flight gates: both reject the apply before approval if
// the agent's flake state would inflate meta's lock with duplicates
// or lie about what nix will fetch. Order matters — sync first so
// the dedup pass acts on the lock nix would actually produce.
//
// Runs after `set_fetched_sha` so the failed row carries the sha
// that broke. Both failure paths mark + emit, then bail.
let sha_short = sha[..sha.len().min(12)].to_owned();
if let Err(e) = crate::flake_check::check_lock_in_sync(&applied_dir, &tag, id).await {
let note = format!("{e:#}");
let _ = coord.approvals.mark_failed(id, &note);
coord.emit_approval_resolved(
id,
agent,
"apply_commit",
Some(sha_short.clone()),
"failed",
Some(note),
description.map(str::to_owned),
);
return Err(anyhow::anyhow!("flake lock-sync check: {e:#}"));
}
if let Err(e) = crate::flake_check::check_no_duplicate_inputs(&applied_dir, &tag).await {
let note = format!("{e:#}");
let _ = coord.approvals.mark_failed(id, &note);