runbooks 1.1.3__py3-none-any.whl → 1.1.5__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 (247) hide show
  1. runbooks/__init__.py +31 -2
  2. runbooks/__init___optimized.py +18 -4
  3. runbooks/_platform/__init__.py +1 -5
  4. runbooks/_platform/core/runbooks_wrapper.py +141 -138
  5. runbooks/aws2/accuracy_validator.py +812 -0
  6. runbooks/base.py +7 -0
  7. runbooks/cfat/WEIGHT_CONFIG_README.md +1 -1
  8. runbooks/cfat/assessment/compliance.py +8 -8
  9. runbooks/cfat/assessment/runner.py +1 -0
  10. runbooks/cfat/cloud_foundations_assessment.py +227 -239
  11. runbooks/cfat/models.py +6 -2
  12. runbooks/cfat/tests/__init__.py +6 -1
  13. runbooks/cli/__init__.py +13 -0
  14. runbooks/cli/commands/cfat.py +274 -0
  15. runbooks/cli/commands/finops.py +1164 -0
  16. runbooks/cli/commands/inventory.py +379 -0
  17. runbooks/cli/commands/operate.py +239 -0
  18. runbooks/cli/commands/security.py +248 -0
  19. runbooks/cli/commands/validation.py +825 -0
  20. runbooks/cli/commands/vpc.py +310 -0
  21. runbooks/cli/registry.py +107 -0
  22. runbooks/cloudops/__init__.py +23 -30
  23. runbooks/cloudops/base.py +96 -107
  24. runbooks/cloudops/cost_optimizer.py +549 -547
  25. runbooks/cloudops/infrastructure_optimizer.py +5 -4
  26. runbooks/cloudops/interfaces.py +226 -227
  27. runbooks/cloudops/lifecycle_manager.py +5 -4
  28. runbooks/cloudops/mcp_cost_validation.py +252 -235
  29. runbooks/cloudops/models.py +78 -53
  30. runbooks/cloudops/monitoring_automation.py +5 -4
  31. runbooks/cloudops/notebook_framework.py +179 -215
  32. runbooks/cloudops/security_enforcer.py +125 -159
  33. runbooks/common/accuracy_validator.py +11 -0
  34. runbooks/common/aws_pricing.py +349 -326
  35. runbooks/common/aws_pricing_api.py +211 -212
  36. runbooks/common/aws_profile_manager.py +341 -0
  37. runbooks/common/aws_utils.py +75 -80
  38. runbooks/common/business_logic.py +127 -105
  39. runbooks/common/cli_decorators.py +36 -60
  40. runbooks/common/comprehensive_cost_explorer_integration.py +456 -464
  41. runbooks/common/cross_account_manager.py +198 -205
  42. runbooks/common/date_utils.py +27 -39
  43. runbooks/common/decorators.py +235 -0
  44. runbooks/common/dry_run_examples.py +173 -208
  45. runbooks/common/dry_run_framework.py +157 -155
  46. runbooks/common/enhanced_exception_handler.py +15 -4
  47. runbooks/common/enhanced_logging_example.py +50 -64
  48. runbooks/common/enhanced_logging_integration_example.py +65 -37
  49. runbooks/common/env_utils.py +16 -16
  50. runbooks/common/error_handling.py +40 -38
  51. runbooks/common/lazy_loader.py +41 -23
  52. runbooks/common/logging_integration_helper.py +79 -86
  53. runbooks/common/mcp_cost_explorer_integration.py +478 -495
  54. runbooks/common/mcp_integration.py +63 -74
  55. runbooks/common/memory_optimization.py +140 -118
  56. runbooks/common/module_cli_base.py +37 -58
  57. runbooks/common/organizations_client.py +176 -194
  58. runbooks/common/patterns.py +204 -0
  59. runbooks/common/performance_monitoring.py +67 -71
  60. runbooks/common/performance_optimization_engine.py +283 -274
  61. runbooks/common/profile_utils.py +248 -39
  62. runbooks/common/rich_utils.py +643 -92
  63. runbooks/common/sre_performance_suite.py +177 -186
  64. runbooks/enterprise/__init__.py +1 -1
  65. runbooks/enterprise/logging.py +144 -106
  66. runbooks/enterprise/security.py +187 -204
  67. runbooks/enterprise/validation.py +43 -56
  68. runbooks/finops/__init__.py +29 -33
  69. runbooks/finops/account_resolver.py +1 -1
  70. runbooks/finops/advanced_optimization_engine.py +980 -0
  71. runbooks/finops/automation_core.py +268 -231
  72. runbooks/finops/business_case_config.py +184 -179
  73. runbooks/finops/cli.py +660 -139
  74. runbooks/finops/commvault_ec2_analysis.py +157 -164
  75. runbooks/finops/compute_cost_optimizer.py +336 -320
  76. runbooks/finops/config.py +20 -20
  77. runbooks/finops/cost_optimizer.py +488 -622
  78. runbooks/finops/cost_processor.py +332 -214
  79. runbooks/finops/dashboard_runner.py +1006 -172
  80. runbooks/finops/ebs_cost_optimizer.py +991 -657
  81. runbooks/finops/elastic_ip_optimizer.py +317 -257
  82. runbooks/finops/enhanced_mcp_integration.py +340 -0
  83. runbooks/finops/enhanced_progress.py +40 -37
  84. runbooks/finops/enhanced_trend_visualization.py +3 -2
  85. runbooks/finops/enterprise_wrappers.py +230 -292
  86. runbooks/finops/executive_export.py +203 -160
  87. runbooks/finops/helpers.py +130 -288
  88. runbooks/finops/iam_guidance.py +1 -1
  89. runbooks/finops/infrastructure/__init__.py +80 -0
  90. runbooks/finops/infrastructure/commands.py +506 -0
  91. runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
  92. runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
  93. runbooks/finops/markdown_exporter.py +338 -175
  94. runbooks/finops/mcp_validator.py +1952 -0
  95. runbooks/finops/nat_gateway_optimizer.py +1513 -482
  96. runbooks/finops/network_cost_optimizer.py +657 -587
  97. runbooks/finops/notebook_utils.py +226 -188
  98. runbooks/finops/optimization_engine.py +1136 -0
  99. runbooks/finops/optimizer.py +25 -29
  100. runbooks/finops/rds_snapshot_optimizer.py +367 -411
  101. runbooks/finops/reservation_optimizer.py +427 -363
  102. runbooks/finops/scenario_cli_integration.py +77 -78
  103. runbooks/finops/scenarios.py +1278 -439
  104. runbooks/finops/schemas.py +218 -182
  105. runbooks/finops/snapshot_manager.py +2289 -0
  106. runbooks/finops/tests/test_finops_dashboard.py +3 -3
  107. runbooks/finops/tests/test_reference_images_validation.py +2 -2
  108. runbooks/finops/tests/test_single_account_features.py +17 -17
  109. runbooks/finops/tests/validate_test_suite.py +1 -1
  110. runbooks/finops/types.py +3 -3
  111. runbooks/finops/validation_framework.py +263 -269
  112. runbooks/finops/vpc_cleanup_exporter.py +191 -146
  113. runbooks/finops/vpc_cleanup_optimizer.py +593 -575
  114. runbooks/finops/workspaces_analyzer.py +171 -182
  115. runbooks/hitl/enhanced_workflow_engine.py +1 -1
  116. runbooks/integration/__init__.py +89 -0
  117. runbooks/integration/mcp_integration.py +1920 -0
  118. runbooks/inventory/CLAUDE.md +816 -0
  119. runbooks/inventory/README.md +3 -3
  120. runbooks/inventory/Tests/common_test_data.py +30 -30
  121. runbooks/inventory/__init__.py +2 -2
  122. runbooks/inventory/cloud_foundations_integration.py +144 -149
  123. runbooks/inventory/collectors/aws_comprehensive.py +28 -11
  124. runbooks/inventory/collectors/aws_networking.py +111 -101
  125. runbooks/inventory/collectors/base.py +4 -0
  126. runbooks/inventory/core/collector.py +495 -313
  127. runbooks/inventory/discovery.md +2 -2
  128. runbooks/inventory/drift_detection_cli.py +69 -96
  129. runbooks/inventory/find_ec2_security_groups.py +1 -1
  130. runbooks/inventory/inventory_mcp_cli.py +48 -46
  131. runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
  132. runbooks/inventory/mcp_inventory_validator.py +549 -465
  133. runbooks/inventory/mcp_vpc_validator.py +359 -442
  134. runbooks/inventory/organizations_discovery.py +56 -52
  135. runbooks/inventory/rich_inventory_display.py +33 -32
  136. runbooks/inventory/unified_validation_engine.py +278 -251
  137. runbooks/inventory/vpc_analyzer.py +733 -696
  138. runbooks/inventory/vpc_architecture_validator.py +293 -348
  139. runbooks/inventory/vpc_dependency_analyzer.py +382 -378
  140. runbooks/inventory/vpc_flow_analyzer.py +3 -3
  141. runbooks/main.py +152 -9147
  142. runbooks/main_final.py +91 -60
  143. runbooks/main_minimal.py +22 -10
  144. runbooks/main_optimized.py +131 -100
  145. runbooks/main_ultra_minimal.py +7 -2
  146. runbooks/mcp/__init__.py +36 -0
  147. runbooks/mcp/integration.py +679 -0
  148. runbooks/metrics/dora_metrics_engine.py +2 -2
  149. runbooks/monitoring/performance_monitor.py +9 -4
  150. runbooks/operate/dynamodb_operations.py +3 -1
  151. runbooks/operate/ec2_operations.py +145 -137
  152. runbooks/operate/iam_operations.py +146 -152
  153. runbooks/operate/mcp_integration.py +1 -1
  154. runbooks/operate/networking_cost_heatmap.py +33 -10
  155. runbooks/operate/privatelink_operations.py +1 -1
  156. runbooks/operate/rds_operations.py +223 -254
  157. runbooks/operate/s3_operations.py +107 -118
  158. runbooks/operate/vpc_endpoints.py +1 -1
  159. runbooks/operate/vpc_operations.py +648 -618
  160. runbooks/remediation/base.py +1 -1
  161. runbooks/remediation/commons.py +10 -7
  162. runbooks/remediation/commvault_ec2_analysis.py +71 -67
  163. runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
  164. runbooks/remediation/multi_account.py +24 -21
  165. runbooks/remediation/rds_snapshot_list.py +91 -65
  166. runbooks/remediation/remediation_cli.py +92 -146
  167. runbooks/remediation/universal_account_discovery.py +83 -79
  168. runbooks/remediation/workspaces_list.py +49 -44
  169. runbooks/security/__init__.py +19 -0
  170. runbooks/security/assessment_runner.py +1150 -0
  171. runbooks/security/baseline_checker.py +812 -0
  172. runbooks/security/cloudops_automation_security_validator.py +509 -535
  173. runbooks/security/compliance_automation_engine.py +17 -17
  174. runbooks/security/config/__init__.py +2 -2
  175. runbooks/security/config/compliance_config.py +50 -50
  176. runbooks/security/config_template_generator.py +63 -76
  177. runbooks/security/enterprise_security_framework.py +1 -1
  178. runbooks/security/executive_security_dashboard.py +519 -508
  179. runbooks/security/integration_test_enterprise_security.py +5 -3
  180. runbooks/security/multi_account_security_controls.py +959 -1210
  181. runbooks/security/real_time_security_monitor.py +422 -444
  182. runbooks/security/run_script.py +1 -1
  183. runbooks/security/security_baseline_tester.py +1 -1
  184. runbooks/security/security_cli.py +143 -112
  185. runbooks/security/test_2way_validation.py +439 -0
  186. runbooks/security/two_way_validation_framework.py +852 -0
  187. runbooks/sre/mcp_reliability_engine.py +6 -6
  188. runbooks/sre/production_monitoring_framework.py +167 -177
  189. runbooks/tdd/__init__.py +15 -0
  190. runbooks/tdd/cli.py +1071 -0
  191. runbooks/utils/__init__.py +14 -17
  192. runbooks/utils/logger.py +7 -2
  193. runbooks/utils/version_validator.py +51 -48
  194. runbooks/validation/__init__.py +6 -6
  195. runbooks/validation/cli.py +9 -3
  196. runbooks/validation/comprehensive_2way_validator.py +754 -708
  197. runbooks/validation/mcp_validator.py +906 -228
  198. runbooks/validation/terraform_citations_validator.py +104 -115
  199. runbooks/validation/terraform_drift_detector.py +447 -451
  200. runbooks/vpc/README.md +617 -0
  201. runbooks/vpc/__init__.py +8 -1
  202. runbooks/vpc/analyzer.py +577 -0
  203. runbooks/vpc/cleanup_wrapper.py +476 -413
  204. runbooks/vpc/cli_cloudtrail_commands.py +339 -0
  205. runbooks/vpc/cli_mcp_validation_commands.py +480 -0
  206. runbooks/vpc/cloudtrail_audit_integration.py +717 -0
  207. runbooks/vpc/config.py +92 -97
  208. runbooks/vpc/cost_engine.py +411 -148
  209. runbooks/vpc/cost_explorer_integration.py +553 -0
  210. runbooks/vpc/cross_account_session.py +101 -106
  211. runbooks/vpc/enhanced_mcp_validation.py +917 -0
  212. runbooks/vpc/eni_gate_validator.py +961 -0
  213. runbooks/vpc/heatmap_engine.py +190 -162
  214. runbooks/vpc/mcp_no_eni_validator.py +681 -640
  215. runbooks/vpc/nat_gateway_optimizer.py +358 -0
  216. runbooks/vpc/networking_wrapper.py +15 -8
  217. runbooks/vpc/pdca_remediation_planner.py +528 -0
  218. runbooks/vpc/performance_optimized_analyzer.py +219 -231
  219. runbooks/vpc/runbooks_adapter.py +1167 -241
  220. runbooks/vpc/tdd_red_phase_stubs.py +601 -0
  221. runbooks/vpc/test_data_loader.py +358 -0
  222. runbooks/vpc/tests/conftest.py +314 -4
  223. runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
  224. runbooks/vpc/tests/test_cost_engine.py +0 -2
  225. runbooks/vpc/topology_generator.py +326 -0
  226. runbooks/vpc/unified_scenarios.py +1302 -1129
  227. runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
  228. runbooks-1.1.5.dist-info/METADATA +328 -0
  229. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/RECORD +233 -200
  230. runbooks/finops/README.md +0 -414
  231. runbooks/finops/accuracy_cross_validator.py +0 -647
  232. runbooks/finops/business_cases.py +0 -950
  233. runbooks/finops/dashboard_router.py +0 -922
  234. runbooks/finops/ebs_optimizer.py +0 -956
  235. runbooks/finops/embedded_mcp_validator.py +0 -1629
  236. runbooks/finops/enhanced_dashboard_runner.py +0 -527
  237. runbooks/finops/finops_dashboard.py +0 -584
  238. runbooks/finops/finops_scenarios.py +0 -1218
  239. runbooks/finops/legacy_migration.py +0 -730
  240. runbooks/finops/multi_dashboard.py +0 -1519
  241. runbooks/finops/single_dashboard.py +0 -1113
  242. runbooks/finops/unlimited_scenarios.py +0 -393
  243. runbooks-1.1.3.dist-info/METADATA +0 -799
  244. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
  245. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
  246. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
  247. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
