vanguard_plugin/
validator.rs1use std::path::Path;
2use thiserror::Error;
3
4use crate::PluginMetadata;
5
6#[derive(Error, Debug)]
8pub enum ValidationError {
9 #[error("Signature verification failed: {0}")]
11 SignatureInvalid(String),
12
13 #[error("Platform not supported: {0}")]
15 PlatformIncompatible(String),
16
17 #[error("Resource limit exceeded: {0}")]
19 ResourceLimitExceeded(String),
20
21 #[error("Sandbox constraint violation: {0}")]
23 SandboxViolation(String),
24
25 #[error("Invalid metadata: {0}")]
27 InvalidMetadata(String),
28}
29
30pub type ValidationResult = Result<(), ValidationError>;
32
33#[derive(Debug)]
35pub struct PluginValidator {
36 pub max_memory: usize,
38 pub strict_signatures: bool,
40 pub enforce_sandbox: bool,
42}
43
44impl Default for PluginValidator {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl PluginValidator {
51 pub fn new() -> Self {
53 Self {
54 max_memory: 100 * 1024 * 1024, strict_signatures: true,
56 enforce_sandbox: true,
57 }
58 }
59
60 pub fn with_max_memory(mut self, max_bytes: usize) -> Self {
62 self.max_memory = max_bytes;
63 self
64 }
65
66 pub fn with_strict_signatures(mut self, strict: bool) -> Self {
68 self.strict_signatures = strict;
69 self
70 }
71
72 pub fn with_sandbox(mut self, enforce: bool) -> Self {
74 self.enforce_sandbox = enforce;
75 self
76 }
77
78 pub async fn validate_plugin(
80 &self,
81 binary_path: &Path,
82 metadata: &PluginMetadata,
83 ) -> ValidationResult {
84 self.validate_metadata(metadata)?;
86
87 if self.strict_signatures {
89 self.verify_signature(binary_path)?;
90 }
91
92 self.check_platform_compatibility(metadata)?;
94
95 self.validate_resources(binary_path)?;
97
98 if self.enforce_sandbox {
100 self.check_sandbox_constraints(binary_path)?;
101 }
102
103 Ok(())
104 }
105
106 fn validate_metadata(&self, metadata: &PluginMetadata) -> ValidationResult {
108 if metadata.name.is_empty() {
110 return Err(ValidationError::InvalidMetadata("name is required".into()));
111 }
112 if metadata.version.is_empty() {
113 return Err(ValidationError::InvalidMetadata(
114 "version is required".into(),
115 ));
116 }
117 Ok(())
118 }
119
120 fn verify_signature(&self, _binary_path: &Path) -> ValidationResult {
122 Ok(())
125 }
126
127 fn check_platform_compatibility(&self, _metadata: &PluginMetadata) -> ValidationResult {
129 Ok(())
132 }
133
134 fn validate_resources(&self, _binary_path: &Path) -> ValidationResult {
136 Ok(())
139 }
140
141 fn check_sandbox_constraints(&self, _binary_path: &Path) -> ValidationResult {
143 Ok(())
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use std::path::PathBuf;
153
154 fn create_test_metadata() -> PluginMetadata {
155 PluginMetadata {
156 name: "test-plugin".to_string(),
157 version: "1.0.0".to_string(),
158 description: "Test Plugin".to_string(),
159 author: "Test Author".to_string(),
160 min_vanguard_version: Some("0.1.0".to_string()),
161 max_vanguard_version: Some("2.0.0".to_string()),
162 dependencies: vec![],
163 }
164 }
165
166 #[tokio::test]
167 async fn test_validator_configuration() {
168 let validator = PluginValidator::new()
169 .with_max_memory(50 * 1024 * 1024)
170 .with_strict_signatures(false)
171 .with_sandbox(true);
172
173 assert_eq!(validator.max_memory, 50 * 1024 * 1024);
174 assert!(!validator.strict_signatures);
175 assert!(validator.enforce_sandbox);
176 }
177
178 #[tokio::test]
179 async fn test_metadata_validation() {
180 let validator = PluginValidator::new();
181 let metadata = create_test_metadata();
182
183 assert!(validator.validate_metadata(&metadata).is_ok());
184
185 let invalid_metadata = PluginMetadata {
187 name: "".to_string(),
188 ..metadata.clone()
189 };
190 assert!(matches!(
191 validator.validate_metadata(&invalid_metadata),
192 Err(ValidationError::InvalidMetadata(_))
193 ));
194 }
195
196 #[tokio::test]
197 async fn test_full_validation() {
198 let validator = PluginValidator::new();
199 let metadata = create_test_metadata();
200 let binary_path = PathBuf::from("test-binary");
201
202 let result = validator.validate_plugin(&binary_path, &metadata).await;
203 assert!(result.is_ok());
204 }
205}