pub mod never_grant;
pub mod socket;
pub mod types;
pub use never_grant::{NeverGrantChecker, NeverGrantResult};
pub use socket::SupervisorSocket;
pub use types::{
ApprovalDecision, AuditEntry, CapabilityRequest, SupervisorMessage, SupervisorResponse,
};
use crate::error::Result;
pub trait ApprovalBackend: Send + Sync {
fn request_capability(&self, request: &CapabilityRequest) -> Result<ApprovalDecision>;
fn backend_name(&self) -> &str;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::capability::AccessMode;
struct TestDenyBackend;
impl ApprovalBackend for TestDenyBackend {
fn request_capability(&self, _request: &CapabilityRequest) -> Result<ApprovalDecision> {
Ok(ApprovalDecision::Denied {
reason: "test deny".to_string(),
})
}
fn backend_name(&self) -> &str {
"test-deny"
}
}
struct TestGrantBackend;
impl ApprovalBackend for TestGrantBackend {
fn request_capability(&self, _request: &CapabilityRequest) -> Result<ApprovalDecision> {
Ok(ApprovalDecision::Granted)
}
fn backend_name(&self) -> &str {
"test-grant"
}
}
fn make_request() -> CapabilityRequest {
CapabilityRequest {
request_id: "test-001".to_string(),
path: "/tmp/test".into(),
access: AccessMode::Read,
reason: Some("unit test".to_string()),
child_pid: 1234,
session_id: "sess-001".to_string(),
}
}
#[test]
fn test_deny_backend() {
let backend = TestDenyBackend;
let request = make_request();
let decision = backend.request_capability(&request).expect("decision");
assert!(decision.is_denied());
assert_eq!(backend.backend_name(), "test-deny");
}
#[test]
fn test_grant_backend() {
let backend = TestGrantBackend;
let request = make_request();
let decision = backend.request_capability(&request).expect("decision");
assert!(decision.is_granted());
assert_eq!(backend.backend_name(), "test-grant");
}
#[test]
fn test_approval_decision_methods() {
let granted = ApprovalDecision::Granted;
assert!(granted.is_granted());
assert!(!granted.is_denied());
let denied = ApprovalDecision::Denied {
reason: "no".to_string(),
};
assert!(!denied.is_granted());
assert!(denied.is_denied());
let timeout = ApprovalDecision::Timeout;
assert!(!timeout.is_granted());
assert!(!timeout.is_denied());
}
}