@@ -20,38 +20,39 @@ Strategic Alignment:
20
20
  - Maintains enterprise standards for data integrity
21
21
  """
22
22
 
23
- from decimal import Decimal, ROUND_HALF_UP
24
- from datetime import datetime, date
25
- from typing import Dict, List, Optional, Union, Any, Literal
26
- from enum import Enum
27
23
  import re
24
+ from datetime import date, datetime
25
+ from decimal import ROUND_HALF_UP, Decimal
26
+ from enum import Enum
27
+ from typing import Any, Dict, List, Literal, Optional, Union
28
28
 
29
- from pydantic import BaseModel, Field, field_validator, model_validator, ConfigDict
30
- from pydantic.types import UUID4, PositiveFloat, NonNegativeFloat
29
+ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
30
+ from pydantic.types import UUID4, NonNegativeFloat, PositiveFloat
31
31
 
32
32
 
33
33
  # Configuration for Pydantic v2
34
34
  class BaseSchema(BaseModel):
35
35
  """Base schema with common configuration for all models."""
36
-
36
+
37
37
  model_config = ConfigDict(
38
38
  # Enable strict validation
39
39
  str_strip_whitespace=True,
40
40
  validate_assignment=True,
41
41
  use_enum_values=True,
42
42
  # Allow for schema evolution
43
- extra='forbid', # Strict validation - no unexpected fields
43
+ extra="forbid", # Strict validation - no unexpected fields
44
44
  # JSON encoding settings
45
45
  json_encoders={
46
46
  datetime: lambda dt: dt.isoformat(),
47
47
  date: lambda d: d.isoformat(),
48
48
  Decimal: lambda d: float(d),
49
- }
49
+ },
50
50
  )
51
51
 
52
52
 
53
53
  class ComplexityLevel(str, Enum):
54
54
  """Implementation complexity levels for cost optimization scenarios."""
55
+
55
56
  LOW = "Low"
56
57
  MEDIUM = "Medium"
57
58
  HIGH = "High"
@@ -59,6 +60,7 @@ class ComplexityLevel(str, Enum):
59
60
 
60
61
  class RiskLevel(str, Enum):
61
62
  """Risk levels for cost optimization implementations."""
63
+
62
64
  LOW = "Low"
63
65
  MEDIUM = "Medium"
64
66
  HIGH = "High"
@@ -67,6 +69,7 @@ class RiskLevel(str, Enum):
67
69
 
68
70
  class OptimizationCategory(str, Enum):
69
71
  """Categories of cost optimization scenarios."""
72
+
70
73
  UNUSED_RESOURCES = "Unused Resources"
71
74
  RIGHTSIZING = "Rightsizing"
72
75
  RESERVED_INSTANCES = "Reserved Instances"
@@ -79,8 +82,9 @@ class OptimizationCategory(str, Enum):
79
82
 
80
83
  class ValidationStatus(str, Enum):
81
84
  """Validation status for cross-checking with MCP servers."""
85
+
82
86
  VALIDATED = "validated"
83
- VARIANCE_DETECTED = "variance_detected"
87
+ VARIANCE_DETECTED = "variance_detected"
84
88
  MCP_UNAVAILABLE = "mcp_unavailable"
85
89
  ERROR = "error"
86
90
  PENDING = "pending"
@@ -88,6 +92,7 @@ class ValidationStatus(str, Enum):
88
92
 
89
93
  class ExportFormat(str, Enum):
90
94
  """Supported export formats for reports."""
95
+
91
96
  JSON = "json"
92
97
  CSV = "csv"
93
98
  HTML = "html"
@@ -97,219 +102,244 @@ class ExportFormat(str, Enum):
97
102
 
98
103
  # Core Cost Optimization Schemas
99
104
 
105
+
100
106
  class CostBreakdown(BaseSchema):
101
107
  """Detailed cost breakdown by service/category."""
102
-
108
+
103
109
  service_name: str = Field(..., min_length=1, max_length=100)
104
110
  monthly_cost: NonNegativeFloat = Field(..., ge=0)
105
111
  annual_cost: NonNegativeFloat = Field(..., ge=0)
106
112
  percentage_of_total: float = Field(..., ge=0, le=100)
107
113
  resource_count: int = Field(..., ge=0)
108
-
109
- @field_validator('service_name')
114
+
115
+ @field_validator("service_name")
110
116
  @classmethod
111
117
  def validate_service_name(cls, v):
112
118
  """Validate AWS service names."""
113
119
  # Common AWS service patterns
114
120
  valid_patterns = [
115
- r'^EC2-', # EC2 services
116
- r'^S3', # S3 services
117
- r'^RDS', # RDS services
118
- r'^Lambda', # Lambda
119
- r'^CloudWatch', # CloudWatch
120
- r'^VPC', # VPC services
121
- r'^Route 53', # Route 53
122
- r'^ElastiCache', # ElastiCache
123
- r'^Redshift', # Redshift
124
- r'^\w+$' # General service names
121
+ r"^EC2-", # EC2 services
122
+ r"^S3", # S3 services
123
+ r"^RDS", # RDS services
124
+ r"^Lambda", # Lambda
125
+ r"^CloudWatch", # CloudWatch
126
+ r"^VPC", # VPC services
127
+ r"^Route 53", # Route 53
128
+ r"^ElastiCache", # ElastiCache
129
+ r"^Redshift", # Redshift
130
+ r"^\w+$", # General service names
125
131
  ]
126
-
132
+
127
133
  if not any(re.match(pattern, v) for pattern in valid_patterns):
128
134
  # Allow any string for flexibility, but validate length
129
135
  if len(v.strip()) == 0:
130
- raise ValueError('Service name cannot be empty')
131
-
136
+ raise ValueError("Service name cannot be empty")
137
+
132
138
  return v.strip()
133
-
134
- @field_validator('annual_cost')
139
+
140
+ @field_validator("annual_cost")
135
141
  @classmethod
136
142
  def validate_annual_cost_consistency(cls, v, info):
137
143
  """Ensure annual cost is approximately 12x monthly cost."""
138
- if 'monthly_cost' in info.data:
139
- expected_annual = info.data['monthly_cost'] * 12
144
+ if "monthly_cost" in info.data:
145
+ expected_annual = info.data["monthly_cost"] * 12
140
146
  # Allow 1% tolerance for rounding differences
141
147
  if abs(v - expected_annual) > (expected_annual * 0.01):
142
- raise ValueError(f'Annual cost {v} should be approximately 12x monthly cost {info.data["monthly_cost"]}')
148
+ raise ValueError(
149
+ f"Annual cost {v} should be approximately 12x monthly cost {info.data['monthly_cost']}"
150
+ )
143
151
  return v
144
152
 
145
153
 
146
154
  class OptimizationScenario(BaseSchema):
147
155
  """Individual cost optimization scenario with validation."""
148
-
156
+
149
157
  scenario_name: str = Field(..., min_length=3, max_length=200)
150
158
  category: OptimizationCategory = Field(...)
151
159
  description: str = Field(..., min_length=10, max_length=1000)
152
-
160
+
153
161
  # Financial metrics
154
162
  monthly_savings: NonNegativeFloat = Field(..., ge=0)
155
163
  annual_savings: NonNegativeFloat = Field(..., ge=0)
156
164
  implementation_cost: NonNegativeFloat = Field(0, ge=0)
157
165
  payback_period_months: Optional[PositiveFloat] = Field(None, gt=0, le=120) # Max 10 years
158
-
166
+
159
167
  # Implementation details
160
168
  complexity: ComplexityLevel = Field(...)
161
169
  risk_level: RiskLevel = Field(...)
162
170
  estimated_hours: PositiveFloat = Field(..., gt=0, le=2000) # Reasonable implementation time
163
-
171
+
164
172
  # Resource impact
165
173
  affected_services: List[str] = Field(..., min_items=1)
166
174
  affected_accounts: List[str] = Field(..., min_items=1)
167
175
  resource_count: int = Field(..., ge=1)
168
-
176
+
169
177
  # Validation metadata
170
178
  validation_status: ValidationStatus = Field(ValidationStatus.PENDING)
171
179
  validation_timestamp: Optional[datetime] = Field(None)
172
180
  mcp_variance_percent: Optional[float] = Field(None, ge=0, le=100)
173
-
174
- @field_validator('scenario_name')
181
+
182
+ @field_validator("scenario_name")
175
183
  @classmethod
176
184
  def validate_scenario_name(cls, v):
177
185
  """Validate scenario naming conventions."""
178
186
  # Ensure professional naming
179
- if not re.match(r'^[A-Z][A-Za-z0-9\s\-\(\)]{2,199}$', v):
180
- raise ValueError('Scenario name must start with capital letter and contain only letters, numbers, spaces, hyphens, and parentheses')
187
+ if not re.match(r"^[A-Z][A-Za-z0-9\s\-\(\)]{2,199}$", v):
188
+ raise ValueError(
189
+ "Scenario name must start with capital letter and contain only letters, numbers, spaces, hyphens, and parentheses"
190
+ )
181
191
  return v.strip()
182
-
183
- @field_validator('annual_savings')
192
+
193
+ @field_validator("annual_savings")
184
194
  @classmethod
185
195
  def validate_annual_savings_consistency(cls, v, info):
186
196
  """Ensure annual savings consistency with monthly savings."""
187
- if 'monthly_savings' in info.data:
188
- expected_annual = info.data['monthly_savings'] * 12
197
+ if "monthly_savings" in info.data:
198
+ expected_annual = info.data["monthly_savings"] * 12
189
199
  if abs(v - expected_annual) > (expected_annual * 0.01): # 1% tolerance
190
- raise ValueError(f'Annual savings {v} should be approximately 12x monthly savings {info.data["monthly_savings"]}')
200
+ raise ValueError(
201
+ f"Annual savings {v} should be approximately 12x monthly savings {info.data['monthly_savings']}"
202
+ )
191
203
  return v
192
-
193
- @field_validator('payback_period_months')
204
+
205
+ @field_validator("payback_period_months")
194
206
  @classmethod
195
207
  def calculate_payback_period(cls, v, info):
196
208
  """Calculate payback period if not provided."""
197
- if v is None and 'implementation_cost' in info.data and 'monthly_savings' in info.data:
198
- impl_cost = info.data['implementation_cost']
199
- monthly_savings = info.data['monthly_savings']
209
+ if v is None and "implementation_cost" in info.data and "monthly_savings" in info.data:
210
+ impl_cost = info.data["implementation_cost"]
211
+ monthly_savings = info.data["monthly_savings"]
200
212
  if monthly_savings > 0:
201
213
  calculated_payback = impl_cost / monthly_savings
202
214
  return round(calculated_payback, 1)
203
215
  return v
204
-
205
- @field_validator('affected_services')
216
+
217
+ @field_validator("affected_services")
206
218
  @classmethod
207
219
  def validate_aws_services(cls, v):
208
220
  """Validate AWS service names in affected services."""
209
221
  common_services = {
210
- 'EC2', 'S3', 'RDS', 'Lambda', 'CloudWatch', 'VPC', 'ELB',
211
- 'Route53', 'CloudFront', 'ElastiCache', 'Redshift', 'DynamoDB',
212
- 'EBS', 'EFS', 'FSx', 'Backup', 'Config', 'CloudTrail', 'IAM'
222
+ "EC2",
223
+ "S3",
224
+ "RDS",
225
+ "Lambda",
226
+ "CloudWatch",
227
+ "VPC",
228
+ "ELB",
229
+ "Route53",
230
+ "CloudFront",
231
+ "ElastiCache",
232
+ "Redshift",
233
+ "DynamoDB",
234
+ "EBS",
235
+ "EFS",
236
+ "FSx",
237
+ "Backup",
238
+ "Config",
239
+ "CloudTrail",
240
+ "IAM",
213
241
  }
214
-
242
+
215
243
  for service in v:
216
244
  # Allow any service that starts with common patterns or is in common list
217
- if not (service in common_services or
218
- any(service.startswith(prefix) for prefix in ['AWS', 'Amazon']) or
219
- re.match(r'^[A-Z][A-Za-z0-9\-]{1,50}$', service)):
220
- raise ValueError(f'Invalid AWS service name: {service}')
221
-
245
+ if not (
246
+ service in common_services
247
+ or any(service.startswith(prefix) for prefix in ["AWS", "Amazon"])
248
+ or re.match(r"^[A-Z][A-Za-z0-9\-]{1,50}$", service)
249
+ ):
250
+ raise ValueError(f"Invalid AWS service name: {service}")
251
+
222
252
  return v
223
-
224
- @field_validator('affected_accounts')
253
+
254
+ @field_validator("affected_accounts")
225
255
  @classmethod
226
256
  def validate_account_ids(cls, v):
227
257
  """Validate AWS account ID format."""
228
- account_pattern = r'^\d{12}$|^[\w\-\.]{1,50}$' # 12-digit ID or account name
229
-
258
+ account_pattern = r"^\d{12}$|^[\w\-\.]{1,50}$" # 12-digit ID or account name
259
+
230
260
  for account in v:
231
261
  if not re.match(account_pattern, account):
232
- raise ValueError(f'Invalid account format: {account}. Must be 12-digit ID or valid account name')
233
-
262
+ raise ValueError(f"Invalid account format: {account}. Must be 12-digit ID or valid account name")
263
+
234
264
  return v
235
265
 
236
266
 
237
267
  class CostOptimizationResult(BaseSchema):
238
268
  """Comprehensive cost optimization analysis result."""
239
-
269
+
240
270
  # Analysis metadata
241
271
  analysis_id: UUID4 = Field(..., description="Unique analysis identifier")
242
272
  analysis_timestamp: datetime = Field(..., description="Analysis execution time")
243
273
  profile_name: str = Field(..., min_length=1, max_length=100)
244
-
274
+
245
275
  # Scope and configuration
246
276
  analysis_scope: Literal["single_account", "multi_account", "organization"] = Field(...)
247
277
  total_accounts: int = Field(..., ge=1, le=1000) # Reasonable limit
248
278
  analysis_period_days: int = Field(..., ge=1, le=365)
249
-
279
+
250
280
  # Financial summary
251
281
  current_monthly_spend: NonNegativeFloat = Field(..., ge=0)
252
282
  total_potential_monthly_savings: NonNegativeFloat = Field(..., ge=0)
253
283
  total_potential_annual_savings: NonNegativeFloat = Field(..., ge=0)
254
284
  savings_percentage: float = Field(..., ge=0, le=100)
255
-
285
+
256
286
  # Scenarios and breakdown
257
287
  optimization_scenarios: List[OptimizationScenario] = Field(..., min_items=1, max_items=100)
258
288
  cost_breakdown: List[CostBreakdown] = Field(..., min_items=1)
259
-
289
+
260
290
  # Implementation summary
261
291
  total_scenarios: int = Field(..., ge=1)
262
292
  low_complexity_scenarios: int = Field(..., ge=0)
263
293
  medium_complexity_scenarios: int = Field(..., ge=0)
264
294
  high_complexity_scenarios: int = Field(..., ge=0)
265
-
295
+
266
296
  # Risk assessment
267
297
  average_risk_score: float = Field(..., ge=1, le=5) # 1-5 scale
268
298
  high_risk_scenarios_count: int = Field(..., ge=0)
269
-
299
+
270
300
  # Validation and quality
271
301
  mcp_validation_status: ValidationStatus = Field(ValidationStatus.PENDING)
272
302
  validation_summary: Optional[Dict[str, Any]] = Field(None)
273
303
  accuracy_confidence: Optional[float] = Field(None, ge=0, le=100)
274
-
304
+
275
305
  # Export metadata
276
306
  supported_export_formats: List[ExportFormat] = Field(
277
307
  default=[ExportFormat.JSON, ExportFormat.CSV, ExportFormat.PDF]
278
308
  )
279
-
280
- @field_validator('total_potential_annual_savings')
309
+
310
+ @field_validator("total_potential_annual_savings")
281
311
  @classmethod
282
312
  def validate_annual_consistency(cls, v, info):
283
313
  """Validate annual savings consistency."""
284
- if 'total_potential_monthly_savings' in info.data:
285
- expected = info.data['total_potential_monthly_savings'] * 12
314
+ if "total_potential_monthly_savings" in info.data:
315
+ expected = info.data["total_potential_monthly_savings"] * 12
286
316
  if abs(v - expected) > (expected * 0.01):
287
- raise ValueError('Annual savings must be approximately 12x monthly savings')
317
+ raise ValueError("Annual savings must be approximately 12x monthly savings")
288
318
  return v
289
-
290
- @field_validator('savings_percentage')
319
+
320
+ @field_validator("savings_percentage")
291
321
  @classmethod
292
322
  def calculate_savings_percentage(cls, v, info):
293
323
  """Validate or calculate savings percentage."""
294
- if 'current_monthly_spend' in info.data and 'total_potential_monthly_savings' in info.data:
295
- current_spend = info.data['current_monthly_spend']
324
+ if "current_monthly_spend" in info.data and "total_potential_monthly_savings" in info.data:
325
+ current_spend = info.data["current_monthly_spend"]
296
326
  if current_spend > 0:
297
- calculated = (info.data['total_potential_monthly_savings'] / current_spend) * 100
327
+ calculated = (info.data["total_potential_monthly_savings"] / current_spend) * 100
298
328
  if abs(v - calculated) > 0.1: # 0.1% tolerance
299
- raise ValueError(f'Savings percentage {v}% inconsistent with calculated {calculated:.1f}%')
329
+ raise ValueError(f"Savings percentage {v}% inconsistent with calculated {calculated:.1f}%")
300
330
  return v
301
-
302
- @field_validator('total_scenarios')
331
+
332
+ @field_validator("total_scenarios")
303
333
  @classmethod
304
334
  def validate_scenario_count(cls, v, info):
305
335
  """Ensure scenario count matches actual scenarios."""
306
- if 'optimization_scenarios' in info.data:
307
- actual_count = len(info.data['optimization_scenarios'])
336
+ if "optimization_scenarios" in info.data:
337
+ actual_count = len(info.data["optimization_scenarios"])
308
338
  if v != actual_count:
309
- raise ValueError(f'Total scenarios {v} does not match actual scenarios count {actual_count}')
339
+ raise ValueError(f"Total scenarios {v} does not match actual scenarios count {actual_count}")
310
340
  return v
311
-
312
- @model_validator(mode='after')
341
+
342
+ @model_validator(mode="after")
313
343
  def validate_complexity_distribution(self):
314
344
  """Validate complexity scenario counts."""
315
345
  scenarios = self.optimization_scenarios or []
@@ -317,112 +347,112 @@ class CostOptimizationResult(BaseSchema):
317
347
  low_count = sum(1 for s in scenarios if s.complexity == ComplexityLevel.LOW)
318
348
  medium_count = sum(1 for s in scenarios if s.complexity == ComplexityLevel.MEDIUM)
319
349
  high_count = sum(1 for s in scenarios if s.complexity == ComplexityLevel.HIGH)
320
-
350
+
321
351
  expected_low = self.low_complexity_scenarios or 0
322
352
  expected_medium = self.medium_complexity_scenarios or 0
323
353
  expected_high = self.high_complexity_scenarios or 0
324
-
325
- if (low_count != expected_low or
326
- medium_count != expected_medium or
327
- high_count != expected_high):
354
+
355
+ if low_count != expected_low or medium_count != expected_medium or high_count != expected_high:
328
356
  raise ValueError(
329
- f'Complexity counts mismatch: expected L:{expected_low} M:{expected_medium} H:{expected_high}, '
330
- f'actual L:{low_count} M:{medium_count} H:{high_count}'
357
+ f"Complexity counts mismatch: expected L:{expected_low} M:{expected_medium} H:{expected_high}, "
358
+ f"actual L:{low_count} M:{medium_count} H:{high_count}"
331
359
  )
332
-
360
+
333
361
  return self
334
362
 
335
363
 
336
364
  # Business Interface Schemas
337
365
 
366
+
338
367
  class ExecutiveSummary(BaseSchema):
339
368
  """Executive-ready summary for business stakeholders."""
340
-
369
+
341
370
  # High-level metrics
342
371
  total_annual_opportunity: NonNegativeFloat = Field(..., ge=0)
343
372
  confidence_level: float = Field(..., ge=70, le=100) # Must be high confidence for exec presentation
344
373
  implementation_timeline_months: PositiveFloat = Field(..., gt=0, le=24) # Reasonable timeline
345
-
374
+
346
375
  # Business impact
347
376
  roi_percentage: PositiveFloat = Field(..., gt=0)
348
377
  payback_period_months: PositiveFloat = Field(..., gt=0, le=60) # Max 5 years
349
378
  risk_assessment: RiskLevel = Field(...)
350
-
379
+
351
380
  # Quick wins
352
381
  quick_wins_count: int = Field(..., ge=0, le=50)
353
382
  quick_wins_annual_value: NonNegativeFloat = Field(..., ge=0)
354
-
383
+
355
384
  # Implementation priority
356
385
  priority_scenarios: List[str] = Field(..., max_items=10) # Top priorities only
357
386
  recommended_next_steps: List[str] = Field(..., min_items=1, max_items=5)
358
-
387
+
359
388
  # Validation status
360
389
  data_validation_status: ValidationStatus = Field(...)
361
390
  last_validated: datetime = Field(...)
362
-
363
- @field_validator('roi_percentage')
391
+
392
+ @field_validator("roi_percentage")
364
393
  @classmethod
365
394
  def validate_reasonable_roi(cls, v):
366
395
  """Ensure ROI is reasonable for executive presentation."""
367
396
  if v > 1000: # 1000% ROI
368
- raise ValueError('ROI over 1000% requires additional validation')
397
+ raise ValueError("ROI over 1000% requires additional validation")
369
398
  return v
370
399
 
371
400
 
372
401
  # Technical Validation Schemas
373
402
 
403
+
374
404
  class MCPValidationResult(BaseSchema):
375
405
  """MCP cross-validation result with strict tolerance checking."""
376
-
406
+
377
407
  validation_timestamp: datetime = Field(...)
378
408
  notebook_value: NonNegativeFloat = Field(..., ge=0)
379
409
  mcp_value: NonNegativeFloat = Field(..., ge=0)
380
410
  variance_amount: NonNegativeFloat = Field(..., ge=0)
381
411
  variance_percent: float = Field(..., ge=0)
382
412
  tolerance_threshold: PositiveFloat = Field(..., gt=0, le=10) # Max 10% tolerance
383
-
413
+
384
414
  validation_status: ValidationStatus = Field(...)
385
415
  validation_message: str = Field(..., min_length=1)
386
-
416
+
387
417
  # Technical details
388
418
  mcp_source: str = Field(..., min_length=1)
389
419
  response_time_seconds: Optional[PositiveFloat] = Field(None, le=300) # 5 minute timeout
390
-
391
- @field_validator('variance_percent')
420
+
421
+ @field_validator("variance_percent")
392
422
  @classmethod
393
423
  def calculate_variance_percent(cls, v, info):
394
424
  """Calculate and validate variance percentage."""
395
- if 'notebook_value' in info.data and 'mcp_value' in info.data:
396
- notebook_val = info.data['notebook_value']
397
- mcp_val = info.data['mcp_value']
398
-
425
+ if "notebook_value" in info.data and "mcp_value" in info.data:
426
+ notebook_val = info.data["notebook_value"]
427
+ mcp_val = info.data["mcp_value"]
428
+
399
429
  if notebook_val > 0:
400
430
  calculated = abs((notebook_val - mcp_val) / notebook_val) * 100
401
431
  if abs(v - calculated) > 0.01: # Very tight tolerance for variance calculation
402
- raise ValueError(f'Variance percent {v}% does not match calculated {calculated:.2f}%')
432
+ raise ValueError(f"Variance percent {v}% does not match calculated {calculated:.2f}%")
403
433
  return v
404
434
 
405
435
 
406
436
  class FunctionalTestResult(BaseSchema):
407
437
  """Functional testing result for technical validation."""
408
-
438
+
409
439
  test_name: str = Field(..., min_length=3, max_length=200)
410
440
  test_category: Literal["cost_analysis", "mcp_validation", "export_validation", "performance"] = Field(...)
411
-
441
+
412
442
  # Test execution
413
443
  execution_timestamp: datetime = Field(...)
414
444
  execution_time_seconds: PositiveFloat = Field(..., le=300) # 5 minute timeout
415
445
  test_passed: bool = Field(...)
416
-
446
+
417
447
  # Test details
418
448
  expected_value: Optional[Union[str, float, int, bool]] = Field(None)
419
449
  actual_value: Optional[Union[str, float, int, bool]] = Field(None)
420
450
  tolerance_applied: Optional[float] = Field(None, ge=0, le=10)
421
-
451
+
422
452
  # Error handling
423
453
  error_message: Optional[str] = Field(None, max_length=1000)
424
454
  stack_trace: Optional[str] = Field(None, max_length=5000)
425
-
455
+
426
456
  # Performance metrics
427
457
  memory_usage_mb: Optional[PositiveFloat] = Field(None, le=4096) # 4GB max
428
458
  cpu_utilization_percent: Optional[float] = Field(None, ge=0, le=100)
@@ -430,92 +460,94 @@ class FunctionalTestResult(BaseSchema):
430
460
 
431
461
  class ComprehensiveTestSuite(BaseSchema):
432
462
  """Complete test suite results for technical validation."""
433
-
463
+
434
464
  # Test suite metadata
435
465
  suite_id: UUID4 = Field(...)
436
466
  execution_timestamp: datetime = Field(...)
437
467
  total_execution_time_seconds: PositiveFloat = Field(...)
438
-
468
+
439
469
  # Test results
440
470
  total_tests: int = Field(..., ge=1)
441
471
  passed_tests: int = Field(..., ge=0)
442
472
  failed_tests: int = Field(..., ge=0)
443
473
  skipped_tests: int = Field(..., ge=0)
444
-
474
+
445
475
  test_results: List[FunctionalTestResult] = Field(..., min_items=1)
446
-
476
+
447
477
  # Summary metrics
448
478
  pass_rate_percent: float = Field(..., ge=0, le=100)
449
479
  performance_target_met: bool = Field(...)
450
480
  mcp_validation_success: bool = Field(...)
451
-
481
+
452
482
  # Quality gates
453
483
  meets_production_criteria: bool = Field(...)
454
484
  quality_score: float = Field(..., ge=0, le=100)
455
-
456
- @field_validator('passed_tests')
485
+
486
+ @field_validator("passed_tests")
457
487
  @classmethod
458
488
  def validate_test_counts(cls, v, info):
459
489
  """Ensure test counts are consistent."""
460
- if 'failed_tests' in info.data and 'skipped_tests' in info.data and 'total_tests' in info.data:
461
- calculated_total = v + info.data['failed_tests'] + info.data['skipped_tests']
462
- if calculated_total != info.data['total_tests']:
463
- raise ValueError(f'Test counts inconsistent: {calculated_total} ≠ {info.data["total_tests"]}')
490
+ if "failed_tests" in info.data and "skipped_tests" in info.data and "total_tests" in info.data:
491
+ calculated_total = v + info.data["failed_tests"] + info.data["skipped_tests"]
492
+ if calculated_total != info.data["total_tests"]:
493
+ raise ValueError(f"Test counts inconsistent: {calculated_total} ≠ {info.data['total_tests']}")
464
494
  return v
465
-
466
- @field_validator('pass_rate_percent')
495
+
496
+ @field_validator("pass_rate_percent")
467
497
  @classmethod
468
498
  def calculate_pass_rate(cls, v, info):
469
499
  """Calculate and validate pass rate."""
470
- if 'passed_tests' in info.data and 'total_tests' in info.data:
471
- total = info.data['total_tests']
500
+ if "passed_tests" in info.data and "total_tests" in info.data:
501
+ total = info.data["total_tests"]
472
502
  if total > 0:
473
- calculated = (info.data['passed_tests'] / total) * 100
503
+ calculated = (info.data["passed_tests"] / total) * 100
474
504
  if abs(v - calculated) > 0.01:
475
- raise ValueError(f'Pass rate {v}% inconsistent with calculated {calculated:.2f}%')
505
+ raise ValueError(f"Pass rate {v}% inconsistent with calculated {calculated:.2f}%")
476
506
  return v
477
507
 
478
508
 
479
509
  # Export and Integration Schemas
480
510
 
511
+
481
512
  class ExportMetadata(BaseSchema):
482
513
  """Metadata for exported reports."""
483
-
514
+
484
515
  export_timestamp: datetime = Field(...)
485
516
  export_format: ExportFormat = Field(...)
486
517
  file_path: str = Field(..., min_length=1, max_length=500)
487
518
  file_size_bytes: int = Field(..., ge=0)
488
-
519
+
489
520
  # Content metadata
490
521
  record_count: int = Field(..., ge=0)
491
- schema_version: str = Field(..., pattern=r'^\d+\.\d+\.\d+$') # Semantic versioning
492
-
522
+ schema_version: str = Field(..., pattern=r"^\d+\.\d+\.\d+$") # Semantic versioning
523
+
493
524
  # Validation
494
525
  export_validated: bool = Field(...)
495
526
  validation_errors: List[str] = Field(default_factory=list)
496
-
497
- @field_validator('file_path')
527
+
528
+ @field_validator("file_path")
498
529
  @classmethod
499
530
  def validate_file_path(cls, v):
500
531
  """Validate file path format."""
501
532
  # Basic path validation
502
- if not re.match(r'^[/\w\-\.\s]+\.(json|csv|html|pdf|md)$', v):
503
- raise ValueError('Invalid file path format')
533
+ if not re.match(r"^[/\w\-\.\s]+\.(json|csv|html|pdf|md)$", v):
534
+ raise ValueError("Invalid file path format")
504
535
  return v
505
536
 
506
537
 
507
538
  # Utility Functions for Schema Validation
508
539
 
540
+
509
541
  def validate_cost_optimization_result(data: Dict[str, Any]) -> CostOptimizationResult:
510
542
  """
