Skip to main content

scirs2_core/ecosystem/
validation.rs

1//! Ecosystem validation and compatibility checking
2//!
3//! This module provides comprehensive validation for the SciRS2 ecosystem,
4//! ensuring compatibility between modules, API stability, and proper
5//! integration for production 1.0 deployments.
6
7use crate::apiversioning::Version;
8use crate::error::{CoreError, CoreResult, ErrorContext};
9use std::collections::{HashMap, HashSet};
10use std::sync::{Arc, RwLock};
11use std::time::{Duration, Instant};
12
13/// Global ecosystem validator instance
14static GLOBAL_VALIDATOR: std::sync::OnceLock<Arc<EcosystemValidator>> = std::sync::OnceLock::new();
15
16/// Comprehensive ecosystem validator for production environments
17#[derive(Debug)]
18pub struct EcosystemValidator {
19    registry: Arc<RwLock<ModuleRegistry>>,
20    compatibilitymatrix: Arc<RwLock<CompatibilityMatrix>>,
21    validation_cache: Arc<RwLock<ValidationCache>>,
22    policies: Arc<RwLock<ValidationPolicies>>,
23}
24
25#[allow(dead_code)]
26impl EcosystemValidator {
27    /// Create new ecosystem validator
28    pub fn new() -> CoreResult<Self> {
29        Ok(Self {
30            registry: Arc::new(RwLock::new(ModuleRegistry::new())),
31            compatibilitymatrix: Arc::new(RwLock::new(CompatibilityMatrix::new())),
32            validation_cache: Arc::new(RwLock::new(ValidationCache::new())),
33            policies: Arc::new(RwLock::new(ValidationPolicies::default())),
34        })
35    }
36
37    /// Get global validator instance
38    pub fn global() -> CoreResult<Arc<Self>> {
39        Ok(GLOBAL_VALIDATOR
40            .get_or_init(|| Arc::new(Self::new().expect("Operation failed")))
41            .clone())
42    }
43
44    /// Register a module in the ecosystem
45    pub fn register_module(&self, module: ModuleInfo) -> CoreResult<()> {
46        let mut registry = self.registry.write().map_err(|_| {
47            CoreError::InvalidState(crate::error::ErrorContext {
48                message: "Failed to acquire registry lock".to_string(),
49                location: None,
50                cause: None,
51            })
52        })?;
53
54        registry.register(module)?;
55
56        // Invalidate relevant caches
57        let mut cache = self.validation_cache.write().map_err(|_| {
58            CoreError::InvalidState(ErrorContext {
59                message: "Failed to acquire cache lock".to_string(),
60                location: Some(crate::error::ErrorLocation::new(file!(), line!())),
61                cause: None,
62            })
63        })?;
64        cache.invalidate_module_related_cache();
65
66        Ok(())
67    }
68
69    /// Validate entire ecosystem compatibility
70    pub fn validate_ecosystem(&self) -> CoreResult<EcosystemValidationResult> {
71        let start_time = Instant::now();
72
73        // Check cache first
74        {
75            let cache = self.validation_cache.read().map_err(|_| {
76                CoreError::InvalidState(ErrorContext {
77                    message: "Failed to acquire cache lock".to_string(),
78                    location: Some(crate::error::ErrorLocation::new(file!(), line!())),
79                    cause: None,
80                })
81            })?;
82            if let Some(cachedresult) = cache.get_ecosystem_validation() {
83                if cachedresult.is_recent(Duration::from_secs(300)) {
84                    // 5 minutes
85                    return Ok(cachedresult.result.clone());
86                }
87            }
88        }
89
90        let registry = self.registry.read().map_err(|_| {
91            CoreError::InvalidState(crate::error::ErrorContext {
92                message: "Failed to acquire registry lock".to_string(),
93                location: None,
94                cause: None,
95            })
96        })?;
97        let policies = self.policies.read().map_err(|_| {
98            CoreError::InvalidState(ErrorContext {
99                message: "Failed to acquire policies lock".to_string(),
100                location: Some(crate::error::ErrorLocation::new(file!(), line!())),
101                cause: None,
102            })
103        })?;
104
105        let mut result = EcosystemValidationResult::new();
106
107        // Validate individual modules
108        for module in registry.all_modules() {
109            let moduleresult = self.validate_module_internal(module, &policies)?;
110            result.add_moduleresult(module.name.clone(), moduleresult);
111        }
112
113        // Validate inter-module compatibility
114        let compatibilityresult = self.validate_inter_module_compatibility(&registry, &policies)?;
115        result.add_compatibilityresult(compatibilityresult);
116
117        // Validate API stability
118        let api_stabilityresult = self.validate_api_stability(&registry, &policies)?;
119        result.add_api_stabilityresult(api_stabilityresult);
120
121        // Validate version consistency
122        let version_consistencyresult = self.validate_version_consistency(&registry)?;
123        result.add_version_consistencyresult(version_consistencyresult);
124
125        result.validation_time = start_time.elapsed();
126        result.timestamp = Instant::now();
127
128        // Cache the result
129        {
130            let mut cache = self.validation_cache.write().map_err(|_| {
131                CoreError::InvalidState(ErrorContext {
132                    message: "Failed to acquire cache lock".to_string(),
133                    location: Some(crate::error::ErrorLocation::new(file!(), line!())),
134                    cause: None,
135                })
136            })?;
137            cache.cache_ecosystem_validation(result.clone());
138        }
139
140        Ok(result)
141    }
142
143    /// Validate specific module compatibility with ecosystem
144    pub fn validate_module(&self, modulename: &str) -> CoreResult<ModuleValidationResult> {
145        let registry = self.registry.read().map_err(|_| {
146            CoreError::InvalidState(crate::error::ErrorContext {
147                message: "Failed to acquire registry lock".to_string(),
148                location: None,
149                cause: None,
150            })
151        })?;
152        let policies = self.policies.read().map_err(|_| {
153            CoreError::InvalidState(ErrorContext {
154                message: "Failed to acquire policies lock".to_string(),
155                location: Some(crate::error::ErrorLocation::new(file!(), line!())),
156                cause: None,
157            })
158        })?;
159
160        let module = registry.get_module(modulename).ok_or_else(|| {
161            CoreError::ValidationError(ErrorContext {
162                message: format!("Module '{modulename}' not found in registry"),
163                location: None,
164                cause: None,
165            })
166        })?;
167
168        self.validate_module_internal(module, &policies)
169    }
170
171    fn validate_module_internal(
172        &self,
173        module: &ModuleInfo,
174        policies: &ValidationPolicies,
175    ) -> CoreResult<ModuleValidationResult> {
176        let mut result = ModuleValidationResult::new(module.name.clone());
177
178        // Validate version format
179        if let Err(e) = Version::parse(&module.version) {
180            result.adderror(ValidationError::new(
181                ValidationErrorType::InvalidVersion,
182                format!("Invalid _version format '{}': {}", module.version, e),
183            ));
184        }
185
186        // Validate dependencies
187        for dep in &module.dependencies {
188            let depresult = self.validate_dependencypolicies(module, dep, policies)?;
189            if !depresult.is_valid() {
190                result.adderror(ValidationError::new(
191                    ValidationErrorType::DependencyError,
192                    format!("Dependency validation failed for '{}'", dep.name),
193                ));
194            }
195        }
196
197        // Validate API surface
198        // TODO: Implement proper API surface validation
199        // For now, create a successful result
200        let apiresult = ApiStabilityCheck {
201            is_stable: true,
202            breakingchanges: Vec::new(),
203        };
204        if !apiresult.is_valid() {
205            result.adderror(ValidationError::new(
206                ValidationErrorType::ApiCompatibility,
207                "API surface validation failed".to_string(),
208            ));
209        }
210
211        // Validate feature flags
212        for feature in &module.features {
213            if !self.is_feature_compatible(feature, policies)? {
214                result.add_warning(ValidationWarning::new(
215                    ValidationWarningType::FeatureCompatibility,
216                    format!("Feature '{feature}' may have compatibility issues"),
217                ));
218            }
219        }
220
221        // Validate security requirements
222        if policies.enforce_security_checks {
223            let securityresult = self.validate_module_security(module)?;
224            if !securityresult.is_secure() {
225                result.adderror(ValidationError::new(
226                    ValidationErrorType::SecurityViolation,
227                    "Module failed security validation".to_string(),
228                ));
229            }
230        }
231
232        Ok(result)
233    }
234
235    fn validate_dependencypolicies(
236        &self,
237        module: &ModuleInfo,
238        dep: &DependencyInfo,
239        policies: &ValidationPolicies,
240    ) -> CoreResult<DependencyValidationResult> {
241        let mut result = DependencyValidationResult::new(dep.name.clone());
242
243        // Check if dependency exists in registry
244        let registry = self.registry.read().map_err(|_| {
245            CoreError::InvalidState(crate::error::ErrorContext {
246                message: "Failed to acquire registry lock".to_string(),
247                location: None,
248                cause: None,
249            })
250        })?;
251
252        if let Some(dep_module) = registry.get_module(&dep.name) {
253            // Validate version compatibility
254            let dep_version = Version::parse(&dep_module.version).map_err(|e| {
255                CoreError::ValidationError(ErrorContext {
256                    message: format!("Invalid dependency version: {e}"),
257                    location: None,
258                    cause: None,
259                })
260            })?;
261
262            if !dep.version_requirement.version(&dep_version) {
263                result.add_incompatibility(format!(
264                    "Version mismatch: required {}, found {}",
265                    dep.version_requirement, dep_version
266                ));
267            }
268
269            // Check circular dependencies
270            if self.has_circular_dependency(&module.name, &dep.name) {
271                result.add_incompatibility("Circular dependency detected".to_string());
272            }
273        } else {
274            result.add_incompatibility("Dependency not found in ecosystem".to_string());
275        }
276
277        Ok(result)
278    }
279
280    fn validate_inter_module_compatibility(
281        &self,
282        registry: &ModuleRegistry,
283        policies: &ValidationPolicies,
284    ) -> CoreResult<CompatibilityValidationResult> {
285        let mut result = CompatibilityValidationResult::new();
286        let modules = registry.all_modules();
287
288        // Build compatibility matrix
289        let mut matrix = self.compatibilitymatrix.write().map_err(|_| {
290            CoreError::InvalidState(ErrorContext::new(
291                "Failed to acquire matrix lock".to_string(),
292            ))
293        })?;
294
295        for module_a in &modules {
296            for module_b in &modules {
297                if module_a.name != module_b.name {
298                    let compatibility =
299                        self.check_module_compatibility(module_a, module_b, policies)?;
300                    (*matrix).b(&module_a.name, &module_b.name, compatibility.clone());
301
302                    if !compatibility.is_compatible() {
303                        result.add_incompatibility(format!(
304                            "Modules '{}' and '{}' are incompatible: {}",
305                            module_a.name,
306                            module_b.name,
307                            compatibility.reason_2()
308                        ));
309                    }
310                }
311            }
312        }
313
314        Ok(result)
315    }
316
317    fn check_module_compatibility(
318        &self,
319        module_a: &ModuleInfo,
320        module_b: &ModuleInfo,
321        policies: &ValidationPolicies,
322    ) -> CoreResult<ModuleCompatibility> {
323        // Check version compatibility
324        let version_a = Version::parse(&module_a.version).map_err(|e| {
325            CoreError::ValidationError(ErrorContext {
326                message: format!("Invalid _version for module '{}': {}", module_a.name, e),
327                location: Some(crate::error::ErrorLocation::new(file!(), line!())),
328                cause: None,
329            })
330        })?;
331        let version_b = Version::parse(&module_b.version).map_err(|e| {
332            CoreError::ValidationError(ErrorContext {
333                message: format!("Invalid _version for module '{}': {}", module_b.name, e),
334                location: Some(crate::error::ErrorLocation::new(file!(), line!())),
335                cause: None,
336            })
337        })?;
338
339        if !self.areversions_compatible(&version_a.to_string(), &version_b.to_string()) {
340            return Ok(ModuleCompatibility::incompatible(format!(
341                "Version incompatibility: {version_a} vs {version_b}"
342            )));
343        }
344
345        // Check API compatibility
346        if !self.are_apis_compatible(&module_a.apisurface, &module_b.apisurface) {
347            return Ok(ModuleCompatibility::incompatible(
348                "API incompatibility".to_string(),
349            ));
350        }
351
352        // Check feature compatibility
353        if !self.are_features_compatible(&module_a.features, &module_b.features) {
354            return Ok(ModuleCompatibility::incompatible(
355                "Feature incompatibility".to_string(),
356            ));
357        }
358
359        Ok(ModuleCompatibility::compatible())
360    }
361
362    fn validate_api_stability(
363        &self,
364        registry: &ModuleRegistry,
365        policies: &ValidationPolicies,
366    ) -> CoreResult<ApiStabilityResult> {
367        let mut result = ApiStabilityResult::new();
368
369        for module in registry.all_modules() {
370            // Check for breaking changes in API
371            if let Some(_previous_version) = registry.get_previous_version(&module.name) {
372                let stability_check = self.check_api_stability(&module.name);
373                if !stability_check.is_stable() {
374                    result.add_breaking_change(
375                        module.name.clone(),
376                        stability_check.breakingchanges().to_vec(),
377                    );
378                }
379            }
380
381            // Validate API versioning compliance
382            if !self.is_api_properly_versioned(&module.apisurface) {
383                result.add_versioning_violation(
384                    module.name.clone(),
385                    "API not properly versioned".to_string(),
386                );
387            }
388        }
389
390        Ok(result)
391    }
392
393    fn validate_version_consistency(
394        &self,
395        registry: &ModuleRegistry,
396    ) -> CoreResult<VersionConsistencyResult> {
397        let mut result = VersionConsistencyResult::new();
398        let modules = registry.all_modules();
399
400        // Check for version conflicts
401        let mut version_map: HashMap<String, Vec<Version>> = HashMap::new();
402
403        for module in &modules {
404            let version = Version::parse(&module.version).map_err(|e| {
405                CoreError::ValidationError(ErrorContext {
406                    message: format!("Invalid version for module '{}': {}", module.name, e),
407                    location: Some(crate::error::ErrorLocation::new(file!(), line!())),
408                    cause: None,
409                })
410            })?;
411            version_map
412                .entry(module.name.clone())
413                .or_default()
414                .push(version);
415        }
416
417        for (modulename, versions) in version_map {
418            if versions.len() > 1 {
419                result.add_conflict(modulename, versions);
420            }
421        }
422
423        // Validate dependency version consistency
424        for module in &modules {
425            for dep in &module.dependencies {
426                if let Some(dep_module) = registry.get_module(&dep.name) {
427                    let dep_version = Version::parse(&dep_module.version).map_err(|e| {
428                        CoreError::ValidationError(ErrorContext {
429                            message: format!(
430                                "Invalid _version format for dependency {}: {}",
431                                dep.name, e
432                            ),
433                            location: Some(crate::error::ErrorLocation::new(file!(), line!())),
434                            cause: None,
435                        })
436                    })?;
437                    if !dep.version_requirement.version(&dep_version) {
438                        result.add_dependency_mismatch(
439                            module.name.clone(),
440                            dep.name.clone(),
441                            dep.version_requirement.clone(),
442                            dep_version,
443                        );
444                    }
445                }
446            }
447        }
448
449        Ok(result)
450    }
451
452    #[allow(dead_code)]
453    fn surface(
454        &self,
455        apisurface: &ApiSurface,
456        policies: &ValidationPolicies,
457    ) -> CoreResult<ApiValidationResult> {
458        let mut result = ApiValidationResult::new();
459
460        // Validate public APIs
461        for api in &apisurface.public_apis {
462            if !self.is_api_properly_documented(api)? {
463                result.add_documentation_issue(api.name.clone());
464            }
465
466            if policies.enforce_semver && !self.is_api_semver_compliant(api)? {
467                result.add_semver_violation(api.name.clone());
468            }
469        }
470
471        // Validate deprecated APIs
472        for api in &apisurface.deprecated_apis {
473            if !api.has_migration_path() {
474                result.add_deprecation_issue(
475                    api.name.clone(),
476                    "No migration path provided".to_string(),
477                );
478            }
479        }
480
481        Ok(result)
482    }
483
484    fn validate_module_security(
485        &self,
486        module: &ModuleInfo,
487    ) -> CoreResult<SecurityValidationResult> {
488        let mut result = SecurityValidationResult::new(module.name.clone());
489
490        // Check for known vulnerabilities
491        for dep in &module.dependencies {
492            if self.has_known_vulnerabilities(&dep.name) {
493                result.add_vulnerability(format!(
494                    "Dependency '{}' has known vulnerabilities",
495                    dep.name
496                ));
497            }
498        }
499
500        // Validate security features
501        if !module.features.contains(&"security".to_string())
502            && self.requires_security_features(module)?
503        {
504            result.add_security_issue("Module should enable security features".to_string());
505        }
506
507        Ok(result)
508    }
509
510    // Helper methods
511    #[allow(dead_code)]
512    fn check_circular_dependencies(
513        &self,
514        modulename: &str,
515        dependencies: &[DependencyInfo],
516    ) -> CoreResult<bool> {
517        // Simple circular dependency detection
518        for dep in dependencies {
519            if dep.name == modulename {
520                return Ok(true);
521            }
522        }
523        Ok(false)
524    }
525
526    fn check_version_compatibility(
527        &self,
528        version_a: &Version,
529        version_b: &Version,
530        policies: &ValidationPolicies,
531    ) -> bool {
532        if policies.strict_version_matching {
533            version_a == version_b
534        } else {
535            // Allow compatible versions (same major version)
536            version_a.major == version_b.major
537        }
538    }
539
540    fn check_api_compatibility(&self, api_a: &ApiSurface, apib: &ApiSurface) -> CoreResult<bool> {
541        // Simple API compatibility check
542        // In _a real implementation, this would do deep API analysis
543        Ok(api_a.public_apis.len() == apib.public_apis.len())
544    }
545
546    fn check_feature_compatibility(
547        &self,
548        _features_a: &[String],
549        _features_b: &[String],
550    ) -> CoreResult<bool> {
551        // Check for conflicting features
552        // In _a real implementation, would check for conflicts
553        // No conflicting features for now
554        Ok(true)
555    }
556
557    fn validate_apipolicies(
558        &self,
559        previous: &ApiSurface,
560        current: &ApiSurface,
561        policies: &ValidationPolicies,
562    ) -> CoreResult<ApiStabilityCheck> {
563        let mut breakingchanges = Vec::new();
564
565        // Check for removed APIs
566        for prev_api in &previous.public_apis {
567            if !current
568                .public_apis
569                .iter()
570                .any(|api| api.name == prev_api.name)
571            {
572                breakingchanges.push(format!("API '{}' was removed", prev_api.name));
573            }
574        }
575
576        // Check for signature changes
577        for current_api in &current.public_apis {
578            if let Some(prev_api) = previous
579                .public_apis
580                .iter()
581                .find(|api| api.name == current_api.name)
582            {
583                if current_api.signature != prev_api.signature {
584                    breakingchanges.push(format!("API '{}' signature changed", current_api.name));
585                }
586            }
587        }
588
589        Ok(ApiStabilityCheck::new(
590            breakingchanges.is_empty(),
591            breakingchanges,
592        ))
593    }
594
595    fn is_apisurface_versioned(&self, apisurface: &ApiSurface) -> CoreResult<bool> {
596        // Check if all APIs have version information
597        for api in &apisurface.public_apis {
598            if api.since_version.is_none() {
599                return Ok(false);
600            }
601        }
602        Ok(true)
603    }
604
605    fn is_feature_compatible(
606        &self,
607        feature: &str,
608        policies: &ValidationPolicies,
609    ) -> CoreResult<bool> {
610        // Check feature compatibility rules
611        Ok(!policies.incompatible_features.contains(feature))
612    }
613
614    fn is_api_properly_documented(&self, api: &ApiInfo) -> CoreResult<bool> {
615        Ok(!api.documentation.is_empty())
616    }
617
618    fn is_api_semver_compliant(&self, api: &ApiInfo) -> CoreResult<bool> {
619        // Check if API follows semantic versioning principles
620        Ok(api.since_version.is_some())
621    }
622
623    fn req(&self, _module: &ModuleInfo, _versionreq: &VersionRequirement) -> CoreResult<bool> {
624        // In a real implementation, this would check against vulnerability databases
625        Ok(false)
626    }
627
628    fn requires_security_features(&self, module: &ModuleInfo) -> CoreResult<bool> {
629        // Check if module handles sensitive data or network operations
630        Ok(module.name.contains("network") || module.name.contains("auth"))
631    }
632
633    /// Update validation policies
634    pub fn updatepolicies(&self, newpolicies: ValidationPolicies) -> CoreResult<()> {
635        let mut policies = self.policies.write().map_err(|_| {
636            CoreError::InvalidState(ErrorContext::new(
637                "Failed to acquire policies lock".to_string(),
638            ))
639        })?;
640        *policies = newpolicies;
641
642        // Clear cache since policies changed
643        let mut cache = self.validation_cache.write().map_err(|_| {
644            CoreError::InvalidState(ErrorContext::new(
645                "Failed to acquire cache lock".to_string(),
646            ))
647        })?;
648        cache.clear();
649
650        Ok(())
651    }
652
653    /// Get ecosystem health summary
654    pub fn get_ecosystem_health(&self) -> CoreResult<EcosystemHealth> {
655        let validationresult = self.validate_ecosystem()?;
656        Ok(EcosystemHealth::from_validationresult(&validationresult))
657    }
658
659    pub fn has_circular_dependency(&self, _module: &str, dependency: &str) -> bool {
660        // Placeholder implementation
661        false
662    }
663
664    pub fn areversions_compatible(&self, _version_a: &str, _versionb: &str) -> bool {
665        // Placeholder implementation
666        true
667    }
668
669    pub fn are_apis_compatible(&self, _api_a: &ApiSurface, _apib: &ApiSurface) -> bool {
670        // Placeholder implementation
671        true
672    }
673
674    pub fn are_features_compatible(&self, _features_a: &[String], _featuresb: &[String]) -> bool {
675        // Placeholder implementation
676        true
677    }
678
679    pub fn check_api_stability(&self, module: &str) -> ApiStabilityCheck {
680        // Placeholder implementation
681        ApiStabilityCheck::new(true, vec![])
682    }
683
684    pub fn is_api_properly_versioned(&self, _apisurface: &ApiSurface) -> bool {
685        // Placeholder implementation
686        true
687    }
688
689    pub fn has_known_vulnerabilities(&self, module: &str) -> bool {
690        // Placeholder implementation
691        false
692    }
693}
694
695/// Module registry for tracking ecosystem components
696#[derive(Debug)]
697pub struct ModuleRegistry {
698    modules: HashMap<String, ModuleInfo>,
699    previousversions: HashMap<String, ModuleInfo>,
700}
701
702impl ModuleRegistry {
703    pub fn new() -> Self {
704        Self {
705            modules: HashMap::new(),
706            previousversions: HashMap::new(),
707        }
708    }
709
710    pub fn register(&mut self, module: ModuleInfo) -> CoreResult<()> {
711        // Store previous version if updating
712        if let Some(existing) = self.modules.get(&module.name) {
713            self.previousversions
714                .insert(module.name.clone(), existing.clone());
715        }
716
717        self.modules.insert(module.name.clone(), module);
718        Ok(())
719    }
720
721    pub fn get_module(&self, name: &str) -> Option<&ModuleInfo> {
722        self.modules.get(name)
723    }
724
725    pub fn get_previous_version(&self, name: &str) -> Option<&ModuleInfo> {
726        self.previousversions.get(name)
727    }
728
729    pub fn all_modules(&self) -> Vec<&ModuleInfo> {
730        self.modules.values().collect()
731    }
732
733    pub fn module_count(&self) -> usize {
734        self.modules.len()
735    }
736}
737
738impl Default for ModuleRegistry {
739    fn default() -> Self {
740        Self::new()
741    }
742}
743
744/// Information about a module in the ecosystem
745#[derive(Debug, Clone)]
746pub struct ModuleInfo {
747    pub name: String,
748    pub version: String,
749    pub dependencies: Vec<DependencyInfo>,
750    pub apisurface: ApiSurface,
751    pub features: Vec<String>,
752    pub metadata: ModuleMetadata,
753}
754
755#[derive(Debug, Clone)]
756pub struct DependencyInfo {
757    pub name: String,
758    pub version_requirement: VersionRequirement,
759    pub optional: bool,
760}
761
762#[derive(Debug, Clone)]
763pub struct VersionRequirement {
764    pub requirement: String,
765}
766
767impl VersionRequirement {
768    pub fn new(requirement: &str) -> Self {
769        Self {
770            requirement: requirement.to_string(),
771        }
772    }
773
774    pub fn version(&self, version: &Version) -> bool {
775        // Simple version matching for now
776        // In a real implementation, this would parse semver requirements
777        self.requirement == version.to_string()
778    }
779}
780
781impl std::fmt::Display for VersionRequirement {
782    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
783        write!(f, "{}", self.requirement)
784    }
785}
786
787#[derive(Debug, Clone)]
788pub struct ApiSurface {
789    pub public_apis: Vec<ApiInfo>,
790    pub deprecated_apis: Vec<DeprecatedApiInfo>,
791}
792
793#[derive(Debug, Clone)]
794pub struct ApiInfo {
795    pub name: String,
796    pub signature: String,
797    pub documentation: String,
798    pub since_version: Option<Version>,
799    pub stability: ApiStability,
800}
801
802#[derive(Debug, Clone)]
803pub struct DeprecatedApiInfo {
804    pub name: String,
805    pub deprecated_since: Version,
806    pub removal_version: Option<Version>,
807    pub migration_path: Option<String>,
808}
809
810impl DeprecatedApiInfo {
811    pub fn has_migration_path(&self) -> bool {
812        self.migration_path.is_some()
813    }
814}
815
816#[derive(Debug, Clone, Copy, PartialEq, Eq)]
817pub enum ApiStability {
818    Stable,
819    Unstable,
820    Experimental,
821}
822
823#[derive(Debug, Clone)]
824pub struct ModuleMetadata {
825    pub author: String,
826    pub description: String,
827    pub license: String,
828    pub repository: Option<String>,
829    pub build_time: Option<String>,
830}
831
832/// Compatibility matrix for module interactions
833#[derive(Debug)]
834pub struct CompatibilityMatrix {
835    matrix: HashMap<(String, String), ModuleCompatibility>,
836}
837
838impl CompatibilityMatrix {
839    pub fn new() -> Self {
840        Self {
841            matrix: HashMap::new(),
842        }
843    }
844
845    pub fn b(&mut self, module_a: &str, moduleb: &str, compatibility: ModuleCompatibility) {
846        self.matrix
847            .insert((module_a.to_string(), moduleb.to_string()), compatibility);
848    }
849
850    pub fn b_2(&self, module_a: &str, moduleb: &str) -> Option<&ModuleCompatibility> {
851        self.matrix
852            .get(&(module_a.to_string(), moduleb.to_string()))
853    }
854}
855
856impl Default for CompatibilityMatrix {
857    fn default() -> Self {
858        Self::new()
859    }
860}
861
862#[derive(Debug, Clone)]
863pub struct ModuleCompatibility {
864    compatible: bool,
865    reason: String,
866}
867
868impl ModuleCompatibility {
869    pub fn compatible() -> Self {
870        Self {
871            compatible: true,
872            reason: String::new(),
873        }
874    }
875
876    pub fn incompatible(reason: String) -> Self {
877        Self {
878            compatible: false,
879            reason,
880        }
881    }
882}
883
884impl ModuleCompatibility {
885    pub fn is_compatible(&self) -> bool {
886        self.compatible
887    }
888
889    pub fn reason_2(&self) -> &str {
890        &self.reason
891    }
892}
893
894/// Validation cache for performance optimization
895#[derive(Debug)]
896pub struct ValidationCache {
897    ecosystem_validation: Option<CachedValidationResult>,
898    module_validations: HashMap<String, CachedModuleValidation>,
899}
900
901impl ValidationCache {
902    pub fn new() -> Self {
903        Self {
904            ecosystem_validation: None,
905            module_validations: HashMap::new(),
906        }
907    }
908
909    pub fn cache_ecosystem_validation(&mut self, result: EcosystemValidationResult) {
910        self.ecosystem_validation = Some(CachedValidationResult {
911            result,
912            timestamp: Instant::now(),
913        });
914    }
915
916    pub fn get_ecosystem_validation(&self) -> Option<&CachedValidationResult> {
917        self.ecosystem_validation.as_ref()
918    }
919
920    pub fn invalidate_module_related_cache(&mut self) {
921        self.ecosystem_validation = None;
922        self.module_validations.clear();
923    }
924
925    pub fn clear(&mut self) {
926        self.ecosystem_validation = None;
927        self.module_validations.clear();
928    }
929}
930
931impl Default for ValidationCache {
932    fn default() -> Self {
933        Self::new()
934    }
935}
936
937#[derive(Debug, Clone)]
938pub struct CachedValidationResult {
939    pub result: EcosystemValidationResult,
940    pub timestamp: Instant,
941}
942
943impl CachedValidationResult {
944    pub fn age(&self, maxage: Duration) -> bool {
945        self.timestamp.elapsed() < maxage
946    }
947
948    pub fn is_recent(&self, maxage: Duration) -> bool {
949        self.age(maxage)
950    }
951}
952
953#[derive(Debug)]
954pub struct CachedModuleValidation {
955    pub result: ModuleValidationResult,
956    pub timestamp: Instant,
957}
958
959/// Validation policies and configuration
960#[derive(Debug, Clone)]
961pub struct ValidationPolicies {
962    pub enforce_semver: bool,
963    pub strict_version_matching: bool,
964    pub enforce_security_checks: bool,
965    pub allow_deprecated_apis: bool,
966    pub max_dependency_depth: usize,
967    pub incompatible_features: HashSet<String>,
968    pub required_features: HashSet<String>,
969}
970
971impl Default for ValidationPolicies {
972    fn default() -> Self {
973        Self {
974            enforce_semver: true,
975            strict_version_matching: false,
976            enforce_security_checks: true,
977            allow_deprecated_apis: true,
978            max_dependency_depth: 10,
979            incompatible_features: HashSet::new(),
980            required_features: HashSet::new(),
981        }
982    }
983}
984
985/// Comprehensive validation results
986#[derive(Debug, Clone)]
987pub struct EcosystemValidationResult {
988    pub timestamp: Instant,
989    pub validation_time: Duration,
990    pub moduleresults: HashMap<String, ModuleValidationResult>,
991    pub compatibilityresult: CompatibilityValidationResult,
992    pub api_stabilityresult: ApiStabilityResult,
993    pub version_consistencyresult: VersionConsistencyResult,
994    pub overall_status: ValidationStatus,
995}
996
997impl EcosystemValidationResult {
998    pub fn new() -> Self {
999        Self {
1000            timestamp: Instant::now(),
1001            validation_time: Duration::ZERO,
1002            moduleresults: HashMap::new(),
1003            compatibilityresult: CompatibilityValidationResult::new(),
1004            api_stabilityresult: ApiStabilityResult::new(),
1005            version_consistencyresult: VersionConsistencyResult::new(),
1006            overall_status: ValidationStatus::Unknown,
1007        }
1008    }
1009
1010    pub fn name(&mut self, modulename: String, result: ModuleValidationResult) {
1011        self.moduleresults.insert(modulename, result);
1012        self.update_overall_status();
1013    }
1014
1015    pub fn add_moduleresult(&mut self, modulename: String, result: ModuleValidationResult) {
1016        self.moduleresults.insert(modulename, result);
1017        self.update_overall_status();
1018    }
1019
1020    pub fn add_compatibilityresult(&mut self, result: CompatibilityValidationResult) {
1021        self.compatibilityresult = result;
1022        self.update_overall_status();
1023    }
1024
1025    pub fn add_api_stabilityresult(&mut self, result: ApiStabilityResult) {
1026        self.api_stabilityresult = result;
1027        self.update_overall_status();
1028    }
1029
1030    pub fn add_version_consistencyresult(&mut self, result: VersionConsistencyResult) {
1031        self.version_consistencyresult = result;
1032        self.update_overall_status();
1033    }
1034
1035    fn update_overall_status(&mut self) {
1036        let haserrors = self.moduleresults.values().any(|r| !r.errors.is_empty())
1037            || !self.compatibilityresult.incompatibilities.is_empty()
1038            || !self.api_stabilityresult.breakingchanges.is_empty()
1039            || !self.version_consistencyresult.conflicts.is_empty();
1040
1041        let has_warnings = self.moduleresults.values().any(|r| !r.warnings.is_empty());
1042
1043        self.overall_status = if haserrors {
1044            ValidationStatus::Failed
1045        } else if has_warnings {
1046            ValidationStatus::Warning
1047        } else {
1048            ValidationStatus::Passed
1049        };
1050    }
1051
1052    pub fn is_valid(&self) -> bool {
1053        matches!(
1054            self.overall_status,
1055            ValidationStatus::Passed | ValidationStatus::Warning
1056        )
1057    }
1058
1059    pub fn error_count(&self) -> usize {
1060        self.moduleresults
1061            .values()
1062            .map(|r| r.errors.len())
1063            .sum::<usize>()
1064            + self.compatibilityresult.incompatibilities.len()
1065            + self.api_stabilityresult.breakingchanges.len()
1066            + self.version_consistencyresult.conflicts.len()
1067    }
1068
1069    pub fn warning_count(&self) -> usize {
1070        self.moduleresults.values().map(|r| r.warnings.len()).sum()
1071    }
1072}
1073
1074impl Default for EcosystemValidationResult {
1075    fn default() -> Self {
1076        Self::new()
1077    }
1078}
1079
1080#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1081pub enum ValidationStatus {
1082    Unknown,
1083    Passed,
1084    Warning,
1085    Failed,
1086}
1087
1088/// Individual module validation result
1089#[derive(Debug, Clone)]
1090pub struct ModuleValidationResult {
1091    pub modulename: String,
1092    pub errors: Vec<ValidationError>,
1093    pub warnings: Vec<ValidationWarning>,
1094    pub status: ValidationStatus,
1095}
1096
1097impl ModuleValidationResult {
1098    pub fn new(modulename: String) -> Self {
1099        Self {
1100            modulename,
1101            errors: Vec::new(),
1102            warnings: Vec::new(),
1103            status: ValidationStatus::Unknown,
1104        }
1105    }
1106
1107    pub fn adderror(&mut self, error: ValidationError) {
1108        self.errors.push(error);
1109        self.status = ValidationStatus::Failed;
1110    }
1111
1112    pub fn add_warning(&mut self, warning: ValidationWarning) {
1113        self.warnings.push(warning);
1114        if self.status == ValidationStatus::Unknown {
1115            self.status = ValidationStatus::Warning;
1116        }
1117    }
1118
1119    pub fn is_valid(&self) -> bool {
1120        self.errors.is_empty()
1121    }
1122}
1123
1124#[derive(Debug, Clone)]
1125pub struct ValidationError {
1126    pub errortype: ValidationErrorType,
1127    pub message: String,
1128    pub context: Option<String>,
1129}
1130
1131impl ValidationError {
1132    pub fn new(errortype: ValidationErrorType, message: String) -> Self {
1133        Self {
1134            errortype,
1135            message,
1136            context: None,
1137        }
1138    }
1139}
1140
1141#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1142pub enum ValidationErrorType {
1143    InvalidVersion,
1144    DependencyError,
1145    ApiCompatibility,
1146    SecurityViolation,
1147    FeatureConflict,
1148}
1149
1150#[derive(Debug, Clone)]
1151pub struct ValidationWarning {
1152    pub warningtype: ValidationWarningType,
1153    pub message: String,
1154}
1155
1156impl ValidationWarning {
1157    pub fn new(warningtype: ValidationWarningType, message: String) -> Self {
1158        Self {
1159            warningtype,
1160            message,
1161        }
1162    }
1163}
1164
1165#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1166pub enum ValidationWarningType {
1167    FeatureCompatibility,
1168    PerformanceImpact,
1169    DeprecationWarning,
1170}
1171
1172/// Additional validation result types
1173#[derive(Debug, Clone)]
1174pub struct CompatibilityValidationResult {
1175    pub incompatibilities: Vec<String>,
1176}
1177
1178impl CompatibilityValidationResult {
1179    pub fn new() -> Self {
1180        Self {
1181            incompatibilities: Vec::new(),
1182        }
1183    }
1184
1185    pub fn add_incompatibility(&mut self, incompatibility: String) {
1186        self.incompatibilities.push(incompatibility);
1187    }
1188}
1189
1190impl Default for CompatibilityValidationResult {
1191    fn default() -> Self {
1192        Self::new()
1193    }
1194}
1195
1196#[derive(Debug, Clone)]
1197pub struct ApiStabilityResult {
1198    pub breakingchanges: HashMap<String, Vec<String>>,
1199    pub versioning_violations: HashMap<String, String>,
1200}
1201
1202impl ApiStabilityResult {
1203    pub fn new() -> Self {
1204        Self {
1205            breakingchanges: HashMap::new(),
1206            versioning_violations: HashMap::new(),
1207        }
1208    }
1209
1210    pub fn add_breaking_change(&mut self, module: String, changes: Vec<String>) {
1211        self.breakingchanges.insert(module, changes);
1212    }
1213
1214    pub fn add_versioning_violation(&mut self, module: String, violation: String) {
1215        self.versioning_violations.insert(module, violation);
1216    }
1217}
1218
1219impl Default for ApiStabilityResult {
1220    fn default() -> Self {
1221        Self::new()
1222    }
1223}
1224
1225#[derive(Debug, Clone)]
1226pub struct VersionConsistencyResult {
1227    pub conflicts: HashMap<String, Vec<Version>>,
1228    pub dependency_mismatches: Vec<DependencyMismatch>,
1229}
1230
1231impl VersionConsistencyResult {
1232    pub fn new() -> Self {
1233        Self {
1234            conflicts: HashMap::new(),
1235            dependency_mismatches: Vec::new(),
1236        }
1237    }
1238
1239    pub fn add_conflict(&mut self, module: String, versions: Vec<Version>) {
1240        self.conflicts.insert(module, versions);
1241    }
1242
1243    pub fn add_dependency_mismatch(
1244        &mut self,
1245        module: String,
1246        dependency: String,
1247        required: VersionRequirement,
1248        found: Version,
1249    ) {
1250        self.dependency_mismatches.push(DependencyMismatch {
1251            module,
1252            dependency,
1253            required,
1254            found,
1255        });
1256    }
1257}
1258
1259impl Default for VersionConsistencyResult {
1260    fn default() -> Self {
1261        Self::new()
1262    }
1263}
1264
1265#[derive(Debug, Clone)]
1266pub struct DependencyMismatch {
1267    pub module: String,
1268    pub dependency: String,
1269    pub required: VersionRequirement,
1270    pub found: Version,
1271}
1272
1273/// Additional helper types
1274#[derive(Debug, Clone)]
1275pub struct DependencyValidationResult {
1276    pub dependency_name: String,
1277    pub incompatibilities: Vec<String>,
1278}
1279
1280impl DependencyValidationResult {
1281    pub fn new(modulename: String) -> Self {
1282        Self {
1283            dependency_name: modulename,
1284            incompatibilities: Vec::new(),
1285        }
1286    }
1287
1288    pub fn add_incompatibility(&mut self, incompatibility: String) {
1289        self.incompatibilities.push(incompatibility);
1290    }
1291
1292    pub fn is_valid(&self) -> bool {
1293        self.incompatibilities.is_empty()
1294    }
1295}
1296
1297#[derive(Debug, Clone)]
1298pub struct ApiValidationResult {
1299    pub documentation_issues: Vec<String>,
1300    pub semver_violations: Vec<String>,
1301    pub deprecation_issues: HashMap<String, String>,
1302}
1303
1304impl ApiValidationResult {
1305    pub fn new() -> Self {
1306        Self {
1307            documentation_issues: Vec::new(),
1308            semver_violations: Vec::new(),
1309            deprecation_issues: HashMap::new(),
1310        }
1311    }
1312
1313    pub fn name(&mut self, apiname: String) {
1314        self.documentation_issues.push(apiname);
1315    }
1316
1317    pub fn add_documentation_issue(&mut self, apiname: String) {
1318        self.documentation_issues.push(apiname);
1319    }
1320
1321    pub fn name_2(&mut self, apiname: String) {
1322        self.semver_violations.push(apiname);
1323    }
1324
1325    pub fn add_semver_violation(&mut self, apiname: String) {
1326        self.semver_violations.push(apiname);
1327    }
1328
1329    pub fn name_3(&mut self, apiname: String, issue: String) {
1330        self.deprecation_issues.insert(apiname, issue);
1331    }
1332
1333    pub fn add_deprecation_issue(&mut self, apiname: String, issue: String) {
1334        self.deprecation_issues.insert(apiname, issue);
1335    }
1336
1337    pub fn is_valid(&self) -> bool {
1338        self.documentation_issues.is_empty()
1339            && self.semver_violations.is_empty()
1340            && self.deprecation_issues.is_empty()
1341    }
1342}
1343
1344impl Default for ApiValidationResult {
1345    fn default() -> Self {
1346        Self::new()
1347    }
1348}
1349
1350#[derive(Debug, Clone)]
1351pub struct SecurityValidationResult {
1352    pub modulename: String,
1353    pub vulnerabilities: Vec<String>,
1354    pub security_issues: Vec<String>,
1355}
1356
1357impl SecurityValidationResult {
1358    pub fn new(modulename: String) -> Self {
1359        Self {
1360            modulename,
1361            vulnerabilities: Vec::new(),
1362            security_issues: Vec::new(),
1363        }
1364    }
1365
1366    pub fn add_vulnerability(&mut self, vulnerability: String) {
1367        self.vulnerabilities.push(vulnerability);
1368    }
1369
1370    pub fn add_security_issue(&mut self, issue: String) {
1371        self.security_issues.push(issue);
1372    }
1373
1374    pub fn is_secure(&self) -> bool {
1375        self.vulnerabilities.is_empty() && self.security_issues.is_empty()
1376    }
1377}
1378
1379#[derive(Debug, Clone)]
1380pub struct ApiStabilityCheck {
1381    pub is_stable: bool,
1382    pub breakingchanges: Vec<String>,
1383}
1384
1385impl ApiStabilityCheck {
1386    pub fn new(is_stable: bool, breakingchanges: Vec<String>) -> Self {
1387        Self {
1388            is_stable,
1389            breakingchanges,
1390        }
1391    }
1392
1393    pub fn is_stable(&self) -> bool {
1394        self.is_stable
1395    }
1396
1397    pub fn breakingchanges(&self) -> &[String] {
1398        &self.breakingchanges
1399    }
1400
1401    pub fn is_valid(&self) -> bool {
1402        self.is_stable && self.breakingchanges.is_empty()
1403    }
1404}
1405
1406/// Ecosystem health summary
1407#[derive(Debug, Clone)]
1408pub struct EcosystemHealth {
1409    pub overall_status: HealthStatus,
1410    pub module_count: usize,
1411    pub error_count: usize,
1412    pub warning_count: usize,
1413    pub compatibility_score: f64,
1414    pub recommendations: Vec<String>,
1415}
1416
1417#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1418pub enum HealthStatus {
1419    Excellent,
1420    Good,
1421    Fair,
1422    Poor,
1423    Critical,
1424}
1425
1426impl EcosystemHealth {
1427    pub fn from_validationresult(result: &EcosystemValidationResult) -> Self {
1428        let module_count = result.moduleresults.len();
1429        let error_count = result.error_count();
1430        let warning_count = result.warning_count();
1431
1432        let compatibility_score = if module_count == 0 {
1433            1.0
1434        } else {
1435            1.0 - (error_count as f64 / (module_count as f64 * 10.0))
1436        };
1437
1438        let overall_status = match error_count {
1439            0 => {
1440                if warning_count == 0 {
1441                    HealthStatus::Excellent
1442                } else {
1443                    HealthStatus::Good
1444                }
1445            }
1446            1..=5 => HealthStatus::Fair,
1447            6..=15 => HealthStatus::Poor,
1448            _ => HealthStatus::Critical,
1449        };
1450
1451        let recommendations = Self::generate_recommendations(result);
1452
1453        Self {
1454            overall_status,
1455            module_count,
1456            error_count,
1457            warning_count,
1458            compatibility_score: compatibility_score.clamp(0.0, 1.0),
1459            recommendations,
1460        }
1461    }
1462
1463    fn generate_recommendations(result: &EcosystemValidationResult) -> Vec<String> {
1464        let mut recommendations = Vec::new();
1465
1466        if result.error_count() > 0 {
1467            recommendations
1468                .push("Address validation errors before production deployment".to_string());
1469        }
1470
1471        if !result.api_stabilityresult.breakingchanges.is_empty() {
1472            recommendations
1473                .push("Review API breaking changes and update version numbers".to_string());
1474        }
1475
1476        if !result.version_consistencyresult.conflicts.is_empty() {
1477            recommendations.push("Resolve version conflicts between modules".to_string());
1478        }
1479
1480        if result.warning_count() > 10 {
1481            recommendations
1482                .push("Consider addressing warnings to improve ecosystem stability".to_string());
1483        }
1484
1485        recommendations
1486    }
1487}
1488
1489/// Initialize ecosystem validation with detected modules
1490#[allow(dead_code)]
1491pub fn initialize_ecosystem_validation() -> CoreResult<()> {
1492    let validator = EcosystemValidator::global()?;
1493
1494    // Register core modules
1495    validator.register_module(create_core_module_info())?;
1496
1497    // Additional modules would be detected and registered here
1498
1499    Ok(())
1500}
1501
1502#[allow(dead_code)]
1503fn create_core_module_info() -> ModuleInfo {
1504    ModuleInfo {
1505        name: "scirs2-core".to_string(),
1506        version: "1.0.0".to_string(),
1507        dependencies: Vec::new(),
1508        apisurface: ApiSurface {
1509            public_apis: vec![ApiInfo {
1510                name: "validate_ecosystem".to_string(),
1511                signature: "fn validate_ecosystem() -> CoreResult<EcosystemValidationResult>"
1512                    .to_string(),
1513                documentation: "Validates the entire ecosystem compatibility".to_string(),
1514                since_version: Some(Version::new(1, 0, 0)),
1515                stability: ApiStability::Stable,
1516            }],
1517            deprecated_apis: Vec::new(),
1518        },
1519        features: vec!["validation".to_string(), "ecosystem".to_string()],
1520        metadata: ModuleMetadata {
1521            author: "SciRS2 Team".to_string(),
1522            description: "Core utilities for SciRS2 ecosystem".to_string(),
1523            license: "MIT".to_string(),
1524            repository: Some("https://github.com/cool-japan/scirs".to_string()),
1525            build_time: None,
1526        },
1527    }
1528}
1529
1530#[cfg(test)]
1531mod tests {
1532    use super::*;
1533
1534    #[test]
1535    fn test_validator_creation() {
1536        let validator = EcosystemValidator::new().expect("Operation failed");
1537        // Basic functionality test
1538    }
1539
1540    #[test]
1541    fn test_module_registration() {
1542        let validator = EcosystemValidator::new().expect("Operation failed");
1543        let module = create_core_module_info();
1544
1545        validator.register_module(module).expect("Operation failed");
1546
1547        let result = validator
1548            .validate_module("scirs2-core")
1549            .expect("Operation failed");
1550        assert!(result.is_valid());
1551    }
1552
1553    #[test]
1554    fn test_ecosystem_validation() {
1555        let validator = EcosystemValidator::new().expect("Operation failed");
1556        validator
1557            .register_module(create_core_module_info())
1558            .expect("Operation failed");
1559
1560        let result = validator.validate_ecosystem().expect("Operation failed");
1561        assert!(result.is_valid());
1562    }
1563
1564    #[test]
1565    fn test_version_requirement() {
1566        let req = VersionRequirement::new("1.0.0");
1567        let version = Version::new(1, 0, 0);
1568
1569        assert!(req.version(&version));
1570    }
1571
1572    #[test]
1573    fn test_ecosystem_health() {
1574        let mut result = EcosystemValidationResult::new();
1575        result.add_moduleresult(
1576            "test".to_string(),
1577            ModuleValidationResult::new("test".to_string()),
1578        );
1579
1580        let health = EcosystemHealth::from_validationresult(&result);
1581        assert_eq!(health.overall_status, HealthStatus::Excellent);
1582    }
1583}