kailash 0.9.15__py3-none-any.whl → 0.9.17__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. kailash/__init__.py +4 -3
  2. kailash/middleware/database/base_models.py +7 -1
  3. kailash/migration/__init__.py +30 -0
  4. kailash/migration/cli.py +340 -0
  5. kailash/migration/compatibility_checker.py +662 -0
  6. kailash/migration/configuration_validator.py +837 -0
  7. kailash/migration/documentation_generator.py +1828 -0
  8. kailash/migration/examples/__init__.py +5 -0
  9. kailash/migration/examples/complete_migration_example.py +692 -0
  10. kailash/migration/migration_assistant.py +715 -0
  11. kailash/migration/performance_comparator.py +760 -0
  12. kailash/migration/regression_detector.py +1141 -0
  13. kailash/migration/tests/__init__.py +6 -0
  14. kailash/migration/tests/test_compatibility_checker.py +403 -0
  15. kailash/migration/tests/test_integration.py +463 -0
  16. kailash/migration/tests/test_migration_assistant.py +397 -0
  17. kailash/migration/tests/test_performance_comparator.py +433 -0
  18. kailash/monitoring/__init__.py +29 -2
  19. kailash/monitoring/asyncsql_metrics.py +275 -0
  20. kailash/nodes/data/async_sql.py +1828 -33
  21. kailash/runtime/local.py +1255 -8
  22. kailash/runtime/monitoring/__init__.py +1 -0
  23. kailash/runtime/monitoring/runtime_monitor.py +780 -0
  24. kailash/runtime/resource_manager.py +3033 -0
  25. kailash/sdk_exceptions.py +21 -0
  26. kailash/workflow/cyclic_runner.py +18 -2
  27. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/METADATA +1 -1
  28. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/RECORD +33 -14
  29. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/WHEEL +0 -0
  30. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/entry_points.txt +0 -0
  31. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/licenses/LICENSE +0 -0
  32. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/licenses/NOTICE +0 -0
  33. {kailash-0.9.15.dist-info → kailash-0.9.17.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,837 @@
1
+ """Configuration validator for LocalRuntime migration validation.
2
+
3
+ This module provides comprehensive validation of LocalRuntime configurations
4
+ to ensure they are correct, secure, and optimized for the target environment.
5
+ It validates parameters, detects conflicts, and provides optimization recommendations.
6
+ """
7
+
8
+ import json
9
+ import re
10
+ from dataclasses import dataclass, field
11
+ from enum import Enum
12
+ from pathlib import Path
13
+ from typing import Any, Dict, List, Optional, Set, Tuple, Union
14
+
15
+ from kailash.runtime.local import LocalRuntime
16
+
17
+
18
+ class ValidationLevel(Enum):
19
+ """Validation severity levels."""
20
+
21
+ ERROR = "error" # Configuration is invalid/dangerous
22
+ WARNING = "warning" # Configuration may cause issues
23
+ INFO = "info" # Informational/optimization suggestion
24
+ DEBUG = "debug" # Debug information
25
+
26
+
27
+ class ValidationCategory(Enum):
28
+ """Categories of validation checks."""
29
+
30
+ SYNTAX = "syntax" # Basic syntax and type validation
31
+ COMPATIBILITY = "compatibility" # Parameter compatibility
32
+ SECURITY = "security" # Security-related validation
33
+ PERFORMANCE = "performance" # Performance optimization
34
+ RESOURCE = "resource" # Resource management
35
+ ENTERPRISE = "enterprise" # Enterprise features
36
+ BEST_PRACTICE = "best_practice" # Best practice recommendations
37
+
38
+
39
+ @dataclass
40
+ class ValidationIssue:
41
+ """Represents a configuration validation issue."""
42
+
43
+ level: ValidationLevel
44
+ category: ValidationCategory
45
+ parameter: str
46
+ message: str
47
+ suggestion: str
48
+ auto_fixable: bool = False
49
+ enterprise_feature: bool = False
50
+ impact: str = "low" # low, medium, high, critical
51
+
52
+
53
+ @dataclass
54
+ class ValidationResult:
55
+ """Results of configuration validation."""
56
+
57
+ valid: bool
58
+ issues: List[ValidationIssue] = field(default_factory=list)
59
+ optimized_config: Optional[Dict[str, Any]] = None
60
+ security_score: int = 0 # 0-100
61
+ performance_score: int = 0 # 0-100
62
+ enterprise_readiness: int = 0 # 0-100
63
+
64
+
65
+ class ConfigurationValidator:
66
+ """Comprehensive LocalRuntime configuration validator."""
67
+
68
+ def __init__(self):
69
+ """Initialize the configuration validator."""
70
+ # Valid parameter definitions with types and constraints
71
+ self.valid_parameters = {
72
+ "debug": {"type": bool, "default": False},
73
+ "enable_cycles": {"type": bool, "default": True},
74
+ "enable_async": {"type": bool, "default": True},
75
+ "max_concurrency": {"type": int, "min": 1, "max": 1000, "default": 10},
76
+ "user_context": {"type": object, "optional": True},
77
+ "enable_monitoring": {"type": bool, "default": True},
78
+ "enable_security": {"type": bool, "default": False},
79
+ "enable_audit": {"type": bool, "default": False},
80
+ "resource_limits": {"type": dict, "optional": True},
81
+ "secret_provider": {"type": object, "optional": True},
82
+ "connection_validation": {
83
+ "type": str,
84
+ "values": ["strict", "warn", "disable"],
85
+ "default": "warn",
86
+ },
87
+ "conditional_execution": {
88
+ "type": str,
89
+ "values": ["route_data", "skip_node"],
90
+ "default": "route_data",
91
+ },
92
+ "content_aware_success_detection": {"type": bool, "default": True},
93
+ "persistent_mode": {"type": bool, "default": False},
94
+ "enable_connection_sharing": {"type": bool, "default": True},
95
+ "max_concurrent_workflows": {
96
+ "type": int,
97
+ "min": 1,
98
+ "max": 100,
99
+ "default": 10,
100
+ },
101
+ "connection_pool_size": {"type": int, "min": 1, "max": 1000, "default": 20},
102
+ "enable_enterprise_monitoring": {"type": bool, "default": False},
103
+ "enable_health_monitoring": {"type": bool, "default": False},
104
+ "enable_resource_coordination": {"type": bool, "default": True},
105
+ "circuit_breaker_config": {"type": dict, "optional": True},
106
+ "retry_policy_config": {"type": dict, "optional": True},
107
+ "connection_pool_config": {"type": dict, "optional": True},
108
+ }
109
+
110
+ # Deprecated parameters
111
+ self.deprecated_parameters = {
112
+ "enable_parallel": "Use max_concurrency instead",
113
+ "thread_pool_size": "Use max_concurrency instead",
114
+ "memory_limit": "Use resource_limits parameter instead",
115
+ "timeout": "Use resource_limits parameter instead",
116
+ "log_level": "Use debug parameter or logging configuration",
117
+ "cache_enabled": "Use enterprise caching nodes instead",
118
+ "retry_count": "Use retry_policy_config parameter",
119
+ }
120
+
121
+ # Parameter dependencies
122
+ self.parameter_dependencies = {
123
+ "enable_security": ["user_context"],
124
+ "enable_audit": ["enable_security"],
125
+ "enable_enterprise_monitoring": ["enable_monitoring"],
126
+ "persistent_mode": ["enable_connection_sharing"],
127
+ "circuit_breaker_config": ["enable_resource_coordination"],
128
+ "retry_policy_config": ["enable_resource_coordination"],
129
+ }
130
+
131
+ # Conflicting parameters
132
+ self.parameter_conflicts = {
133
+ ("debug", True): [
134
+ ("enable_security", True)
135
+ ], # Debug mode conflicts with security
136
+ }
137
+
138
+ # Security validations
139
+ self.security_validations = [
140
+ self._validate_debug_security_conflict,
141
+ self._validate_audit_requirements,
142
+ self._validate_user_context_security,
143
+ self._validate_connection_security,
144
+ ]
145
+
146
+ # Performance validations
147
+ self.performance_validations = [
148
+ self._validate_concurrency_settings,
149
+ self._validate_resource_limits,
150
+ self._validate_connection_pooling,
151
+ self._validate_monitoring_overhead,
152
+ ]
153
+
154
+ # Enterprise validations
155
+ self.enterprise_validations = [
156
+ self._validate_enterprise_features,
157
+ self._validate_monitoring_configuration,
158
+ self._validate_resilience_configuration,
159
+ ]
160
+
161
+ def validate_configuration(self, config: Dict[str, Any]) -> ValidationResult:
162
+ """Validate a LocalRuntime configuration.
163
+
164
+ Args:
165
+ config: Configuration dictionary to validate
166
+
167
+ Returns:
168
+ Comprehensive validation results
169
+ """
170
+ result = ValidationResult(valid=True, issues=[])
171
+
172
+ # Basic syntax validation
173
+ self._validate_syntax(config, result)
174
+
175
+ # Parameter validation
176
+ self._validate_parameters(config, result)
177
+
178
+ # Dependency validation
179
+ self._validate_dependencies(config, result)
180
+
181
+ # Conflict validation
182
+ self._validate_conflicts(config, result)
183
+
184
+ # Security validation
185
+ for validator in self.security_validations:
186
+ validator(config, result)
187
+
188
+ # Performance validation
189
+ for validator in self.performance_validations:
190
+ validator(config, result)
191
+
192
+ # Enterprise validation
193
+ for validator in self.enterprise_validations:
194
+ validator(config, result)
195
+
196
+ # Generate optimized configuration
197
+ result.optimized_config = self._generate_optimized_config(config, result)
198
+
199
+ # Calculate scores
200
+ self._calculate_scores(result)
201
+
202
+ # Determine overall validity
203
+ error_issues = [i for i in result.issues if i.level == ValidationLevel.ERROR]
204
+ result.valid = len(error_issues) == 0
205
+
206
+ return result
207
+
208
+ def _validate_syntax(
209
+ self, config: Dict[str, Any], result: ValidationResult
210
+ ) -> None:
211
+ """Validate basic syntax and structure."""
212
+ if not isinstance(config, dict):
213
+ result.issues.append(
214
+ ValidationIssue(
215
+ level=ValidationLevel.ERROR,
216
+ category=ValidationCategory.SYNTAX,
217
+ parameter="config",
218
+ message="Configuration must be a dictionary",
219
+ suggestion="Ensure configuration is passed as a dictionary",
220
+ impact="critical",
221
+ )
222
+ )
223
+ return
224
+
225
+ # Check for invalid parameter names
226
+ for param_name in config.keys():
227
+ if (
228
+ param_name not in self.valid_parameters
229
+ and param_name not in self.deprecated_parameters
230
+ ):
231
+ result.issues.append(
232
+ ValidationIssue(
233
+ level=ValidationLevel.WARNING,
234
+ category=ValidationCategory.SYNTAX,
235
+ parameter=param_name,
236
+ message=f"Unknown parameter '{param_name}'",
237
+ suggestion="Remove unknown parameter or check spelling",
238
+ impact="medium",
239
+ )
240
+ )
241
+
242
+ def _validate_parameters(
243
+ self, config: Dict[str, Any], result: ValidationResult
244
+ ) -> None:
245
+ """Validate individual parameters."""
246
+ for param_name, param_value in config.items():
247
+ # Check deprecated parameters
248
+ if param_name in self.deprecated_parameters:
249
+ result.issues.append(
250
+ ValidationIssue(
251
+ level=ValidationLevel.WARNING,
252
+ category=ValidationCategory.COMPATIBILITY,
253
+ parameter=param_name,
254
+ message=f"Parameter '{param_name}' is deprecated",
255
+ suggestion=self.deprecated_parameters[param_name],
256
+ auto_fixable=True,
257
+ impact="medium",
258
+ )
259
+ )
260
+ continue
261
+
262
+ # Validate known parameters
263
+ if param_name in self.valid_parameters:
264
+ param_def = self.valid_parameters[param_name]
265
+
266
+ # Type validation
267
+ expected_type = param_def["type"]
268
+ if expected_type != object and not isinstance(
269
+ param_value, expected_type
270
+ ):
271
+ result.issues.append(
272
+ ValidationIssue(
273
+ level=ValidationLevel.ERROR,
274
+ category=ValidationCategory.SYNTAX,
275
+ parameter=param_name,
276
+ message=f"Parameter '{param_name}' must be of type {expected_type.__name__}, got {type(param_value).__name__}",
277
+ suggestion=f"Convert value to {expected_type.__name__}",
278
+ impact="high",
279
+ )
280
+ )
281
+
282
+ # Range validation for integers
283
+ if expected_type == int and isinstance(param_value, int):
284
+ if "min" in param_def and param_value < param_def["min"]:
285
+ result.issues.append(
286
+ ValidationIssue(
287
+ level=ValidationLevel.ERROR,
288
+ category=ValidationCategory.SYNTAX,
289
+ parameter=param_name,
290
+ message=f"Parameter '{param_name}' value {param_value} is below minimum {param_def['min']}",
291
+ suggestion=f"Set value to at least {param_def['min']}",
292
+ impact="high",
293
+ )
294
+ )
295
+
296
+ if "max" in param_def and param_value > param_def["max"]:
297
+ result.issues.append(
298
+ ValidationIssue(
299
+ level=ValidationLevel.WARNING,
300
+ category=ValidationCategory.PERFORMANCE,
301
+ parameter=param_name,
302
+ message=f"Parameter '{param_name}' value {param_value} is above recommended maximum {param_def['max']}",
303
+ suggestion=f"Consider reducing to {param_def['max']} or below",
304
+ impact="medium",
305
+ )
306
+ )
307
+
308
+ # Value validation for strings with restricted values
309
+ if "values" in param_def and param_value not in param_def["values"]:
310
+ result.issues.append(
311
+ ValidationIssue(
312
+ level=ValidationLevel.ERROR,
313
+ category=ValidationCategory.SYNTAX,
314
+ parameter=param_name,
315
+ message=f"Parameter '{param_name}' value '{param_value}' is not valid. Valid values: {param_def['values']}",
316
+ suggestion=f"Use one of: {', '.join(param_def['values'])}",
317
+ impact="high",
318
+ )
319
+ )
320
+
321
+ def _validate_dependencies(
322
+ self, config: Dict[str, Any], result: ValidationResult
323
+ ) -> None:
324
+ """Validate parameter dependencies."""
325
+ for param_name, dependencies in self.parameter_dependencies.items():
326
+ if config.get(param_name):
327
+ for dep_param in dependencies:
328
+ if not config.get(dep_param):
329
+ result.issues.append(
330
+ ValidationIssue(
331
+ level=ValidationLevel.WARNING,
332
+ category=ValidationCategory.COMPATIBILITY,
333
+ parameter=param_name,
334
+ message=f"Parameter '{param_name}' requires '{dep_param}' to be set",
335
+ suggestion=f"Set '{dep_param}' parameter or disable '{param_name}'",
336
+ impact="medium",
337
+ )
338
+ )
339
+
340
+ def _validate_conflicts(
341
+ self, config: Dict[str, Any], result: ValidationResult
342
+ ) -> None:
343
+ """Validate parameter conflicts."""
344
+ for conflict_param, conflict_conditions in self.parameter_conflicts.items():
345
+ param_name, param_value = conflict_param
346
+
347
+ if config.get(param_name) == param_value:
348
+ for conflict_condition in conflict_conditions:
349
+ conflict_name, conflict_value = conflict_condition
350
+ if config.get(conflict_name) == conflict_value:
351
+ result.issues.append(
352
+ ValidationIssue(
353
+ level=ValidationLevel.WARNING,
354
+ category=ValidationCategory.SECURITY,
355
+ parameter=param_name,
356
+ message=f"Parameter '{param_name}={param_value}' conflicts with '{conflict_name}={conflict_value}'",
357
+ suggestion=f"Disable either '{param_name}' or '{conflict_name}' to resolve conflict",
358
+ impact="medium",
359
+ )
360
+ )
361
+
362
+ def _validate_debug_security_conflict(
363
+ self, config: Dict[str, Any], result: ValidationResult
364
+ ) -> None:
365
+ """Validate debug and security configuration conflicts."""
366
+ if config.get("debug") and config.get("enable_security"):
367
+ result.issues.append(
368
+ ValidationIssue(
369
+ level=ValidationLevel.WARNING,
370
+ category=ValidationCategory.SECURITY,
371
+ parameter="debug",
372
+ message="Debug mode enabled with security features may expose sensitive information",
373
+ suggestion="Disable debug mode in production or when security is enabled",
374
+ impact="high",
375
+ )
376
+ )
377
+
378
+ def _validate_audit_requirements(
379
+ self, config: Dict[str, Any], result: ValidationResult
380
+ ) -> None:
381
+ """Validate audit logging requirements."""
382
+ if config.get("enable_audit") and not config.get("enable_security"):
383
+ result.issues.append(
384
+ ValidationIssue(
385
+ level=ValidationLevel.ERROR,
386
+ category=ValidationCategory.SECURITY,
387
+ parameter="enable_audit",
388
+ message="Audit logging requires security features to be enabled",
389
+ suggestion="Enable security with 'enable_security=True'",
390
+ auto_fixable=True,
391
+ impact="high",
392
+ )
393
+ )
394
+
395
+ def _validate_user_context_security(
396
+ self, config: Dict[str, Any], result: ValidationResult
397
+ ) -> None:
398
+ """Validate user context security configuration."""
399
+ if config.get("user_context") and not config.get("enable_security"):
400
+ result.issues.append(
401
+ ValidationIssue(
402
+ level=ValidationLevel.INFO,
403
+ category=ValidationCategory.SECURITY,
404
+ parameter="user_context",
405
+ message="User context provided but security features are disabled",
406
+ suggestion="Enable security with 'enable_security=True' to utilize user context",
407
+ enterprise_feature=True,
408
+ impact="low",
409
+ )
410
+ )
411
+
412
+ def _validate_connection_security(
413
+ self, config: Dict[str, Any], result: ValidationResult
414
+ ) -> None:
415
+ """Validate connection security settings."""
416
+ connection_validation = config.get("connection_validation", "warn")
417
+ if connection_validation == "disable":
418
+ result.issues.append(
419
+ ValidationIssue(
420
+ level=ValidationLevel.WARNING,
421
+ category=ValidationCategory.SECURITY,
422
+ parameter="connection_validation",
423
+ message="Connection validation is disabled, which may allow invalid connections",
424
+ suggestion="Use 'warn' or 'strict' for better security",
425
+ impact="medium",
426
+ )
427
+ )
428
+
429
+ def _validate_concurrency_settings(
430
+ self, config: Dict[str, Any], result: ValidationResult
431
+ ) -> None:
432
+ """Validate concurrency and performance settings."""
433
+ max_concurrency = config.get("max_concurrency", 10)
434
+ max_workflows = config.get("max_concurrent_workflows", 10)
435
+ pool_size = config.get("connection_pool_size", 20)
436
+
437
+ # Check for reasonable concurrency settings
438
+ if max_concurrency > 50:
439
+ result.issues.append(
440
+ ValidationIssue(
441
+ level=ValidationLevel.WARNING,
442
+ category=ValidationCategory.PERFORMANCE,
443
+ parameter="max_concurrency",
444
+ message=f"High concurrency setting ({max_concurrency}) may cause resource contention",
445
+ suggestion="Consider reducing concurrency or increasing resource limits",
446
+ impact="medium",
447
+ )
448
+ )
449
+
450
+ # Check workflow to concurrency ratio
451
+ if max_workflows > max_concurrency * 5:
452
+ result.issues.append(
453
+ ValidationIssue(
454
+ level=ValidationLevel.INFO,
455
+ category=ValidationCategory.PERFORMANCE,
456
+ parameter="max_concurrent_workflows",
457
+ message="High workflow concurrency relative to node concurrency",
458
+ suggestion="Consider increasing max_concurrency or reducing max_concurrent_workflows",
459
+ impact="low",
460
+ )
461
+ )
462
+
463
+ # Check connection pool sizing
464
+ if pool_size < max_concurrency:
465
+ result.issues.append(
466
+ ValidationIssue(
467
+ level=ValidationLevel.WARNING,
468
+ category=ValidationCategory.PERFORMANCE,
469
+ parameter="connection_pool_size",
470
+ message="Connection pool size is smaller than max concurrency",
471
+ suggestion=f"Increase connection_pool_size to at least {max_concurrency}",
472
+ auto_fixable=True,
473
+ impact="medium",
474
+ )
475
+ )
476
+
477
+ def _validate_resource_limits(
478
+ self, config: Dict[str, Any], result: ValidationResult
479
+ ) -> None:
480
+ """Validate resource limit configurations."""
481
+ resource_limits = config.get("resource_limits", {})
482
+
483
+ if isinstance(resource_limits, dict):
484
+ # Validate memory limits
485
+ if "memory_mb" in resource_limits:
486
+ memory_mb = resource_limits["memory_mb"]
487
+ if memory_mb < 256:
488
+ result.issues.append(
489
+ ValidationIssue(
490
+ level=ValidationLevel.WARNING,
491
+ category=ValidationCategory.RESOURCE,
492
+ parameter="resource_limits.memory_mb",
493
+ message=f"Low memory limit ({memory_mb}MB) may cause performance issues",
494
+ suggestion="Consider increasing memory limit to at least 512MB",
495
+ impact="medium",
496
+ )
497
+ )
498
+
499
+ # Validate timeout settings
500
+ if "timeout_seconds" in resource_limits:
501
+ timeout = resource_limits["timeout_seconds"]
502
+ if timeout > 3600: # 1 hour
503
+ result.issues.append(
504
+ ValidationIssue(
505
+ level=ValidationLevel.INFO,
506
+ category=ValidationCategory.RESOURCE,
507
+ parameter="resource_limits.timeout_seconds",
508
+ message=f"Very high timeout setting ({timeout}s)",
509
+ suggestion="Consider if such a long timeout is necessary",
510
+ impact="low",
511
+ )
512
+ )
513
+
514
+ def _validate_connection_pooling(
515
+ self, config: Dict[str, Any], result: ValidationResult
516
+ ) -> None:
517
+ """Validate connection pooling configuration."""
518
+ enable_sharing = config.get("enable_connection_sharing", True)
519
+ persistent_mode = config.get("persistent_mode", False)
520
+
521
+ if persistent_mode and not enable_sharing:
522
+ result.issues.append(
523
+ ValidationIssue(
524
+ level=ValidationLevel.WARNING,
525
+ category=ValidationCategory.PERFORMANCE,
526
+ parameter="enable_connection_sharing",
527
+ message="Persistent mode without connection sharing reduces efficiency",
528
+ suggestion="Enable connection sharing for better performance in persistent mode",
529
+ auto_fixable=True,
530
+ impact="medium",
531
+ )
532
+ )
533
+
534
+ def _validate_monitoring_overhead(
535
+ self, config: Dict[str, Any], result: ValidationResult
536
+ ) -> None:
537
+ """Validate monitoring configuration for performance impact."""
538
+ monitoring_features = [
539
+ "enable_monitoring",
540
+ "enable_enterprise_monitoring",
541
+ "enable_health_monitoring",
542
+ ]
543
+
544
+ enabled_monitoring = [f for f in monitoring_features if config.get(f)]
545
+
546
+ if len(enabled_monitoring) > 2:
547
+ result.issues.append(
548
+ ValidationIssue(
549
+ level=ValidationLevel.INFO,
550
+ category=ValidationCategory.PERFORMANCE,
551
+ parameter="monitoring",
552
+ message="Multiple monitoring features enabled may impact performance",
553
+ suggestion="Consider enabling only necessary monitoring features for production",
554
+ impact="low",
555
+ )
556
+ )
557
+
558
+ def _validate_enterprise_features(
559
+ self, config: Dict[str, Any], result: ValidationResult
560
+ ) -> None:
561
+ """Validate enterprise feature configurations."""
562
+ enterprise_features = [
563
+ "enable_security",
564
+ "enable_audit",
565
+ "enable_enterprise_monitoring",
566
+ "enable_health_monitoring",
567
+ "user_context",
568
+ ]
569
+
570
+ enabled_features = [f for f in enterprise_features if config.get(f)]
571
+
572
+ if len(enabled_features) > 0:
573
+ result.issues.append(
574
+ ValidationIssue(
575
+ level=ValidationLevel.INFO,
576
+ category=ValidationCategory.ENTERPRISE,
577
+ parameter="enterprise_features",
578
+ message=f"Enterprise features detected: {', '.join(enabled_features)}",
579
+ suggestion="Ensure enterprise license and proper configuration for production use",
580
+ enterprise_feature=True,
581
+ impact="low",
582
+ )
583
+ )
584
+
585
+ def _validate_monitoring_configuration(
586
+ self, config: Dict[str, Any], result: ValidationResult
587
+ ) -> None:
588
+ """Validate monitoring configuration completeness."""
589
+ if config.get("enable_enterprise_monitoring") and not config.get(
590
+ "enable_monitoring"
591
+ ):
592
+ result.issues.append(
593
+ ValidationIssue(
594
+ level=ValidationLevel.ERROR,
595
+ category=ValidationCategory.ENTERPRISE,
596
+ parameter="enable_enterprise_monitoring",
597
+ message="Enterprise monitoring requires basic monitoring to be enabled",
598
+ suggestion="Enable basic monitoring with 'enable_monitoring=True'",
599
+ auto_fixable=True,
600
+ impact="high",
601
+ )
602
+ )
603
+
604
+ def _validate_resilience_configuration(
605
+ self, config: Dict[str, Any], result: ValidationResult
606
+ ) -> None:
607
+ """Validate resilience and reliability configurations."""
608
+ circuit_breaker = config.get("circuit_breaker_config")
609
+ retry_policy = config.get("retry_policy_config")
610
+ resource_coordination = config.get("enable_resource_coordination", True)
611
+
612
+ if (circuit_breaker or retry_policy) and not resource_coordination:
613
+ result.issues.append(
614
+ ValidationIssue(
615
+ level=ValidationLevel.WARNING,
616
+ category=ValidationCategory.ENTERPRISE,
617
+ parameter="enable_resource_coordination",
618
+ message="Resilience features require resource coordination to be enabled",
619
+ suggestion="Enable resource coordination for circuit breaker and retry policies",
620
+ auto_fixable=True,
621
+ enterprise_feature=True,
622
+ impact="medium",
623
+ )
624
+ )
625
+
626
+ def _generate_optimized_config(
627
+ self, config: Dict[str, Any], result: ValidationResult
628
+ ) -> Dict[str, Any]:
629
+ """Generate an optimized configuration based on validation results."""
630
+ optimized = config.copy()
631
+
632
+ # Apply auto-fixable improvements
633
+ for issue in result.issues:
634
+ if issue.auto_fixable:
635
+ if issue.parameter == "connection_pool_size":
636
+ max_concurrency = config.get("max_concurrency", 10)
637
+ optimized["connection_pool_size"] = max(
638
+ optimized.get("connection_pool_size", 20), max_concurrency
639
+ )
640
+
641
+ elif issue.parameter == "enable_monitoring" and config.get(
642
+ "enable_enterprise_monitoring"
643
+ ):
644
+ optimized["enable_monitoring"] = True
645
+
646
+ elif issue.parameter == "enable_security" and config.get(
647
+ "enable_audit"
648
+ ):
649
+ optimized["enable_security"] = True
650
+
651
+ elif issue.parameter == "enable_connection_sharing" and config.get(
652
+ "persistent_mode"
653
+ ):
654
+ optimized["enable_connection_sharing"] = True
655
+
656
+ elif issue.parameter == "enable_resource_coordination" and (
657
+ config.get("circuit_breaker_config")
658
+ or config.get("retry_policy_config")
659
+ ):
660
+ optimized["enable_resource_coordination"] = True
661
+
662
+ return optimized
663
+
664
+ def _calculate_scores(self, result: ValidationResult) -> None:
665
+ """Calculate security, performance, and enterprise readiness scores."""
666
+ total_issues = len(result.issues)
667
+ error_count = len(
668
+ [i for i in result.issues if i.level == ValidationLevel.ERROR]
669
+ )
670
+ warning_count = len(
671
+ [i for i in result.issues if i.level == ValidationLevel.WARNING]
672
+ )
673
+
674
+ # Security score (0-100)
675
+ security_issues = [
676
+ i for i in result.issues if i.category == ValidationCategory.SECURITY
677
+ ]
678
+ security_deduction = len(security_issues) * 10
679
+ result.security_score = max(0, 100 - security_deduction)
680
+
681
+ # Performance score (0-100)
682
+ performance_issues = [
683
+ i for i in result.issues if i.category == ValidationCategory.PERFORMANCE
684
+ ]
685
+ performance_deduction = len(performance_issues) * 15
686
+ result.performance_score = max(0, 100 - performance_deduction)
687
+
688
+ # Enterprise readiness score (0-100)
689
+ enterprise_features = len([i for i in result.issues if i.enterprise_feature])
690
+ enterprise_issues = [
691
+ i
692
+ for i in result.issues
693
+ if i.category == ValidationCategory.ENTERPRISE
694
+ and i.level in [ValidationLevel.ERROR, ValidationLevel.WARNING]
695
+ ]
696
+
697
+ base_score = 50 if enterprise_features > 0 else 20
698
+ enterprise_deduction = len(enterprise_issues) * 20
699
+ result.enterprise_readiness = max(
700
+ 0, base_score + (enterprise_features * 10) - enterprise_deduction
701
+ )
702
+
703
+ def generate_validation_report(
704
+ self, result: ValidationResult, output_format: str = "text"
705
+ ) -> str:
706
+ """Generate a comprehensive validation report.
707
+
708
+ Args:
709
+ result: Validation results
710
+ output_format: Report format ("text", "json", "markdown")
711
+
712
+ Returns:
713
+ Formatted validation report
714
+ """
715
+ if output_format == "json":
716
+ return self._generate_json_report(result)
717
+ elif output_format == "markdown":
718
+ return self._generate_markdown_report(result)
719
+ else:
720
+ return self._generate_text_report(result)
721
+
722
+ def _generate_text_report(self, result: ValidationResult) -> str:
723
+ """Generate text format validation report."""
724
+ lines = []
725
+ lines.append("=" * 60)
726
+ lines.append("LocalRuntime Configuration Validation Report")
727
+ lines.append("=" * 60)
728
+ lines.append("")
729
+
730
+ # Summary
731
+ lines.append("VALIDATION SUMMARY")
732
+ lines.append("-" * 20)
733
+ lines.append(f"Configuration Valid: {'Yes' if result.valid else 'No'}")
734
+ lines.append(f"Total Issues: {len(result.issues)}")
735
+ lines.append(f"Security Score: {result.security_score}/100")
736
+ lines.append(f"Performance Score: {result.performance_score}/100")
737
+ lines.append(f"Enterprise Readiness: {result.enterprise_readiness}/100")
738
+ lines.append("")
739
+
740
+ # Issues by level
741
+ for level in ValidationLevel:
742
+ level_issues = [i for i in result.issues if i.level == level]
743
+ if level_issues:
744
+ lines.append(f"{level.value.upper()} ISSUES ({len(level_issues)})")
745
+ lines.append("-" * (len(level.value) + 15))
746
+
747
+ for issue in level_issues:
748
+ lines.append(f"• {issue.message}")
749
+ lines.append(f" Parameter: {issue.parameter}")
750
+ lines.append(f" Category: {issue.category.value}")
751
+ lines.append(f" Suggestion: {issue.suggestion}")
752
+ if issue.auto_fixable:
753
+ lines.append(" Auto-fixable: Yes")
754
+ lines.append("")
755
+
756
+ return "\n".join(lines)
757
+
758
+ def _generate_json_report(self, result: ValidationResult) -> str:
759
+ """Generate JSON format validation report."""
760
+ data = {
761
+ "valid": result.valid,
762
+ "scores": {
763
+ "security": result.security_score,
764
+ "performance": result.performance_score,
765
+ "enterprise_readiness": result.enterprise_readiness,
766
+ },
767
+ "issues": [
768
+ {
769
+ "level": issue.level.value,
770
+ "category": issue.category.value,
771
+ "parameter": issue.parameter,
772
+ "message": issue.message,
773
+ "suggestion": issue.suggestion,
774
+ "auto_fixable": issue.auto_fixable,
775
+ "enterprise_feature": issue.enterprise_feature,
776
+ "impact": issue.impact,
777
+ }
778
+ for issue in result.issues
779
+ ],
780
+ "optimized_config": result.optimized_config,
781
+ }
782
+
783
+ return json.dumps(data, indent=2)
784
+
785
+ def _generate_markdown_report(self, result: ValidationResult) -> str:
786
+ """Generate markdown format validation report."""
787
+ lines = []
788
+ lines.append("# LocalRuntime Configuration Validation Report")
789
+ lines.append("")
790
+
791
+ # Summary
792
+ lines.append("## Summary")
793
+ lines.append("")
794
+ lines.append("| Metric | Score |")
795
+ lines.append("|--------|-------|")
796
+ lines.append(
797
+ f"| Configuration Valid | {'✅ Yes' if result.valid else '❌ No'} |"
798
+ )
799
+ lines.append(f"| Total Issues | {len(result.issues)} |")
800
+ lines.append(f"| Security Score | {result.security_score}/100 |")
801
+ lines.append(f"| Performance Score | {result.performance_score}/100 |")
802
+ lines.append(f"| Enterprise Readiness | {result.enterprise_readiness}/100 |")
803
+ lines.append("")
804
+
805
+ # Issues
806
+ if result.issues:
807
+ lines.append("## Issues")
808
+ lines.append("")
809
+
810
+ for level in ValidationLevel:
811
+ level_issues = [i for i in result.issues if i.level == level]
812
+ if level_issues:
813
+ level_emoji = {
814
+ ValidationLevel.ERROR: "🚨",
815
+ ValidationLevel.WARNING: "⚠️",
816
+ ValidationLevel.INFO: "ℹ️",
817
+ ValidationLevel.DEBUG: "🔍",
818
+ }
819
+
820
+ lines.append(
821
+ f"### {level_emoji.get(level, '')} {level.value.title()} Issues"
822
+ )
823
+ lines.append("")
824
+
825
+ for issue in level_issues:
826
+ lines.append(f"**{issue.parameter}**: {issue.message}")
827
+ lines.append("")
828
+ lines.append(f"- **Suggestion**: {issue.suggestion}")
829
+ lines.append(f"- **Category**: {issue.category.value}")
830
+ lines.append(f"- **Impact**: {issue.impact}")
831
+ if issue.auto_fixable:
832
+ lines.append("- **Auto-fixable**: ✅ Yes")
833
+ if issue.enterprise_feature:
834
+ lines.append("- **Enterprise Feature**: 🏢 Yes")
835
+ lines.append("")
836
+
837
+ return "\n".join(lines)