use mrapids::core::api::{run_operation, RunRequest};
use mrapids::core::parser::parse_spec;
use mrapids::core::policy::{
explain_decision, load_policy_from_file, EvaluationContext, PolicyEngine, PolicyExplanation,
PolicySet,
};
use std::path::PathBuf;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("MicroRapid Policy Integration Example");
println!("=====================================\n");
let policy_path = PathBuf::from("examples/.mrapids/policy.yaml");
let policy = load_policy_from_file(&policy_path)?;
println!(
"Loaded policy: {}",
policy
.metadata
.as_ref()
.map(|m| m.name.as_str())
.unwrap_or("Unnamed")
);
let engine = PolicyEngine::new(policy.clone())?;
println!("\n--- Example 1: Allowed Operation ---");
test_operation(
&engine,
"getUser",
"api.public.com/users/123",
Some("default"),
"GET",
&policy,
);
println!("\n--- Example 2: Denied Operation (Wrong Method) ---");
test_operation(
&engine,
"createUser",
"api.public.com/users",
Some("default"),
"POST",
&policy,
);
println!("\n--- Example 3: Denied Operation (No Auth) ---");
test_operation(
&engine,
"getUser",
"api.public.com/users/123",
None,
"GET",
&policy,
);
println!("\n--- Example 4: Blocked Payment Operation ---");
test_operation(
&engine,
"processPayment",
"api.example.com/payment/process",
Some("default"),
"POST",
&policy,
);
println!("\n--- Example 5: GitHub Operation ---");
test_operation(
&engine,
"listRepos",
"api.github.com/users/octocat/repos",
Some("github-readonly"),
"GET",
&policy,
);
Ok(())
}
fn test_operation(
engine: &PolicyEngine,
operation_id: &str,
url: &str,
auth_profile: Option<&str>,
method: &str,
policy: &PolicySet,
) {
let request = RunRequest {
operation_id: operation_id.to_string(),
auth_profile: auth_profile.map(|s| s.to_string()),
parameters: None,
body: None,
spec_path: None,
env: None,
};
let context = EvaluationContext {
method: Some(method.to_string()),
tags: None,
source_ip: None,
timestamp: chrono::Utc::now(),
};
let decision = engine.evaluate(&request, url, &context);
let explanation = explain_decision(&decision, &request, url, &context, Some(policy));
println!("Operation: {} ({})", operation_id, method);
println!("URL: {}", url);
println!("Auth: {}", auth_profile.unwrap_or("none"));
println!("{}", explanation);
if decision.is_allowed() {
println!("→ Would proceed with API call");
} else {
println!("→ API call blocked by policy");
}
}
async fn execute_with_policy(
request: RunRequest,
spec_content: &str,
policy: PolicySet,
) -> Result<String, Box<dyn std::error::Error>> {
let spec = parse_spec(spec_content)?;
let engine = PolicyEngine::new(policy)?;
let operation = spec
.operations
.iter()
.find(|op| op.operation_id == request.operation_id)
.ok_or("Operation not found")?;
let url = format!("{}{}", spec.base_url, operation.path);
let context = EvaluationContext {
method: Some(operation.method.clone()),
tags: None,
source_ip: None,
timestamp: chrono::Utc::now(),
};
let decision = engine.evaluate(&request, &url, &context);
if !decision.is_allowed() {
let explanation = explain_decision(&decision, &request, &url, &context, None);
return Err(format!("Policy denied: {}", explanation.summary).into());
}
let _response = run_operation(request, &spec, None).await?;
Ok("Operation completed successfully".to_string())
}