use crate::core::Finding;
use async_trait::async_trait;
use std::path::Path;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum PluginError {
#[error("Plugin initialization failed: {0}")]
InitializationFailed(String),
#[error("Scan failed: {0}")]
ScanFailed(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Configuration error: {0}")]
Config(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScanPhase {
PreExtract,
PostExtract,
GitInternals,
PreCommit,
PrePush,
All,
}
pub struct ScanContext<'a> {
pub path: &'a Path,
pub scan_phase: ScanPhase,
pub file_content: Option<&'a [u8]>,
pub metadata: std::collections::HashMap<String, String>,
}
pub struct PluginReport {
pub plugin_name: String,
pub findings: Vec<Finding>,
pub scanned_files: usize,
pub duration_ms: u64,
}
impl PluginReport {
pub fn new(name: String) -> Self {
Self {
plugin_name: name,
findings: Vec::new(),
scanned_files: 0,
duration_ms: 0,
}
}
}
#[async_trait]
pub trait SecurityPlugin: Send + Sync {
fn name(&self) -> &str;
fn version(&self) -> &str;
fn description(&self) -> &str;
fn scan_phase(&self) -> ScanPhase;
async fn initialize(&mut self) -> Result<(), PluginError>;
async fn scan(&self, context: &ScanContext<'_>) -> Result<PluginReport, PluginError>;
async fn cleanup(&mut self) -> Result<(), PluginError> {
Ok(())
}
}