use crate::core::config::Config;
use crate::core::policy::{PolicyAction, PolicyEngine, PolicyRule};
use crate::core::{agentlog_path, ensure_initialized};
use anyhow::Result;
use colored::Colorize;
pub async fn list() -> Result<()> {
let project_root = ensure_initialized()?;
let config_path = agentlog_path(&project_root).join("config.json");
let config = if config_path.exists() {
Config::load(&config_path)?
} else {
Config::default()
};
println!("{}", "AgentLog Policy Rules".bold().underline());
println!();
println!(
"Policy enforcement: {}",
if config.policy.enabled {
"ENABLED".green()
} else {
"DISABLED".yellow()
}
);
println!();
if config.policy.rules.is_empty() {
println!("{}", "No policy rules configured.".dimmed());
} else {
for rule in &config.policy.rules {
let status = if rule.enabled {
"✓".green()
} else {
"✗".dimmed()
};
let action = match rule.action {
PolicyAction::Block => "BLOCK".red(),
PolicyAction::Warn => "WARN".yellow(),
PolicyAction::RequireConfirmation => "CONFIRM".cyan(),
PolicyAction::Allow => "ALLOW".green(),
};
println!("{} {}", status, rule.name.bold());
println!(" Pattern: {}", rule.pattern.cyan());
println!(" Action: {}", action);
println!(" Description: {}", rule.description);
println!();
}
}
Ok(())
}
pub async fn add(
name: String,
pattern: String,
action: String,
description: Option<String>,
) -> Result<()> {
let project_root = ensure_initialized()?;
let config_path = agentlog_path(&project_root).join("config.json");
let mut config = if config_path.exists() {
Config::load(&config_path)?
} else {
Config::default()
};
let action = parse_action(&action)?;
let rule = PolicyRule {
name: name.clone(),
description: description.unwrap_or_else(|| format!("Custom rule for {}", pattern)),
pattern,
regex: None,
action,
enabled: true,
};
if let Some(existing) = config.policy.rules.iter_mut().find(|r| r.name == name) {
*existing = rule;
println!("{}", format!("Updated rule: {}", name).yellow());
} else {
config.policy.rules.push(rule);
println!("{}", format!("Added rule: {}", name).green());
}
config.save(&config_path)?;
println!("Configuration saved.");
Ok(())
}
pub async fn remove(name: String) -> Result<()> {
let project_root = ensure_initialized()?;
let config_path = agentlog_path(&project_root).join("config.json");
let mut config = if config_path.exists() {
Config::load(&config_path)?
} else {
Config::default()
};
let initial_len = config.policy.rules.len();
config.policy.rules.retain(|r| r.name != name);
if config.policy.rules.len() < initial_len {
config.save(&config_path)?;
println!("{}", format!("Removed rule: {}", name).green());
} else {
println!("{}", format!("Rule not found: {}", name).yellow());
}
Ok(())
}
pub async fn toggle(enabled: bool) -> Result<()> {
let project_root = ensure_initialized()?;
let config_path = agentlog_path(&project_root).join("config.json");
let mut config = if config_path.exists() {
Config::load(&config_path)?
} else {
Config::default()
};
config.policy.enabled = enabled;
config.save(&config_path)?;
if enabled {
println!("{}", "Policy enforcement ENABLED".green());
} else {
println!("{}", "Policy enforcement DISABLED".yellow());
}
Ok(())
}
pub async fn check(file_path: String) -> Result<()> {
let project_root = ensure_initialized()?;
let config_path = agentlog_path(&project_root).join("config.json");
let config = if config_path.exists() {
Config::load(&config_path)?
} else {
Config::default()
};
let engine = PolicyEngine::new(config.policy)?;
let path = std::path::Path::new(&file_path);
println!("{}", format!("Checking: {}", file_path).bold());
println!();
if let Some(violation) = engine.check_file(path) {
println!("{}", violation.format_message());
} else {
println!("{}", "No policy violations found.".green());
}
Ok(())
}
fn parse_action(action: &str) -> Result<PolicyAction> {
match action.to_lowercase().as_str() {
"block" => Ok(PolicyAction::Block),
"warn" => Ok(PolicyAction::Warn),
"confirm" | "require_confirmation" => Ok(PolicyAction::RequireConfirmation),
"allow" => Ok(PolicyAction::Allow),
_ => Err(anyhow::anyhow!(
"Invalid action: {}. Use: block, warn, confirm, allow",
action
)),
}
}