use std::process::Command;
#[test]
fn assay_run_writes_render_safe_run_json_to_disk() {
let secret = format!("ghp_{}", "A".repeat(36));
let email = "alice@example.com";
let prompt = format!("leak {secret} {email}");
let dir = tempfile::tempdir().unwrap();
let cfg = format!(
"version: 1\nsuite: rs_witness\nmodel: trace\nsettings:\n cache: false\ntests:\n \
- id: leak_row\n input:\n prompt: {p}\n expected:\n type: must_contain\n \
must_contain: [\"ABSENT_TOKEN_NEVER_PRESENT\"]\n",
p = serde_json::to_string(&prompt).unwrap()
);
std::fs::write(dir.path().join("eval.yaml"), cfg).unwrap();
let entry = serde_json::json!({
"schema_version": 1, "type": "assay.trace", "request_id": "rs_0",
"prompt": prompt, "response": "benign assistant reply, no secret",
"model": "trace", "provider": "trace", "meta": {}
});
std::fs::write(dir.path().join("trace.jsonl"), format!("{entry}\n")).unwrap();
let status = Command::new(env!("CARGO_BIN_EXE_assay"))
.current_dir(dir.path())
.args([
"run",
"--config",
"eval.yaml",
"--trace-file",
"trace.jsonl",
"--db",
":memory:",
])
.output()
.expect("failed to run assay binary");
let _ = status;
let run_json = std::fs::read_to_string(dir.path().join("run.json"))
.expect("assay run did not write run.json");
let _: serde_json::Value = serde_json::from_str(&run_json).unwrap();
assert!(
!run_json.contains(&secret),
"real `assay run` leaked the secret to run.json on disk"
);
assert!(
!run_json.contains("ghp_"),
"real `assay run` leaked a raw token prefix to run.json on disk"
);
assert!(
!run_json.contains(email),
"real `assay run` leaked PII to run.json on disk"
);
assert!(
run_json.contains("<redacted:"),
"run.json shows no redaction marker (field rendered raw or silently omitted)"
);
assert!(
run_json.contains("leak "),
"planted prompt did not reach run.json details"
);
}