#[cfg(kani)]
use crate::attributes::{DeviceType, EnvironmentAttributes, ResourceAttributes, UserAttributes};
#[cfg(kani)]
use crate::evaluator;
#[cfg(kani)]
use crate::policy::{AbacPolicy, Condition, Effect, Rule};
#[cfg(kani)]
use chrono::{TimeZone, Utc};
#[cfg(kani)]
use kimberlite_types::DataClass;
#[cfg(kani)]
#[kani::proof]
#[kani::unwind(10)]
fn verify_policy_evaluation_determinism() {
let policy = AbacPolicy::hipaa_policy();
let user = UserAttributes::new("doctor", "medicine", 2);
let resource = ResourceAttributes::new(DataClass::PHI, 1, "patient_records");
let ts = Utc.with_ymd_and_hms(2025, 1, 8, 10, 0, 0).unwrap();
let env = EnvironmentAttributes::from_timestamp(ts, "US");
let decision1 = evaluator::evaluate(&policy, &user, &resource, &env);
let decision2 = evaluator::evaluate(&policy, &user, &resource, &env);
assert_eq!(decision1.effect, decision2.effect);
assert_eq!(decision1.matched_rule, decision2.matched_rule);
}
#[cfg(kani)]
#[kani::proof]
#[kani::unwind(10)]
fn verify_priority_conflict_resolution() {
let policy = AbacPolicy::new(Effect::Allow)
.with_rule(Rule {
name: "low-allow".to_string(),
effect: Effect::Allow,
conditions: vec![Condition::ClearanceLevelAtLeast(0)], priority: 1,
})
.unwrap()
.with_rule(Rule {
name: "high-deny".to_string(),
effect: Effect::Deny,
conditions: vec![Condition::ClearanceLevelAtLeast(0)], priority: 100,
})
.unwrap();
let user = UserAttributes::new("user", "engineering", 1);
let resource = ResourceAttributes::new(DataClass::Public, 1, "test");
let ts = Utc.with_ymd_and_hms(2025, 1, 8, 10, 0, 0).unwrap();
let env = EnvironmentAttributes::from_timestamp(ts, "US");
let decision = evaluator::evaluate(&policy, &user, &resource, &env);
assert_eq!(decision.effect, Effect::Deny);
assert_eq!(decision.matched_rule, Some("high-deny".to_string()));
}
#[cfg(kani)]
#[kani::proof]
#[kani::unwind(10)]
fn verify_default_deny_safety() {
let policy = AbacPolicy::new(Effect::Deny)
.with_rule(Rule {
name: "admin-only".to_string(),
effect: Effect::Allow,
conditions: vec![Condition::RoleEquals("admin".to_string())],
priority: 10,
})
.unwrap();
let user = UserAttributes::new("user", "engineering", 1); let resource = ResourceAttributes::new(DataClass::Public, 1, "test");
let ts = Utc.with_ymd_and_hms(2025, 1, 8, 10, 0, 0).unwrap();
let env = EnvironmentAttributes::from_timestamp(ts, "US");
let decision = evaluator::evaluate(&policy, &user, &resource, &env);
assert_eq!(decision.effect, Effect::Deny);
assert!(decision.matched_rule.is_none());
}
#[cfg(kani)]
#[kani::proof]
#[kani::unwind(10)]
fn verify_fedramp_location_enforcement() {
let policy = AbacPolicy::fedramp_policy();
let user = UserAttributes::new("analyst", "engineering", 3);
let resource = ResourceAttributes::new(DataClass::Confidential, 1, "metrics");
let ts = Utc.with_ymd_and_hms(2025, 1, 8, 10, 0, 0).unwrap();
let env = EnvironmentAttributes::from_timestamp(ts, "DE");
let decision = evaluator::evaluate(&policy, &user, &resource, &env);
assert_eq!(decision.effect, Effect::Deny);
assert_eq!(decision.matched_rule, Some("fedramp-us-only".to_string()));
}
#[cfg(kani)]
#[kani::proof]
#[kani::unwind(10)]
fn verify_abac_tenant_isolation() {
let a_raw: u64 = kani::any();
let b_raw: u64 = kani::any();
kani::assume(a_raw != b_raw);
let policy = AbacPolicy::new(Effect::Deny)
.with_rule(Rule {
name: "tenant-a-only".to_string(),
effect: Effect::Allow,
conditions: vec![
Condition::RoleEquals("analyst".to_string()),
Condition::TenantEquals(a_raw),
],
priority: 100,
})
.unwrap();
let resource = ResourceAttributes::new(DataClass::Public, a_raw, "shared");
let ts = Utc.with_ymd_and_hms(2025, 1, 8, 10, 0, 0).unwrap();
let env = EnvironmentAttributes::from_timestamp(ts, "US");
let user_a = UserAttributes::new("analyst", "engineering", 3).with_tenant(a_raw);
let decision_a = evaluator::evaluate(&policy, &user_a, &resource, &env);
assert_eq!(decision_a.effect, Effect::Allow);
assert_eq!(decision_a.matched_rule, Some("tenant-a-only".to_string()));
let user_b = UserAttributes::new("analyst", "engineering", 3).with_tenant(b_raw);
let decision_b = evaluator::evaluate(&policy, &user_b, &resource, &env);
assert_eq!(decision_b.effect, Effect::Deny);
}
#[cfg(test)]
mod tests {
#[test]
fn test_proof_count() {
let proof_count = 5;
assert_eq!(proof_count, 5, "Expected 5 Kani proofs for ABAC");
}
}