use cleanlib_client::{transport, types};
use wiremock::matchers::{body_partial_json, method, path_regex};
use wiremock::{Mock, MockServer, ResponseTemplate};
const VERBS: &[&str] = &["verdict", "scan", "audit", "policy_preview"];
const WRAPPERS: &[&str] = &["npm", "pip", "cargo", "go"];
const ECOSYSTEMS: &[(&str, &str)] = &[
("npm", "npm"),
("pip", "pypi"),
("cargo", "crates"),
("go", "go"),
];
const STATUSES: &[&str] = &[
"ALLOWED_NO_FINDINGS",
"RISK_ACCEPTANCE_REQUIRED",
"VECTOR_VERDICT",
"INSUFFICIENT_DATA",
];
fn status_for_policy(status: &str) -> String {
match status {
"ALLOWED_NO_FINDINGS" => "ALLOW".to_string(),
"RISK_ACCEPTANCE_REQUIRED" => "WARN".to_string(),
"VECTOR_VERDICT" => "DENY".to_string(),
"INSUFFICIENT_DATA" => "INSUFFICIENT_DATA".to_string(),
other => other.to_string(),
}
}
fn fixture_pkg_for_wrapper(wrapper: &str) -> (&'static str, &'static str) {
match wrapper {
"npm" => ("cors", "2.8.5"),
"pip" => ("requests", "2.32.5"),
"cargo" => ("serde", "1.0.200"),
"go" => ("github.com/sirupsen/logrus", "v1.9.0"),
_ => unreachable!(),
}
}
#[tokio::test]
async fn matrix_64_cases() {
let mut failed: Vec<(String, String, String, String)> = Vec::new();
for verb in VERBS {
for (wrapper, ecosystem) in ECOSYSTEMS {
for status in STATUSES {
let case_id = format!("{}/{}/{}", verb, wrapper, status);
if let Err(msg) = run_case(verb, wrapper, ecosystem, status).await {
failed.push((
verb.to_string(),
wrapper.to_string(),
status.to_string(),
msg,
));
eprintln!("CASE FAIL [{}]: {}", case_id, failed.last().unwrap().3);
} else {
eprintln!("CASE PASS [{}]", case_id);
}
}
}
}
let total = VERBS.len() * WRAPPERS.len() * STATUSES.len();
assert_eq!(total, 64, "matrix dimensions changed; update assertion");
if !failed.is_empty() {
for (v, w, s, m) in &failed {
eprintln!("FAIL ({}, {}, {}): {}", v, w, s, m);
}
panic!(
"{} of {} integration cases failed",
failed.len(),
total
);
}
}
async fn run_case(
verb: &str,
wrapper: &str,
ecosystem: &str,
status: &str,
) -> Result<(), String> {
let server = MockServer::start().await;
let (pkg, version) = fixture_pkg_for_wrapper(wrapper);
match verb {
"verdict" => {
let resp = ResponseTemplate::new(200).set_body_json(serde_json::json!({
"verdict_id": format!("01J-{}-{}", wrapper, status),
"verdict": status,
"source": status,
"confidence": 0.9,
"composite_score": match status {
"VECTOR_VERDICT" => 90,
"RISK_ACCEPTANCE_REQUIRED" => 60,
_ => 5,
},
"reasoning": format!("synthetic {} case", status),
"computed_at": "2026-05-28T00:00:00Z"
}));
Mock::given(method("GET"))
.and(path_regex(r"^/v1/customer/verdicts/"))
.respond_with(resp)
.mount(&server)
.await;
let client = transport::Client::new(&server.uri(), Some("test-bearer".into()))
.map_err(|e| e.to_string())?;
let v = client
.fetch_verdict(ecosystem, pkg, version)
.await
.map_err(|e| e.to_string())?;
if v.verdict != status {
return Err(format!("expected verdict={} got {}", status, v.verdict));
}
Ok(())
}
"scan" => {
let resp = ResponseTemplate::new(200).set_body_json(serde_json::json!({
"results": [{
"ecosystem": ecosystem,
"package": pkg,
"version": version,
"verdict": {
"verdict_id": format!("01J-scan-{}-{}", wrapper, status),
"verdict": status,
"source": status,
"confidence": 0.9,
"composite_score": 5,
"reasoning": format!("synthetic scan {} case", status)
}
}]
}));
Mock::given(method("POST"))
.and(path_regex(r"^/v1/scan"))
.and(body_partial_json(serde_json::json!({
"packages": [{ "ecosystem": ecosystem, "package": pkg, "version": version }]
})))
.respond_with(resp)
.mount(&server)
.await;
let client = transport::Client::new(&server.uri(), Some("test-bearer".into()))
.map_err(|e| e.to_string())?;
let req = types::ScanRequest {
packages: vec![types::PackageRef {
ecosystem: ecosystem.to_string(),
name: pkg.to_string(),
version: version.to_string(),
}],
};
let r = client.scan(&req).await.map_err(|e| e.to_string())?;
if r.results.len() != 1 {
return Err(format!("expected 1 result; got {}", r.results.len()));
}
match &r.results[0].verdict {
Some(v) if v.verdict == status => Ok(()),
Some(v) => Err(format!("expected verdict={} got {}", status, v.verdict)),
None => Err("expected a verdict on the scan result; got none".to_string()),
}
}
"policy_preview" => {
let decision = status_for_policy(status);
let resp = ResponseTemplate::new(200).set_body_json(serde_json::json!({
"decisions": [{
"ecosystem": ecosystem,
"package": pkg,
"version": version,
"decision": decision.clone(),
"reason": format!("{} reason", decision)
}]
}));
Mock::given(method("POST"))
.and(path_regex(r"^/v1/policy/preview"))
.respond_with(resp)
.mount(&server)
.await;
let client = transport::Client::new(&server.uri(), Some("test-bearer".into()))
.map_err(|e| e.to_string())?;
let req = types::PolicyPreviewRequest {
packages: vec![types::PackageRef {
ecosystem: ecosystem.to_string(),
name: pkg.to_string(),
version: version.to_string(),
}],
policy: None,
};
let r = client.policy_preview(&req).await.map_err(|e| e.to_string())?;
if r.decisions.len() != 1 {
return Err(format!("expected 1 decision; got {}", r.decisions.len()));
}
if r.decisions[0].decision != decision {
return Err(format!(
"expected decision={} got {}",
decision, r.decisions[0].decision
));
}
Ok(())
}
"audit" => {
let decision = status_for_policy(status);
let per_route_key = format!("/v1/customer/verdicts/{}", ecosystem);
let mut per_route = serde_json::Map::new();
per_route.insert(per_route_key, serde_json::json!(1));
let resp = ResponseTemplate::new(200).set_body_json(serde_json::json!({
"window": {"since": null, "until": null},
"records": [{
"request_id": format!("req-{}-{}", wrapper, status),
"correlation_id": format!("corr-{}-{}", wrapper, status),
"ecosystem": ecosystem,
"package_name": pkg,
"package_version": version,
"variant": "default",
"policy_decision": decision,
"verdict_id": "01936b8f-3c4a-7a12-9c00-000000000000",
"verdict_source": "ALLOWED_NO_FINDINGS",
"policy_rule_id_matched": "",
"risk_acceptance_status": "NONE",
"reasoning": "audit synthetic",
"gcs_hit": true,
"request_at": "2026-05-28T00:00:00Z",
"verdict_at": "2026-05-28T00:00:01Z",
"response_at": "2026-05-28T00:00:02Z",
"app_version": "1.0.0"
}],
"record_count": 1,
"per_route": per_route,
"backend_status": "wired"
}));
Mock::given(method("GET"))
.and(path_regex(r"^/v1/audit"))
.respond_with(resp)
.mount(&server)
.await;
let client = transport::Client::new(&server.uri(), Some("test-bearer".into()))
.map_err(|e| e.to_string())?;
let r = client
.audit(None, Some(&decision), Some(ecosystem))
.await
.map_err(|e| e.to_string())?;
if r.records.len() != 1 {
return Err(format!("expected 1 record; got {}", r.records.len()));
}
if r.records[0].policy_decision != decision {
return Err(format!(
"expected record policy_decision={} got {}",
decision, r.records[0].policy_decision
));
}
Ok(())
}
other => Err(format!("unknown verb {}", other)),
}
}