511
543
  Validate and create CostOptimizationResult from raw data.
512
-
544
+
513
545
  Args:
514
546
  data: Raw data dictionary
515
-
547
+
516
548
  Returns:
517
549
  Validated CostOptimizationResult instance
518
-
550
+
519
551
  Raises:
520
552
  ValidationError: If data doesn't meet schema requirements
521
553
  """
@@ -525,22 +557,22 @@ def validate_cost_optimization_result(data: Dict[str, Any]) -> CostOptimizationR
525
557
  def create_executive_summary(optimization_result: CostOptimizationResult) -> ExecutiveSummary:
526
558
  """
527
559
  Create executive summary from optimization result.
528
-
560
+
529
561
  Args:
530
562
  optimization_result: Validated optimization result
531
-
563
+
532
564
  Returns:
533
565
  ExecutiveSummary instance
534
566
  """
535
567
  # Calculate quick wins (Low complexity, Low-Medium risk)
536
568
  quick_wins = [
537
- scenario for scenario in optimization_result.optimization_scenarios
538
- if (scenario.complexity == ComplexityLevel.LOW and
539
- scenario.risk_level in [RiskLevel.LOW, RiskLevel.MEDIUM])
569
+ scenario
570
+ for scenario in optimization_result.optimization_scenarios
571
+ if (scenario.complexity == ComplexityLevel.LOW and scenario.risk_level in [RiskLevel.LOW, RiskLevel.MEDIUM])
540
572
  ]
541
-
573
+
542
574
  quick_wins_value = sum(scenario.annual_savings for scenario in quick_wins)
543
-
575
+
544
576
  # Calculate implementation timeline (weighted by complexity)
545
577
  complexity_weights = {ComplexityLevel.LOW: 1, ComplexityLevel.MEDIUM: 3, ComplexityLevel.HIGH: 6}
546
578
  total_weighted_hours = sum(
@@ -548,12 +580,12 @@ def create_executive_summary(optimization_result: CostOptimizationResult) -> Exe
548
580
  for scenario in optimization_result.optimization_scenarios
549
581
  )
550
582
  timeline_months = max(1, total_weighted_hours / 160) # Assuming 160 hours/month
551
-
583
+
552
584
  # ROI calculation
553
585
  annual_savings = optimization_result.total_potential_annual_savings
554
586
  implementation_cost = sum(scenario.implementation_cost for scenario in optimization_result.optimization_scenarios)
555
587
  roi_percentage = (annual_savings / max(implementation_cost, 1)) * 100
556
-
588
+
557
589
  return ExecutiveSummary(
558
590
  total_annual_opportunity=annual_savings,
559
591
  confidence_level=optimization_result.accuracy_confidence or 85.0,
@@ -564,41 +596,45 @@ def create_executive_summary(optimization_result: CostOptimizationResult) -> Exe
564
596
  quick_wins_count=len(quick_wins),
565
597
  quick_wins_annual_value=quick_wins_value,
566
598
  priority_scenarios=[
567
- scenario.scenario_name for scenario in
568
- sorted(optimization_result.optimization_scenarios,
569
- key=lambda x: x.annual_savings, reverse=True)[:5]
599
+ scenario.scenario_name
600
+ for scenario in sorted(
601
+ optimization_result.optimization_scenarios, key=lambda x: x.annual_savings, reverse=True
602
+ )[:5]
570
603
  ],
571
604
  recommended_next_steps=[
572
605
  "Review and approve quick-win scenarios",
573
- "Establish implementation team and timeline",
606
+ "Establish implementation team and timeline",
574
607
  "Set up monitoring for cost optimization KPIs",
575
- "Schedule quarterly optimization reviews"
608
+ "Schedule quarterly optimization reviews",
576
609
  ],
577
610
  data_validation_status=optimization_result.mcp_validation_status,
578
- last_validated=datetime.now()
611
+ last_validated=datetime.now(),
579
612
  )
580
613
 
581
614
 
582
615
  # Export all schemas and utilities
583
616
  __all__ = [
584
617
  # Enums
585
- 'ComplexityLevel', 'RiskLevel', 'OptimizationCategory', 'ValidationStatus', 'ExportFormat',
586
-
618
+ "ComplexityLevel",
619
+ "RiskLevel",
620
+ "OptimizationCategory",
621
+ "ValidationStatus",
622
+ "ExportFormat",
587
623
  # Core schemas
588
- 'CostBreakdown', 'OptimizationScenario', 'CostOptimizationResult',
589
-
590
- # Business schemas
591
- 'ExecutiveSummary',
592
-
624
+ "CostBreakdown",
625
+ "OptimizationScenario",
626
+ "CostOptimizationResult",
627
+ # Business schemas
628
+ "ExecutiveSummary",
593
629
  # Technical validation schemas
594
- 'MCPValidationResult', 'FunctionalTestResult', 'ComprehensiveTestSuite',
595
-
630
+ "MCPValidationResult",
631
+ "FunctionalTestResult",
632
+ "ComprehensiveTestSuite",
596
633
  # Export schemas
597
- 'ExportMetadata',
598
-
634
+ "ExportMetadata",
599
635
  # Utility functions
600
- 'validate_cost_optimization_result', 'create_executive_summary',
601
-
636
+ "validate_cost_optimization_result",
637
+ "create_executive_summary",
602
638
  # Base schema
603
- 'BaseSchema'
604
- ]
639
+ "BaseSchema",
640
+ ]