use anyhow::{Context, Result};
use std::any::Any;
use std::collections::HashMap;
use std::sync::{OnceLock, RwLock};
use crate::security::{SecurityValidator, SecurityCheckResult};
use crate::types::*;
#[cfg(feature = "tracing")]
use tracing::info;
#[cfg(not(feature = "tracing"))]
macro_rules! info {
($($arg:tt)*) => {};
}
pub struct ModuleRegistry {
modules: RwLock<HashMap<String, (ModuleMetadata, ModuleFactory)>>,
}
impl ModuleRegistry {
pub fn new() -> Self {
Self {
modules: RwLock::new(HashMap::new()),
}
}
pub fn global() -> &'static Self {
static REGISTRY: OnceLock<ModuleRegistry> = OnceLock::new();
REGISTRY.get_or_init(|| {
let registry = Self::new();
for reg in inventory::iter::<ModuleRegistration> {
let metadata = ModuleMetadata::new(
reg.name.to_string(),
reg.module_type.to_string(),
reg.instantiate_fn_name.to_string(),
reg.module_path.to_string(),
reg.struct_name.to_string(),
);
registry
.modules
.write()
.unwrap()
.insert(metadata.name.clone(), (metadata, reg.factory));
}
info!(
"Module registry initialized with {} modules",
registry.modules.read().unwrap().len()
);
registry
})
}
pub fn register(&self, name: &str, module_type: &str, factory: ModuleFactory) {
self.register_with_metadata(
name,
module_type,
"factory",
module_path!(),
"Module",
factory,
);
}
pub fn register_with_metadata(
&self,
name: &str,
module_type: &str,
instantiate_fn: &str,
module_path: &str,
struct_name: &str,
factory: ModuleFactory,
) {
let metadata = ModuleMetadata::new(
name.to_string(),
module_type.to_string(),
instantiate_fn.to_string(),
module_path.to_string(),
struct_name.to_string(),
);
let mut modules = self.modules.write().expect("Failed to acquire write lock");
modules.insert(name.to_string(), (metadata, factory));
info!("Registered module: {} (type: {})", name, module_type);
}
pub fn create_any(&self, name: &str) -> Result<Box<dyn Any + Send + Sync>> {
let modules = self.modules.read().expect("Failed to acquire read lock");
let (_metadata, factory) = modules
.get(name)
.ok_or_else(|| anyhow::anyhow!("Module not found: {}", name))?;
info!("Creating module: {}", name);
factory().with_context(|| format!("Failed to instantiate module: {}", name))
}
pub fn create<T: 'static>(&self, name: &str) -> Result<Box<T>> {
let any_module = self.create_any(name)?;
any_module
.downcast::<T>()
.map_err(|_| anyhow::anyhow!("Module type mismatch for: {}", name))
}
pub fn list_modules(&self) -> Vec<String> {
self.modules
.read()
.expect("Failed to acquire read lock")
.keys()
.cloned()
.collect()
}
pub fn get_module_names(&self) -> Vec<String> {
self.list_modules()
}
pub fn has_module(&self, name: &str) -> bool {
self.modules
.read()
.expect("Failed to acquire read lock")
.contains_key(name)
}
pub fn get_metadata(&self, name: &str) -> Option<ModuleMetadata> {
self.modules
.read()
.expect("Failed to acquire read lock")
.get(name)
.map(|(metadata, _)| metadata.clone())
}
pub fn clear(&self) {
self.modules
.write()
.expect("Failed to acquire write lock")
.clear();
}
pub fn count(&self) -> usize {
self.modules
.read()
.expect("Failed to acquire read lock")
.len()
}
pub fn verify_module_signature(&self, name: &str) -> Result<bool> {
let modules = self.modules.read().expect("Failed to acquire read lock");
let (metadata, _) = modules
.get(name)
.ok_or_else(|| anyhow::anyhow!("Module not found: {}", name))?;
SecurityValidator::verify_signature(metadata)
}
pub fn check_module_permissions(&self, name: &str, required_permission: &str) -> Result<bool> {
let modules = self.modules.read().expect("Failed to acquire read lock");
let (metadata, _) = modules
.get(name)
.ok_or_else(|| anyhow::anyhow!("Module not found: {}", name))?;
SecurityValidator::check_permissions(metadata, required_permission)
}
pub fn is_module_approved(&self, name: &str) -> Result<bool> {
let modules = self.modules.read().expect("Failed to acquire read lock");
let (metadata, _) = modules
.get(name)
.ok_or_else(|| anyhow::anyhow!("Module not found: {}", name))?;
SecurityValidator::is_approved(metadata)
}
pub fn verify_supply_chain(&self, name: &str) -> Result<bool> {
let modules = self.modules.read().expect("Failed to acquire read lock");
let (metadata, _) = modules
.get(name)
.ok_or_else(|| anyhow::anyhow!("Module not found: {}", name))?;
SecurityValidator::verify_supply_chain(metadata)
}
pub fn create_secure(&self, name: &str) -> Result<Box<dyn Any + Send + Sync>> {
if !self.verify_module_signature(name)? {
return Err(anyhow::anyhow!("Module signature verification failed: {}", name));
}
if !self.is_module_approved(name)? {
return Err(anyhow::anyhow!("Module not approved: {}", name));
}
if !self.verify_supply_chain(name)? {
return Err(anyhow::anyhow!("Supply chain verification failed: {}", name));
}
self.create_with_sandbox(name)
}
pub fn create_with_sandbox(&self, name: &str) -> Result<Box<dyn Any + Send + Sync>> {
let modules = self.modules.read().expect("Failed to acquire read lock");
let (metadata, factory) = modules
.get(name)
.ok_or_else(|| anyhow::anyhow!("Module not found: {}", name))?;
if metadata.sandbox_config.enabled {
info!("Creating sandboxed module: {}", name);
info!("Sandbox config: {:?}", metadata.sandbox_config);
}
info!("Creating module: {}", name);
factory().with_context(|| format!("Failed to instantiate module: {}", name))
}
pub fn register_secure(
&self,
name: &str,
module_type: &str,
factory: ModuleFactory,
signature: Option<ModuleSignature>,
permissions: ModulePermissions,
supply_chain: Option<SupplyChainInfo>,
) {
let metadata = ModuleMetadata::secure(
name.to_string(),
module_type.to_string(),
"factory".to_string(),
module_path!().to_string(),
"Module".to_string(),
signature,
permissions,
supply_chain,
);
let mut modules = self.modules.write().expect("Failed to acquire write lock");
modules.insert(name.to_string(), (metadata, factory));
info!("Registered secure module: {} (type: {})", name, module_type);
}
pub fn update_review_status(
&self,
name: &str,
status: CodeReviewStatus,
) -> Result<()> {
let mut modules = self.modules.write().expect("Failed to acquire write lock");
let (metadata, factory) = modules
.get_mut(name)
.ok_or_else(|| anyhow::anyhow!("Module not found: {}", name))?;
metadata.review_status = status;
info!("Updated review status for module: {}", name);
Ok(())
}
pub fn get_security_report(&self) -> HashMap<String, SecurityReport> {
let modules = self.modules.read().expect("Failed to acquire read lock");
let mut report = HashMap::new();
for (name, (metadata, _)) in modules.iter() {
let security_report = SecurityReport {
name: name.clone(),
has_signature: metadata.signature.is_some(),
signature_verified: metadata.signature.is_some(),
is_approved: matches!(metadata.review_status, CodeReviewStatus::Approved { .. }),
has_supply_chain: metadata.supply_chain.is_some(),
supply_chain_verified: metadata.supply_chain.is_some(),
permissions: metadata.permissions.clone(),
sandbox_enabled: metadata.sandbox_config.enabled,
};
report.insert(name.clone(), security_report);
}
report
}
pub fn security_audit(&self) -> HashMap<String, SecurityCheckResult> {
let modules = self.modules.read().expect("Failed to acquire read lock");
let mut audit_results = HashMap::new();
for (name, (metadata, _)) in modules.iter() {
let security_check = SecurityValidator::comprehensive_check(metadata);
audit_results.insert(name.clone(), security_check);
}
audit_results
}
}
impl Default for ModuleRegistry {
fn default() -> Self {
Self::new()
}
}