test: red for register's stray-store creation outside a project (refs #305)

register_process/register_campaign call env.registry() without the
no-project guard their show/runs siblings carry, so Env::runs_root()'s
relative fallback silently creates ./runs/ in an innocent cwd and
registers the document there (exit 0). The E2E test pins both verbs and
both halves of the wanted refusal: exit 1 naming the missing Aura.toml,
and no store directory created as a side effect.
This commit is contained in:
2026-07-21 14:27:04 +02:00
parent da37f596f2
commit 27ace153f2
+36
View File
@@ -596,6 +596,42 @@ fn campaign_validate_outside_project_skips_referential_tier() {
assert!(out.contains("referential checks skipped (no Aura.toml found up from "));
}
/// #305: `register` outside a project (no Aura.toml up from the cwd) refuses
/// up front — exit 1, prose naming the invoked verb and the missing Aura.toml
/// (the honest-degradation guard family `show`, `campaign runs`, and the
/// dissolved run verbs already share) — and leaves NO store. Today the missing
/// `env.provenance()` guard lets `Env::registry()`'s relative `runs/` fallback
/// silently materialise `./runs/` in the innocent cwd and register the
/// document into a store no project owns, exit 0.
#[test]
fn register_outside_a_project_refuses_and_leaves_no_store() {
for (verb, file, doc) in [
("process", "p.process.json", PROCESS_DOC),
("campaign", "c.campaign.json", CAMPAIGN_DOC),
] {
let dir = temp_cwd(&format!("{verb}-register-outside-project"));
write_doc(&dir, file, doc);
let (out, code) = run_code_in(&dir, &[verb, "register", file]);
assert_eq!(
code,
Some(1),
"{verb} register outside a project must refuse; stdout/stderr: {out}"
);
assert!(
out.contains(&format!("{verb} register needs a project")),
"{verb} register's refusal must name the invoked verb: {out}"
);
assert!(
out.contains("no Aura.toml found up from"),
"{verb} register's refusal must name the missing Aura.toml: {out}"
);
assert!(
!dir.join("runs").exists(),
"{verb} register refused outside a project must leave no ./runs/ store"
);
}
}
#[test]
fn campaign_validate_refuses_empty_axis_prose_exit_1() {
let dir = temp_cwd("campaign-validate-empty-axis");