use car_policy::permission::PermissionTier;
use car_policy::skill_trust::{gate_skill_deployment, SkillProvenance};
pub fn gate(provenance_json: &str, requested_tier: &str) -> Result<String, String> {
let prov: SkillProvenance = crate::from_json("provenance", provenance_json)?;
let requested = PermissionTier::from_str_opt(requested_tier).ok_or_else(|| {
format!(
"invalid requested_tier '{requested_tier}' \
(expected read_only|sandbox_edit|full_access)"
)
})?;
let decision = gate_skill_deployment(&prov, requested);
crate::to_json(&decision)
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::Value;
#[test]
fn official_full_access_allowed() {
let p = r#"{"signed":true,"signer_trusted":true,"scanned":true,"source":"official"}"#;
let v: Value = serde_json::from_str(&gate(p, "full_access").unwrap()).unwrap();
assert_eq!(v["trust"], "official");
assert_eq!(v["outcome"], "allow");
assert_eq!(v["granted"], "full_access");
}
#[test]
fn vulnerable_is_denied() {
let p = r#"{"signed":true,"signer_trusted":true,"scanned":true,"vulnerabilities":2,"source":"official"}"#;
let v: Value = serde_json::from_str(&gate(p, "read_only").unwrap()).unwrap();
assert_eq!(v["trust"], "untrusted");
assert_eq!(v["outcome"], "deny");
}
#[test]
fn verified_downgrades_full_to_sandbox() {
let p = r#"{"signed":true,"scanned":true,"source":"community"}"#;
let v: Value = serde_json::from_str(&gate(p, "full_access").unwrap()).unwrap();
assert_eq!(v["trust"], "verified");
assert_eq!(v["outcome"], "downgrade");
assert_eq!(v["granted"], "sandbox_edit");
}
#[test]
fn bad_tier_errors() {
assert!(gate("{}", "root").is_err());
}
#[test]
fn bad_json_errors() {
assert!(gate("nope", "read_only").is_err());
}
}