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
@@ -4,20 +4,20 @@ Comprehensive 2-Way Validation System - Enterprise MCP Integration
4
4
  ========================================
5
5
 
6
6
  STRATEGIC ALIGNMENT:
7
- - Enhances MCP validation accuracy from 0.0% → ≥99.5% enterprise target
7
+ - Enhances MCP validation accuracy from 0.0% → ≥99.5% enterprise target
8
8
  - Focuses on successful modules: inventory, VPC, and FinOps
9
9
  - Implements cross-validation between runbooks outputs and MCP servers
10
10
  - Builds upon existing working evidence in ./awso_evidence/
11
11
  - Integrates with enterprise AWS profiles: BILLING_PROFILE, MANAGEMENT_PROFILE
12
12
 
13
13
  ENTERPRISE COORDINATION:
14
- - Primary Agent: qa-testing-specialist (validation framework excellence)
14
+ - Primary Agent: qa-testing-specialist (validation framework excellence)
15
15
  - Supporting Agent: python-runbooks-engineer (technical implementation)
16
16
  - Strategic Oversight: enterprise-product-owner (business impact validation)
17
17
 
18
18
  CORE CAPABILITIES:
19
19
  1. Real-time cross-validation between runbooks API and MCP servers
20
- 2. Terraform drift detection for infrastructure alignment
20
+ 2. Terraform drift detection for infrastructure alignment
21
21
  3. Evidence-based validation reports with accuracy metrics
22
22
  4. Discrepancy analysis with automated recommendations
23
23
  5. Performance benchmarking against enterprise <30s targets
@@ -43,19 +43,36 @@ from botocore.exceptions import ClientError
43
43
 
44
44
  # Enterprise Rich CLI standards (mandatory)
45
45
  from runbooks.common.rich_utils import (
46
- console, print_header, print_success, print_error, print_warning, print_info,
47
- create_table, create_progress_bar, format_cost, create_panel, STATUS_INDICATORS
46
+ console,
47
+ print_header,
48
+ print_success,
49
+ print_error,
50
+ print_warning,
51
+ print_info,
52
+ create_table,
53
+ create_progress_bar,
54
+ format_cost,
55
+ create_panel,
56
+ STATUS_INDICATORS,
48
57
  )
49
58
 
59
+ # ProfileManager integration for v1.1.x compatibility
60
+ from runbooks.common.aws_profile_manager import AWSProfileManager, get_current_account_id
61
+
50
62
  # Import MCP integration framework
51
- from notebooks.mcp_integration import (
52
- MCPIntegrationManager, CrossValidationEngine, MCPAWSClient,
53
- create_mcp_manager_for_single_account, create_mcp_manager_for_multi_account
63
+ from runbooks.mcp import (
64
+ MCPIntegrationManager,
65
+ CrossValidationEngine,
66
+ MCPAWSClient,
67
+ create_mcp_manager_for_single_account,
68
+ create_mcp_manager_for_multi_account,
54
69
  )
55
70
 
71
+
56
72
  @dataclass
57
73
  class ValidationDiscrepancy:
58
74
  """Structured validation discrepancy analysis."""
75
+
59
76
  source_name: str
60
77
  mcp_name: str
61
78
  field_name: str
@@ -66,55 +83,58 @@ class ValidationDiscrepancy:
66
83
  recommendation: str
67
84
  business_impact: str
68
85
 
86
+
69
87
  @dataclass
70
88
  class Comprehensive2WayValidationResult:
71
89
  """Complete validation result structure."""
90
+
72
91
  validation_id: str
73
92
  timestamp: datetime
74
93
  module_name: str
75
94
  validation_type: str
76
-
95
+
77
96
  # Core validation metrics
78
97
  total_validations_attempted: int
79
98
  successful_validations: int
80
99
  failed_validations: int
81
100
  validation_accuracy_percentage: float
82
-
101
+
83
102
  # Performance metrics
84
103
  total_execution_time_seconds: float
85
104
  average_validation_time_seconds: float
86
105
  performance_target_met: bool
87
-
106
+
88
107
  # Evidence and reporting
89
108
  discrepancies_found: List[ValidationDiscrepancy]
90
109
  evidence_files_generated: List[str]
91
110
  terraform_drift_detected: bool
92
-
111
+
93
112
  # Business impact assessment
94
113
  estimated_cost_impact: float
95
114
  risk_level: str
96
115
  stakeholder_confidence_score: float
97
116
  recommendations: List[str]
98
117
 
118
+
99
119
  class Comprehensive2WayValidator:
100
120
  """
101
121
  Enterprise 2-way validation system with MCP cross-validation.
102
-
122
+
103
123
  Provides comprehensive validation between runbooks outputs and MCP server data
104
124
  with enterprise-grade accuracy requirements and evidence generation.
105
125
  """
106
-
126
+
107
127
  def __init__(
108
128
  self,
109
129
  billing_profile: str = None,
110
- management_profile: str = None,
130
+ management_profile: str = None,
111
131
  single_account_profile: str = None,
112
132
  accuracy_target: float = 99.5,
113
- performance_target_seconds: float = 30.0
133
+ performance_target_seconds: float = 30.0,
114
134
  ):
115
135
  """
116
136
  Initialize comprehensive validation system with universal environment support.
117
-
137
+
118
138
  Args:
119
139
  billing_profile: AWS profile with Cost Explorer access (defaults to BILLING_PROFILE env var)
120
140
  management_profile: AWS profile with Organizations access (defaults to MANAGEMENT_PROFILE env var)
@@ -124,25 +144,25 @@ class Comprehensive2WayValidator:
124
144
  """
125
145
  # Universal environment support with fallbacks using proven profile pattern
126
146
  from runbooks.common.profile_utils import get_profile_for_operation
127
-
147
+
128
148
  self.billing_profile = billing_profile or get_profile_for_operation("billing", None)
129
149
  self.management_profile = management_profile or get_profile_for_operation("management", None)
130
150
  self.single_account_profile = single_account_profile or get_profile_for_operation("single_account", None)
131
151
  self.accuracy_target = accuracy_target
132
152
  self.performance_target_seconds = performance_target_seconds
133
-
153
+
134
154
  # Initialize evidence collection
135
155
  self.evidence_dir = Path("validation-evidence")
136
156
  self.evidence_dir.mkdir(parents=True, exist_ok=True)
137
-
157
+
138
158
  # Initialize MCP managers for different scenarios
139
159
  self.mcp_multi_account = create_mcp_manager_for_multi_account()
140
160
  self.mcp_single_account = create_mcp_manager_for_single_account()
141
-
161
+
142
162
  # Track validation sessions
143
163
  self.validation_sessions = []
144
164
  self.session_start_time = time.time()
145
-
165
+
146
166
  print_header("Comprehensive 2-Way Validation System", "1.0.0")
147
167
  print_info(f"🎯 Accuracy Target: ≥{accuracy_target}% (Enterprise Requirement)")
148
168
  print_info(f"⚡ Performance Target: <{performance_target_seconds}s operations")
@@ -150,93 +170,88 @@ class Comprehensive2WayValidator:
150
170
  print_info(f"🔍 Validation Scope: inventory, VPC, FinOps modules")
151
171
 
152
172
  async def validate_inventory_module(
153
- self,
154
- inventory_csv_path: str,
155
- account_scope: List[str] = None
173
+ self, inventory_csv_path: str, account_scope: List[str] = None
156
174
  ) -> Comprehensive2WayValidationResult:
157
175
  """
158
176
  Validate inventory module outputs against MCP data.
159
-
177
+
160
178
  Args:
161
179
  inventory_csv_path: Path to inventory CSV export
162
180
  account_scope: List of account IDs to validate (optional)
163
-
181
+
164
182
  Returns:
165
183
  Comprehensive validation results with accuracy metrics
166
184
  """
167
185
  validation_start = time.time()
168
186
  validation_id = f"inventory_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
169
-
187
+
170
188
  print_info(f"🔍 Validating Inventory Module: {validation_id}")
171
-
189
+
172
190
  discrepancies = []
173
191
  successful_validations = 0
174
192
  failed_validations = 0
175
193
  evidence_files = []
176
-
194
+
177
195
  try:
178
196
  # Load inventory data from runbooks export
179
197
  inventory_data = await self._load_inventory_export(inventory_csv_path)
180
- total_validations = len(inventory_data.get('resources', []))
181
-
198
+ total_validations = len(inventory_data.get("resources", []))
199
+
182
200
  print_info(f"📋 Inventory Resources Found: {total_validations}")
183
-
201
+
184
202
  # Cross-validate with MCP Organizations API
185
203
  with create_progress_bar() as progress:
186
- validation_task = progress.add_task(
187
- "[cyan]Cross-validating inventory data...",
188
- total=total_validations
189
- )
190
-
204
+ validation_task = progress.add_task("[cyan]Cross-validating inventory data...", total=total_validations)
205
+
191
206
  # Validate account discovery
192
207
  account_validation = await self._validate_account_discovery(inventory_data)
193
- if account_validation['status'] == 'validated':
208
+ if account_validation["status"] == "validated":
194
209
  successful_validations += 1
195
210
  else:
196
211
  failed_validations += 1
197
- if account_validation.get('discrepancy'):
198
- discrepancies.append(account_validation['discrepancy'])
199
-
212
+ if account_validation.get("discrepancy"):
213
+ discrepancies.append(account_validation["discrepancy"])
214
+
200
215
  progress.advance(validation_task, 1)
201
-
216
+
202
217
  # Validate resource counts by service
203
- for service_type in inventory_data.get('service_summary', {}):
218
+ for service_type in inventory_data.get("service_summary", {}):
204
219
  service_validation = await self._validate_service_resources(
205
220
  service_type, inventory_data, account_scope
206
221
  )
207
-
208
- if service_validation['status'] == 'validated':
222
+
223
+ if service_validation["status"] == "validated":
209
224
  successful_validations += 1
210
225
  else:
211
226
  failed_validations += 1
212
- if service_validation.get('discrepancy'):
213
- discrepancies.append(service_validation['discrepancy'])
214
-
227
+ if service_validation.get("discrepancy"):
228
+ discrepancies.append(service_validation["discrepancy"])
229
+
215
230
  progress.advance(validation_task)
216
-
231
+
217
232
  # Calculate accuracy metrics
218
233
  total_attempted = successful_validations + failed_validations
219
234
  accuracy_percentage = (successful_validations / total_attempted * 100) if total_attempted > 0 else 0
220
-
235
+
221
236
  # Generate evidence
222
237
  evidence_files = await self._generate_inventory_evidence(
223
238
  validation_id, inventory_data, discrepancies, accuracy_percentage
224
239
  )
225
-
240
+
226
241
  # Performance assessment
227
242
  execution_time = time.time() - validation_start
228
243
  performance_met = execution_time <= self.performance_target_seconds
229
-
244
+
230
245
  # Business impact analysis
231
246
  cost_impact = self._assess_inventory_cost_impact(discrepancies)
232
247
  risk_level = self._calculate_risk_level(accuracy_percentage, len(discrepancies))
233
248
  confidence_score = self._calculate_stakeholder_confidence(accuracy_percentage, risk_level)
234
-
249
+
235
250
  # Generate recommendations
236
251
  recommendations = self._generate_inventory_recommendations(
237
252
  accuracy_percentage, discrepancies, performance_met
238
253
  )
239
-
254
+
240
255
  validation_result = Comprehensive2WayValidationResult(
241
256
  validation_id=validation_id,
242
257
  timestamp=datetime.now(),
@@ -255,17 +270,17 @@ class Comprehensive2WayValidator:
255
270
  estimated_cost_impact=cost_impact,
256
271
  risk_level=risk_level,
257
272
  stakeholder_confidence_score=confidence_score,
258
- recommendations=recommendations
273
+ recommendations=recommendations,
259
274
  )
260
-
275
+
261
276
  self.validation_sessions.append(validation_result)
262
277
  await self._display_validation_summary(validation_result)
263
-
278
+
264
279
  return validation_result
265
-
280
+
266
281
  except Exception as e:
267
282
  print_error(f"❌ Inventory validation failed: {str(e)}")
268
-
283
+
269
284
  # Return failure result
270
285
  execution_time = time.time() - validation_start
271
286
  return Comprehensive2WayValidationResult(
@@ -286,123 +301,123 @@ class Comprehensive2WayValidator:
286
301
  estimated_cost_impact=0.0,
287
302
  risk_level="high",
288
303
  stakeholder_confidence_score=0.0,
289
- recommendations=[f"⚠️ Critical: Address validation failure - {str(e)}"]
304
+ recommendations=[f"⚠️ Critical: Address validation failure - {str(e)}"],
290
305
  )
291
306
 
292
307
  async def validate_vpc_module(
293
- self,
294
- vpc_analysis_path: str,
295
- include_cost_correlation: bool = True
308
+ self, vpc_analysis_path: str, include_cost_correlation: bool = True
296
309
  ) -> Comprehensive2WayValidationResult:
297
310
  """
298
311
  Validate VPC module outputs with cost correlation analysis.
299
-
312
+
300
313
  Args:
301
314
  vpc_analysis_path: Path to VPC analysis results
302
315
  include_cost_correlation: Include FinOps cost correlation validation
303
-
316
+
304
317
  Returns:
305
318
  Comprehensive VPC validation results
306
319
  """
307
320
  validation_start = time.time()
308
321
  validation_id = f"vpc_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
309
-
322
+
310
323
  print_info(f"🔍 Validating VPC Module: {validation_id}")
311
-
324
+
312
325
  discrepancies = []
313
326
  successful_validations = 0
314
327
  failed_validations = 0
315
328
  evidence_files = []
316
-
329
+
317
330
  try:
318
331
  # Load VPC analysis data
319
332
  vpc_data = await self._load_vpc_analysis(vpc_analysis_path)
320
- total_validations = len(vpc_data.get('vpcs', []))
321
-
333
+ total_validations = len(vpc_data.get("vpcs", []))
334
+
322
335
  print_info(f"🌐 VPC Resources Found: {total_validations}")
323
-
336
+
324
337
  # Cross-validate with MCP EC2 API
325
338
  with create_progress_bar() as progress:
326
339
  validation_task = progress.add_task(
327
- "[cyan]Cross-validating VPC data...",
328
- total=total_validations + (1 if include_cost_correlation else 0)
340
+ "[cyan]Cross-validating VPC data...",
341
+ total=total_validations + (1 if include_cost_correlation else 0),
329
342
  )
330
-
343
+
331
344
  # Validate VPC configurations
332
- for vpc in vpc_data.get('vpcs', []):
345
+ for vpc in vpc_data.get("vpcs", []):
333
346
  vpc_validation = await self._validate_vpc_configuration(vpc)
334
-
335
- if vpc_validation['status'] == 'validated':
347
+
348
+ if vpc_validation["status"] == "validated":
336
349
  successful_validations += 1
337
350
  else:
338
351
  failed_validations += 1
339
- if vpc_validation.get('discrepancy'):
340
- discrepancies.append(vpc_validation['discrepancy'])
341
-
352
+ if vpc_validation.get("discrepancy"):
353
+ discrepancies.append(vpc_validation["discrepancy"])
354
+
342
355
  progress.advance(validation_task)
343
-
356
+
344
357
  # Cost correlation validation (if requested)
345
358
  if include_cost_correlation:
346
359
  cost_validation = await self._validate_vpc_cost_correlation(vpc_data)
347
-
348
- if cost_validation['status'] == 'validated':
360
+
361
+ if cost_validation["status"] == "validated":
349
362
  successful_validations += 1
350
363
  else:
351
364
  failed_validations += 1
352
- if cost_validation.get('discrepancy'):
353
- discrepancies.append(cost_validation['discrepancy'])
354
-
365
+ if cost_validation.get("discrepancy"):
366
+ discrepancies.append(cost_validation["discrepancy"])
367
+
355
368
  progress.advance(validation_task)
356
-
369
+
357
370
  # Enhanced accuracy calculation following proven patterns from Cost Explorer and Organizations fixes
358
371
  total_attempted = successful_validations + failed_validations
359
-
372
+
360
373
  # Calculate weighted accuracy considering validation quality scores
361
374
  weighted_accuracy_score = 0.0
362
375
  total_possible_score = 0.0
363
-
376
+
364
377
  # Re-process validations to calculate weighted accuracy
365
378
  if total_attempted > 0:
366
- for vpc in vpc_data.get('vpcs', []):
379
+ for vpc in vpc_data.get("vpcs", []):
367
380
  vpc_validation = await self._validate_vpc_configuration(vpc)
368
- validation_accuracy = vpc_validation.get('accuracy_percentage', 0.0)
381
+ validation_accuracy = vpc_validation.get("accuracy_percentage", 0.0)
369
382
  weighted_accuracy_score += validation_accuracy
370
383
  total_possible_score += 100.0
371
-
384
+
372
385
  # Add cost correlation validation to weighted calculation
373
386
  if include_cost_correlation:
374
387
  cost_validation = await self._validate_vpc_cost_correlation(vpc_data)
375
- correlation_accuracy = cost_validation.get('correlation_accuracy', 0.0)
388
+ correlation_accuracy = cost_validation.get("correlation_accuracy", 0.0)
376
389
  weighted_accuracy_score += correlation_accuracy
377
390
  total_possible_score += 100.0
378
-
391
+
379
392
  # Calculate final weighted accuracy percentage
380
- accuracy_percentage = (weighted_accuracy_score / total_possible_score) if total_possible_score > 0 else 0.0
381
-
393
+ accuracy_percentage = (
394
+ (weighted_accuracy_score / total_possible_score) if total_possible_score > 0 else 0.0
395
+ )
396
+
382
397
  # Apply accuracy enhancement factors (following Cost Explorer pattern)
383
398
  if accuracy_percentage > 0:
384
399
  # Bonus for comprehensive data validation
385
- if len(vpc_data.get('vpcs', [])) > 0:
386
- data_completeness_bonus = min(5.0, len(vpc_data.get('vpcs', [])) * 0.5)
400
+ if len(vpc_data.get("vpcs", [])) > 0:
401
+ data_completeness_bonus = min(5.0, len(vpc_data.get("vpcs", [])) * 0.5)
387
402
  accuracy_percentage = min(100.0, accuracy_percentage + data_completeness_bonus)
388
-
403
+
389
404
  # Penalty for validation errors
390
405
  if len(discrepancies) > 0:
391
406
  error_penalty = min(accuracy_percentage * 0.1, len(discrepancies) * 2.0)
392
407
  accuracy_percentage = max(0.0, accuracy_percentage - error_penalty)
393
-
408
+
394
409
  # Enhance accuracy for consistent validation patterns (Cost Explorer methodology)
395
410
  if accuracy_percentage >= 80.0:
396
411
  consistency_bonus = min(5.0, (accuracy_percentage - 80.0) * 0.2)
397
412
  accuracy_percentage = min(100.0, accuracy_percentage + consistency_bonus)
398
413
  else:
399
414
  accuracy_percentage = 0.0
400
-
415
+
401
416
  # Generate evidence
402
417
  evidence_files = await self._generate_vpc_evidence(
403
418
  validation_id, vpc_data, discrepancies, accuracy_percentage
404
419
  )
405
-
420
+
406
421
  # Performance and business impact
407
422
  execution_time = time.time() - validation_start
408
423
  performance_met = execution_time <= self.performance_target_seconds
@@ -410,7 +425,7 @@ class Comprehensive2WayValidator:
410
425
  risk_level = self._calculate_risk_level(accuracy_percentage, len(discrepancies))
411
426
  confidence_score = self._calculate_stakeholder_confidence(accuracy_percentage, risk_level)
412
427
  recommendations = self._generate_vpc_recommendations(accuracy_percentage, discrepancies)
413
-
428
+
414
429
  validation_result = Comprehensive2WayValidationResult(
415
430
  validation_id=validation_id,
416
431
  timestamp=datetime.now(),
@@ -429,17 +444,17 @@ class Comprehensive2WayValidator:
429
444
  estimated_cost_impact=cost_impact,
430
445
  risk_level=risk_level,
431
446
  stakeholder_confidence_score=confidence_score,
432
- recommendations=recommendations
447
+ recommendations=recommendations,
433
448
  )
434
-
449
+
435
450
  self.validation_sessions.append(validation_result)
436
451
  await self._display_validation_summary(validation_result)
437
-
452
+
438
453
  return validation_result
439
-
454
+
440
455
  except Exception as e:
441
456
  print_error(f"❌ VPC validation failed: {str(e)}")
442
-
457
+
443
458
  execution_time = time.time() - validation_start
444
459
  return Comprehensive2WayValidationResult(
445
460
  validation_id=validation_id,
@@ -459,97 +474,97 @@ class Comprehensive2WayValidator:
459
474
  estimated_cost_impact=0.0,
460
475
  risk_level="high",
461
476
  stakeholder_confidence_score=0.0,
462
- recommendations=[f"⚠️ Critical: Address validation failure - {str(e)}"]
477
+ recommendations=[f"⚠️ Critical: Address validation failure - {str(e)}"],
463
478
  )
464
479
 
465
480
  async def validate_finops_module(
466
- self,
467
- finops_export_path: str,
468
- include_quarterly_analysis: bool = True
481
+ self, finops_export_path: str, include_quarterly_analysis: bool = True
469
482
  ) -> Comprehensive2WayValidationResult:
470
483
  """
471
484
  Validate FinOps module with enhanced MCP Cost Explorer integration.
472
-
485
+
473
486
  Args:
474
487
  finops_export_path: Path to FinOps export data
475
488
  include_quarterly_analysis: Include quarterly intelligence validation
476
-
489
+
477
490
  Returns:
478
491
  Comprehensive FinOps validation results
479
492
  """
480
493
  validation_start = time.time()
481
494
  validation_id = f"finops_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
482
-
495
+
483
496
  print_info(f"🔍 Validating FinOps Module: {validation_id}")
484
497
  print_info("💰 Targeting MCP accuracy improvement: 0.0% → ≥99.5%")
485
-
498
+
486
499
  discrepancies = []
487
500
  successful_validations = 0
488
501
  failed_validations = 0
489
502
  evidence_files = []
490
-
503
+
491
504
  try:
492
505
  # Load FinOps data
493
506
  finops_data = await self._load_finops_export(finops_export_path)
494
-
507
+
495
508
  # Enhanced MCP time synchronization (critical for accuracy)
496
509
  mcp_validation_data = await self._get_time_synchronized_cost_data(finops_data)
497
-
510
+
498
511
  print_info(f"💼 Cost Analysis Items: {len(finops_data.get('cost_breakdown', []))}")
499
-
512
+
500
513
  with create_progress_bar() as progress:
501
514
  validation_task = progress.add_task(
502
- "[cyan]Cross-validating FinOps data with MCP Cost Explorer...",
503
- total=5 # Core validation categories
515
+ "[cyan]Cross-validating FinOps data with MCP Cost Explorer...",
516
+ total=5, # Core validation categories
504
517
  )
505
-
518
+
506
519
  # 1. Total cost validation (enhanced time sync)
507
- total_cost_validation = await self._validate_total_cost_with_time_sync(
508
- finops_data, mcp_validation_data
520
+ total_cost_validation = await self._validate_total_cost_with_time_sync(finops_data, mcp_validation_data)
521
+ self._process_validation_result(
522
+ total_cost_validation, successful_validations, failed_validations, discrepancies
509
523
  )
510
- self._process_validation_result(total_cost_validation, successful_validations, failed_validations, discrepancies)
511
524
  progress.advance(validation_task)
512
-
513
- # 2. Service-level cost breakdown validation
514
- service_validation = await self._validate_service_breakdown_accuracy(
515
- finops_data, mcp_validation_data
525
+
526
+ # 2. Service-level cost breakdown validation
527
+ service_validation = await self._validate_service_breakdown_accuracy(finops_data, mcp_validation_data)
528
+ self._process_validation_result(
529
+ service_validation, successful_validations, failed_validations, discrepancies
516
530
  )
517
- self._process_validation_result(service_validation, successful_validations, failed_validations, discrepancies)
518
531
  progress.advance(validation_task)
519
-
532
+
520
533
  # 3. Account-level cost distribution validation
521
- account_validation = await self._validate_account_cost_distribution(
522
- finops_data, mcp_validation_data
534
+ account_validation = await self._validate_account_cost_distribution(finops_data, mcp_validation_data)
535
+ self._process_validation_result(
536
+ account_validation, successful_validations, failed_validations, discrepancies
523
537
  )
524
- self._process_validation_result(account_validation, successful_validations, failed_validations, discrepancies)
525
538
  progress.advance(validation_task)
526
-
539
+
527
540
  # 4. Quarterly intelligence validation (if requested)
528
541
  if include_quarterly_analysis:
529
- quarterly_validation = await self._validate_quarterly_intelligence(
530
- finops_data, mcp_validation_data
542
+ quarterly_validation = await self._validate_quarterly_intelligence(finops_data, mcp_validation_data)
543
+ self._process_validation_result(
544
+ quarterly_validation, successful_validations, failed_validations, discrepancies
531
545
  )
532
- self._process_validation_result(quarterly_validation, successful_validations, failed_validations, discrepancies)
533
546
  progress.advance(validation_task)
534
-
547
+
535
548
  # 5. Cost optimization recommendations validation
536
549
  optimization_validation = await self._validate_cost_optimization_accuracy(
537
550
  finops_data, mcp_validation_data
538
551
  )
539
- self._process_validation_result(optimization_validation, successful_validations, failed_validations, discrepancies)
552
+ self._process_validation_result(
553
+ optimization_validation, successful_validations, failed_validations, discrepancies
554
+ )
540
555
  progress.advance(validation_task)
541
-
556
+
542
557
  # Calculate enhanced accuracy metrics
543
558
  total_attempted = successful_validations + failed_validations
544
559
  accuracy_percentage = (successful_validations / total_attempted * 100) if total_attempted > 0 else 0
545
-
560
+
546
561
  print_success(f"🎯 MCP Validation Accuracy Achieved: {accuracy_percentage:.1f}%")
547
-
562
+
548
563
  # Generate comprehensive evidence
549
564
  evidence_files = await self._generate_finops_evidence(
550
565
  validation_id, finops_data, mcp_validation_data, discrepancies, accuracy_percentage
551
566
  )
552
-
567
+
553
568
  # Business impact and performance metrics
554
569
  execution_time = time.time() - validation_start
555
570
  performance_met = execution_time <= self.performance_target_seconds
@@ -557,7 +572,7 @@ class Comprehensive2WayValidator:
557
572
  risk_level = self._calculate_risk_level(accuracy_percentage, len(discrepancies))
558
573
  confidence_score = self._calculate_stakeholder_confidence(accuracy_percentage, risk_level)
559
574
  recommendations = self._generate_finops_recommendations(accuracy_percentage, discrepancies)
560
-
575
+
561
576
  validation_result = Comprehensive2WayValidationResult(
562
577
  validation_id=validation_id,
563
578
  timestamp=datetime.now(),
@@ -576,17 +591,17 @@ class Comprehensive2WayValidator:
576
591
  estimated_cost_impact=cost_impact,
577
592
  risk_level=risk_level,
578
593
  stakeholder_confidence_score=confidence_score,
579
- recommendations=recommendations
594
+ recommendations=recommendations,
580
595
  )
581
-
596
+
582
597
  self.validation_sessions.append(validation_result)
583
598
  await self._display_validation_summary(validation_result)
584
-
599
+
585
600
  return validation_result
586
-
601
+
587
602
  except Exception as e:
588
603
  print_error(f"❌ FinOps validation failed: {str(e)}")
589
-
604
+
590
605
  execution_time = time.time() - validation_start
591
606
  return Comprehensive2WayValidationResult(
592
607
  validation_id=validation_id,
@@ -606,103 +621,104 @@ class Comprehensive2WayValidator:
606
621
  estimated_cost_impact=0.0,
607
622
  risk_level="critical",
608
623
  stakeholder_confidence_score=0.0,
609
- recommendations=[f"🚨 Critical: Address validation failure - {str(e)}"]
624
+ recommendations=[f"🚨 Critical: Address validation failure - {str(e)}"],
610
625
  )
611
626
 
612
627
  def _process_validation_result(self, validation_result: Dict, successful: int, failed: int, discrepancies: List):
613
628
  """Process individual validation result and update counters."""
614
- if validation_result['status'] == 'validated':
629
+ if validation_result["status"] == "validated":
615
630
  successful += 1
616
631
  else:
617
632
  failed += 1
618
- if validation_result.get('discrepancy'):
619
- discrepancies.append(validation_result['discrepancy'])
633
+ if validation_result.get("discrepancy"):
634
+ discrepancies.append(validation_result["discrepancy"])
620
635
 
621
636
  async def run_comprehensive_validation_suite(
622
637
  self,
623
638
  inventory_csv: Optional[str] = None,
624
639
  vpc_analysis: Optional[str] = None,
625
- finops_export: Optional[str] = None
640
+ finops_export: Optional[str] = None,
626
641
  ) -> Dict[str, Any]:
627
642
  """
628
643
  Run comprehensive validation across all supported modules.
629
-
644
+
630
645
  Args:
631
646
  inventory_csv: Path to inventory export CSV
632
- vpc_analysis: Path to VPC analysis results
647
+ vpc_analysis: Path to VPC analysis results
633
648
  finops_export: Path to FinOps export data
634
-
649
+
635
650
  Returns:
636
651
  Consolidated validation report across all modules
637
652
  """
638
653
  suite_start = time.time()
639
654
  print_header("Comprehensive 2-Way Validation Suite", "Enterprise Execution")
640
-
655
+
641
656
  suite_results = {
642
- 'timestamp': datetime.now().isoformat(),
643
- 'total_modules_tested': 0,
644
- 'modules_passed': 0,
645
- 'overall_accuracy': 0.0,
646
- 'enterprise_target_met': False,
647
- 'validation_results': [],
648
- 'consolidated_recommendations': [],
649
- 'business_impact_summary': {}
657
+ "timestamp": datetime.now().isoformat(),
658
+ "total_modules_tested": 0,
659
+ "modules_passed": 0,
660
+ "overall_accuracy": 0.0,
661
+ "enterprise_target_met": False,
662
+ "validation_results": [],
663
+ "consolidated_recommendations": [],
664
+ "business_impact_summary": {},
650
665
  }
651
-
666
+
652
667
  # Run validation for each available module
653
668
  module_results = []
654
-
669
+
655
670
  if inventory_csv and Path(inventory_csv).exists():
656
671
  print_info("🔍 Starting Inventory Module Validation...")
657
672
  inventory_result = await self.validate_inventory_module(inventory_csv)
658
673
  module_results.append(inventory_result)
659
- suite_results['total_modules_tested'] += 1
660
-
674
+ suite_results["total_modules_tested"] += 1
675
+
661
676
  if vpc_analysis and Path(vpc_analysis).exists():
662
677
  print_info("🌐 Starting VPC Module Validation...")
663
678
  vpc_result = await self.validate_vpc_module(vpc_analysis)
664
679
  module_results.append(vpc_result)
665
- suite_results['total_modules_tested'] += 1
666
-
680
+ suite_results["total_modules_tested"] += 1
681
+
667
682
  if finops_export and Path(finops_export).exists():
668
683
  print_info("💰 Starting FinOps Module Validation...")
669
684
  finops_result = await self.validate_finops_module(finops_export)
670
685
  module_results.append(finops_result)
671
- suite_results['total_modules_tested'] += 1
672
-
686
+ suite_results["total_modules_tested"] += 1
687
+
673
688
  # Calculate consolidated metrics
674
689
  if module_results:
675
690
  total_accuracy = sum(r.validation_accuracy_percentage for r in module_results)
676
- suite_results['overall_accuracy'] = total_accuracy / len(module_results)
677
- suite_results['modules_passed'] = sum(1 for r in module_results
678
- if r.validation_accuracy_percentage >= self.accuracy_target)
679
- suite_results['enterprise_target_met'] = suite_results['overall_accuracy'] >= self.accuracy_target
680
-
691
+ suite_results["overall_accuracy"] = total_accuracy / len(module_results)
692
+ suite_results["modules_passed"] = sum(
693
+ 1 for r in module_results if r.validation_accuracy_percentage >= self.accuracy_target
694
+ )
695
+ suite_results["enterprise_target_met"] = suite_results["overall_accuracy"] >= self.accuracy_target
696
+
681
697
  # Consolidate results
682
- suite_results['validation_results'] = [asdict(r) for r in module_results]
683
- suite_results['consolidated_recommendations'] = self._consolidate_recommendations(module_results)
684
- suite_results['business_impact_summary'] = self._consolidate_business_impact(module_results)
685
-
698
+ suite_results["validation_results"] = [asdict(r) for r in module_results]
699
+ suite_results["consolidated_recommendations"] = self._consolidate_recommendations(module_results)
700
+ suite_results["business_impact_summary"] = self._consolidate_business_impact(module_results)
701
+
686
702
  # Generate comprehensive suite report
687
703
  suite_execution_time = time.time() - suite_start
688
704
  suite_report_path = await self._generate_suite_report(suite_results, suite_execution_time)
689
-
705
+
690
706
  # Display enterprise summary
691
707
  await self._display_suite_summary(suite_results, suite_execution_time)
692
-
708
+
693
709
  return {
694
710
  **suite_results,
695
- 'suite_execution_time_seconds': suite_execution_time,
696
- 'suite_report_path': suite_report_path
711
+ "suite_execution_time_seconds": suite_execution_time,
712
+ "suite_report_path": suite_report_path,
697
713
  }
698
714
 
699
715
  async def _display_validation_summary(self, result: Comprehensive2WayValidationResult):
700
716
  """Display validation summary with enterprise formatting."""
701
-
717
+
702
718
  # Status determination
703
719
  status_color = "green" if result.validation_accuracy_percentage >= self.accuracy_target else "red"
704
720
  status_text = "✅ PASSED" if result.validation_accuracy_percentage >= self.accuracy_target else "❌ FAILED"
705
-
721
+
706
722
  # Create summary table
707
723
  summary_table = create_table(
708
724
  title=f"Validation Summary: {result.module_name.upper()}",
@@ -710,47 +726,47 @@ class Comprehensive2WayValidator:
710
726
  {"name": "Metric", "style": "cyan", "width": 30},
711
727
  {"name": "Value", "style": "white", "justify": "right"},
712
728
  {"name": "Target", "style": "yellow", "justify": "right"},
713
- {"name": "Status", "style": status_color, "justify": "center"}
714
- ]
729
+ {"name": "Status", "style": status_color, "justify": "center"},
730
+ ],
715
731
  )
716
-
732
+
717
733
  summary_table.add_row(
718
734
  "Validation Accuracy",
719
735
  f"{result.validation_accuracy_percentage:.1f}%",
720
736
  f"≥{self.accuracy_target}%",
721
- "✅" if result.validation_accuracy_percentage >= self.accuracy_target else "❌"
737
+ "✅" if result.validation_accuracy_percentage >= self.accuracy_target else "❌",
722
738
  )
723
-
739
+
724
740
  summary_table.add_row(
725
741
  "Execution Time",
726
742
  f"{result.total_execution_time_seconds:.1f}s",
727
743
  f"<{self.performance_target_seconds}s",
728
- "✅" if result.performance_target_met else "❌"
744
+ "✅" if result.performance_target_met else "❌",
729
745
  )
730
-
746
+
731
747
  summary_table.add_row(
732
748
  "Validations Successful",
733
749
  str(result.successful_validations),
734
750
  str(result.total_validations_attempted),
735
- "✅" if result.failed_validations == 0 else "⚠️"
751
+ "✅" if result.failed_validations == 0 else "⚠️",
736
752
  )
737
-
753
+
738
754
  summary_table.add_row(
739
755
  "Discrepancies Found",
740
756
  str(len(result.discrepancies_found)),
741
757
  "0",
742
- "✅" if len(result.discrepancies_found) == 0 else "⚠️"
758
+ "✅" if len(result.discrepancies_found) == 0 else "⚠️",
743
759
  )
744
-
760
+
745
761
  summary_table.add_row(
746
762
  "Risk Level",
747
763
  result.risk_level.upper(),
748
764
  "LOW",
749
- "✅" if result.risk_level == "low" else "⚠️" if result.risk_level == "medium" else "❌"
765
+ "✅" if result.risk_level == "low" else "⚠️" if result.risk_level == "medium" else "❌",
750
766
  )
751
-
767
+
752
768
  console.print(summary_table)
753
-
769
+
754
770
  # Display critical discrepancies if any
755
771
  if result.discrepancies_found:
756
772
  discrepancy_table = create_table(
@@ -760,48 +776,48 @@ class Comprehensive2WayValidator:
760
776
  {"name": "Source Value", "style": "green"},
761
777
  {"name": "MCP Value", "style": "yellow"},
762
778
  {"name": "Variance", "style": "red"},
763
- {"name": "Severity", "style": "magenta"}
764
- ]
779
+ {"name": "Severity", "style": "magenta"},
780
+ ],
765
781
  )
766
-
782
+
767
783
  for disc in result.discrepancies_found[:5]: # Show top 5
768
784
  discrepancy_table.add_row(
769
785
  disc.field_name,
770
786
  str(disc.source_value),
771
787
  str(disc.mcp_value),
772
788
  f"{disc.variance_percentage:.1f}%",
773
- disc.severity.upper()
789
+ disc.severity.upper(),
774
790
  )
775
-
791
+
776
792
  console.print(discrepancy_table)
777
-
793
+
778
794
  # Display recommendations
779
795
  if result.recommendations:
780
796
  recommendations_panel = create_panel(
781
797
  "\n".join(f"• {rec}" for rec in result.recommendations[:3]),
782
798
  title="Key Recommendations",
783
- border_style="yellow"
799
+ border_style="yellow",
784
800
  )
785
801
  console.print(recommendations_panel)
786
-
802
+
787
803
  print_success(f"📊 Validation completed: {status_text}")
788
804
  if result.evidence_files_generated:
789
805
  print_info(f"📄 Evidence files: {len(result.evidence_files_generated)} generated")
790
806
 
791
807
  async def _display_suite_summary(self, suite_results: Dict, execution_time: float):
792
808
  """Display comprehensive suite summary."""
793
-
794
- overall_status = "✅ ENTERPRISE TARGET MET" if suite_results['enterprise_target_met'] else "❌ BELOW TARGET"
795
- status_color = "green" if suite_results['enterprise_target_met'] else "red"
796
-
809
+
810
+ overall_status = "✅ ENTERPRISE TARGET MET" if suite_results["enterprise_target_met"] else "❌ BELOW TARGET"
811
+ status_color = "green" if suite_results["enterprise_target_met"] else "red"
812
+
797
813
  # Create enterprise summary panel
798
814
  enterprise_summary = f"""
799
815
  🎯 ENTERPRISE VALIDATION SUITE COMPLETE
800
816
 
801
817
  📊 Overall Results:
802
- • Modules Tested: {suite_results['total_modules_tested']}
803
- • Modules Passed: {suite_results['modules_passed']}
804
- • Overall Accuracy: {suite_results['overall_accuracy']:.1f}%
818
+ • Modules Tested: {suite_results["total_modules_tested"]}
819
+ • Modules Passed: {suite_results["modules_passed"]}
820
+ • Overall Accuracy: {suite_results["overall_accuracy"]:.1f}%
805
821
  • Enterprise Target: ≥{self.accuracy_target}%
806
822
 
807
823
  ⚡ Performance:
@@ -815,16 +831,14 @@ class Comprehensive2WayValidator:
815
831
  • Compliance: SOX, SOC2, regulatory audit trail support
816
832
  • Risk Mitigation: Comprehensive discrepancy detection
817
833
  """
818
-
834
+
819
835
  enterprise_panel = create_panel(
820
- enterprise_summary,
821
- title="Enterprise Validation Suite Results",
822
- border_style=status_color
836
+ enterprise_summary, title="Enterprise Validation Suite Results", border_style=status_color
823
837
  )
824
-
838
+
825
839
  console.print(enterprise_panel)
826
-
827
- if suite_results['enterprise_target_met']:
840
+
841
+ if suite_results["enterprise_target_met"]:
828
842
  print_success("🏆 ENTERPRISE SUCCESS: ≥99.5% validation accuracy achieved!")
829
843
  print_success("📈 Ready for stakeholder presentation with confidence")
830
844
  else:
@@ -836,30 +850,41 @@ class Comprehensive2WayValidator:
836
850
  """Load inventory export data for validation."""
837
851
  try:
838
852
  import pandas as pd
853
+
839
854
  df = pd.read_csv(csv_path)
840
-
855
+
841
856
  return {
842
- 'resources': df.to_dict('records'),
843
- 'total_resources': len(df),
844
- 'service_summary': df['Resource Type'].value_counts().to_dict(),
845
- 'account_summary': df['Account'].value_counts().to_dict() if 'Account' in df.columns else {}
857
+ "resources": df.to_dict("records"),
858
+ "total_resources": len(df),
859
+ "service_summary": df["Resource Type"].value_counts().to_dict(),
860
+ "account_summary": df["Account"].value_counts().to_dict() if "Account" in df.columns else {},
846
861
  }
847
862
  except Exception as e:
848
863
  print_warning(f"Using mock inventory data due to loading error: {e}")
849
- # Use environment-driven account ID for universal compatibility
850
- generic_account_id = os.getenv("AWS_ACCOUNT_ID", "123456789012")
864
+ # Use dynamic account ID for universal compatibility
865
+ profile_manager = AWSProfileManager()
866
+ generic_account_id = profile_manager.get_account_id()
851
867
  generic_region = os.getenv("AWS_DEFAULT_REGION", "us-east-1")
852
868
  return {
853
- 'resources': [{'Account': generic_account_id, 'Region': generic_region, 'Resource Type': 'S3', 'Resource ID': 'test-bucket', 'Name': 'test', 'Status': 'available'}],
854
- 'total_resources': 1,
855
- 'service_summary': {'S3': 1},
856
- 'account_summary': {generic_account_id: 1}
869
+ "resources": [
870
+ {
871
+ "Account": generic_account_id,
872
+ "Region": generic_region,
873
+ "Resource Type": "S3",
874
+ "Resource ID": "test-bucket",
875
+ "Name": "test",
876
+ "Status": "available",
877
+ }
878
+ ],
879
+ "total_resources": 1,
880
+ "service_summary": {"S3": 1},
881
+ "account_summary": {generic_account_id: 1},
857
882
  }
858
883
 
859
884
  async def _load_vpc_analysis(self, analysis_path: str) -> Dict[str, Any]:
860
885
  """
861
886
  Load VPC analysis data for validation with enhanced accuracy.
862
-
887
+
863
888
  Following proven patterns from Cost Explorer and Organizations fixes:
864
889
  - Robust data loading with comprehensive error handling
865
890
  - Real AWS data only (no mock data fallbacks)
@@ -867,134 +892,130 @@ class Comprehensive2WayValidator:
867
892
  """
868
893
  try:
869
894
  file_path = Path(analysis_path)
870
-
895
+
871
896
  # Validate file exists and is readable
872
897
  if not file_path.exists():
873
898
  print_error(f"VPC analysis file not found: {analysis_path}")
874
899
  raise FileNotFoundError(f"VPC analysis file not found: {analysis_path}")
875
-
900
+
876
901
  if not file_path.is_file():
877
902
  print_error(f"VPC analysis path is not a file: {analysis_path}")
878
903
  raise ValueError(f"VPC analysis path is not a file: {analysis_path}")
879
-
904
+
880
905
  # Load data based on file type
881
- if analysis_path.endswith('.json'):
906
+ if analysis_path.endswith(".json"):
882
907
  print_info(f"Loading VPC analysis from JSON: {analysis_path}")
883
- with open(analysis_path, 'r') as f:
908
+ with open(analysis_path, "r") as f:
884
909
  data = json.load(f)
885
-
910
+
886
911
  # Validate required data structure
887
912
  if not isinstance(data, dict):
888
913
  print_error("VPC analysis data must be a dictionary")
889
914
  raise ValueError("VPC analysis data must be a dictionary")
890
-
915
+
891
916
  # Ensure VPCs data exists
892
- if 'vpcs' not in data:
917
+ if "vpcs" not in data:
893
918
  print_warning("No 'vpcs' key found in VPC analysis data")
894
919
  # Try common alternative keys
895
- if 'Vpcs' in data:
896
- data['vpcs'] = data['Vpcs']
920
+ if "Vpcs" in data:
921
+ data["vpcs"] = data["Vpcs"]
897
922
  print_info("Mapped 'Vpcs' to 'vpcs' key")
898
- elif 'vpc_list' in data:
899
- data['vpcs'] = data['vpc_list']
923
+ elif "vpc_list" in data:
924
+ data["vpcs"] = data["vpc_list"]
900
925
  print_info("Mapped 'vpc_list' to 'vpcs' key")
901
926
  else:
902
- data['vpcs'] = []
927
+ data["vpcs"] = []
903
928
  print_warning("No VPC data found - using empty list")
904
-
929
+
905
930
  # Validate VPC data structure
906
- vpcs = data.get('vpcs', [])
931
+ vpcs = data.get("vpcs", [])
907
932
  if not isinstance(vpcs, list):
908
933
  print_error("VPCs data must be a list")
909
934
  raise ValueError("VPCs data must be a list")
910
-
935
+
911
936
  # Enhanced data validation and standardization
912
937
  validated_vpcs = []
913
938
  for i, vpc in enumerate(vpcs):
914
939
  if not isinstance(vpc, dict):
915
940
  print_warning(f"Skipping invalid VPC entry {i}: not a dictionary")
916
941
  continue
917
-
942
+
918
943
  # Ensure critical VPC fields are present
919
- vpc_id = vpc.get('VpcId') or vpc.get('vpc_id') or vpc.get('id')
944
+ vpc_id = vpc.get("VpcId") or vpc.get("vpc_id") or vpc.get("id")
920
945
  if not vpc_id:
921
946
  print_warning(f"Skipping VPC entry {i}: missing VPC ID")
922
947
  continue
923
-
948
+
924
949
  # Standardize VPC data structure
925
950
  standardized_vpc = {
926
- 'VpcId': vpc_id,
927
- 'State': vpc.get('State', vpc.get('state', 'unknown')),
928
- 'CidrBlock': vpc.get('CidrBlock', vpc.get('cidr_block', vpc.get('cidr', ''))),
929
- 'OwnerId': vpc.get('OwnerId', vpc.get('owner_id', vpc.get('account_id', ''))),
930
- 'IsDefault': vpc.get('IsDefault', vpc.get('is_default', False)),
931
- 'DhcpOptionsId': vpc.get('DhcpOptionsId', vpc.get('dhcp_options_id', '')),
932
- 'InstanceTenancy': vpc.get('InstanceTenancy', vpc.get('instance_tenancy', '')),
933
- 'Tags': vpc.get('Tags', vpc.get('tags', []))
951
+ "VpcId": vpc_id,
952
+ "State": vpc.get("State", vpc.get("state", "unknown")),
953
+ "CidrBlock": vpc.get("CidrBlock", vpc.get("cidr_block", vpc.get("cidr", ""))),
954
+ "OwnerId": vpc.get("OwnerId", vpc.get("owner_id", vpc.get("account_id", ""))),
955
+ "IsDefault": vpc.get("IsDefault", vpc.get("is_default", False)),
956
+ "DhcpOptionsId": vpc.get("DhcpOptionsId", vpc.get("dhcp_options_id", "")),
957
+ "InstanceTenancy": vpc.get("InstanceTenancy", vpc.get("instance_tenancy", "")),
958
+ "Tags": vpc.get("Tags", vpc.get("tags", [])),
934
959
  }
935
-
960
+
936
961
  validated_vpcs.append(standardized_vpc)
937
-
962
+
938
963
  # Update data with validated VPCs
939
- data['vpcs'] = validated_vpcs
940
-
964
+ data["vpcs"] = validated_vpcs
965
+
941
966
  # Ensure other required fields
942
- if 'total_vpcs' not in data:
943
- data['total_vpcs'] = len(validated_vpcs)
944
-
945
- if 'no_eni_vpcs' not in data:
946
- data['no_eni_vpcs'] = 0 # Default value
947
-
948
- if 'cost_impact' not in data:
949
- data['cost_impact'] = 0.0 # Default value
950
-
967
+ if "total_vpcs" not in data:
968
+ data["total_vpcs"] = len(validated_vpcs)
969
+
970
+ if "no_eni_vpcs" not in data:
971
+ data["no_eni_vpcs"] = 0 # Default value
972
+
973
+ if "cost_impact" not in data:
974
+ data["cost_impact"] = 0.0 # Default value
975
+
951
976
  print_success(f"Loaded {len(validated_vpcs)} VPCs from analysis file")
952
977
  return data
953
-
954
- elif analysis_path.endswith('.csv'):
978
+
979
+ elif analysis_path.endswith(".csv"):
955
980
  print_info(f"Loading VPC analysis from CSV: {analysis_path}")
956
981
  import csv
982
+
957
983
  vpcs = []
958
-
959
- with open(analysis_path, 'r') as f:
984
+
985
+ with open(analysis_path, "r") as f:
960
986
  csv_reader = csv.DictReader(f)
961
987
  for row in csv_reader:
962
988
  # Convert CSV row to VPC format
963
989
  vpc = {
964
- 'VpcId': row.get('VpcId', row.get('vpc_id', '')),
965
- 'State': row.get('State', row.get('state', 'unknown')),
966
- 'CidrBlock': row.get('CidrBlock', row.get('cidr_block', '')),
967
- 'OwnerId': row.get('OwnerId', row.get('owner_id', '')),
968
- 'IsDefault': row.get('IsDefault', '').lower() in ('true', '1', 'yes'),
969
- 'DhcpOptionsId': row.get('DhcpOptionsId', ''),
970
- 'InstanceTenancy': row.get('InstanceTenancy', ''),
971
- 'Tags': [] # CSV typically doesn't contain complex tag data
990
+ "VpcId": row.get("VpcId", row.get("vpc_id", "")),
991
+ "State": row.get("State", row.get("state", "unknown")),
992
+ "CidrBlock": row.get("CidrBlock", row.get("cidr_block", "")),
993
+ "OwnerId": row.get("OwnerId", row.get("owner_id", "")),
994
+ "IsDefault": row.get("IsDefault", "").lower() in ("true", "1", "yes"),
995
+ "DhcpOptionsId": row.get("DhcpOptionsId", ""),
996
+ "InstanceTenancy": row.get("InstanceTenancy", ""),
997
+ "Tags": [], # CSV typically doesn't contain complex tag data
972
998
  }
973
-
974
- if vpc['VpcId']: # Only add if has VPC ID
999
+
1000
+ if vpc["VpcId"]: # Only add if has VPC ID
975
1001
  vpcs.append(vpc)
976
-
977
- return {
978
- 'vpcs': vpcs,
979
- 'total_vpcs': len(vpcs),
980
- 'no_eni_vpcs': 0,
981
- 'cost_impact': 0.0
982
- }
983
-
1002
+
1003
+ return {"vpcs": vpcs, "total_vpcs": len(vpcs), "no_eni_vpcs": 0, "cost_impact": 0.0}
1004
+
984
1005
  else:
985
1006
  # Try to detect file format from content
986
1007
  print_info(f"Attempting to detect file format for: {analysis_path}")
987
- with open(analysis_path, 'r') as f:
1008
+ with open(analysis_path, "r") as f:
988
1009
  content = f.read().strip()
989
-
990
- if content.startswith('{') or content.startswith('['):
1010
+
1011
+ if content.startswith("{") or content.startswith("["):
991
1012
  # Looks like JSON
992
1013
  data = json.loads(content)
993
1014
  return await self._load_vpc_analysis(f"{analysis_path}.json") # Re-process as JSON
994
1015
  else:
995
1016
  print_error(f"Unsupported file format for VPC analysis: {analysis_path}")
996
1017
  raise ValueError(f"Unsupported file format for VPC analysis: {analysis_path}")
997
-
1018
+
998
1019
  except FileNotFoundError:
999
1020
  print_error(f"VPC analysis file not found: {analysis_path}")
1000
1021
  raise
@@ -1008,49 +1029,53 @@ class Comprehensive2WayValidator:
1008
1029
  async def _load_finops_export(self, export_path: str) -> Dict[str, Any]:
1009
1030
  """Load FinOps export data for validation."""
1010
1031
  try:
1011
- if export_path.endswith('.json'):
1012
- with open(export_path, 'r') as f:
1032
+ if export_path.endswith(".json"):
1033
+ with open(export_path, "r") as f:
1013
1034
  return json.load(f)
1014
- elif export_path.endswith('.csv'):
1035
+ elif export_path.endswith(".csv"):
1015
1036
  import pandas as pd
1037
+
1016
1038
  df = pd.read_csv(export_path)
1017
1039
  return {
1018
- 'cost_breakdown': df.to_dict('records'),
1019
- 'total_cost': df['Amount'].sum() if 'Amount' in df.columns else 0.0,
1020
- 'account_data': df.groupby('Account')['Amount'].sum().to_dict() if 'Account' in df.columns else {}
1040
+ "cost_breakdown": df.to_dict("records"),
1041
+ "total_cost": df["Amount"].sum() if "Amount" in df.columns else 0.0,
1042
+ "account_data": df.groupby("Account")["Amount"].sum().to_dict() if "Account" in df.columns else {},
1021
1043
  }
1022
1044
  except Exception as e:
1023
1045
  print_warning(f"Using mock FinOps data due to loading error: {e}")
1024
- # Use environment-driven values for universal compatibility
1025
- generic_account_id = os.getenv("AWS_ACCOUNT_ID", "123456789012")
1046
+ # Use dynamic account ID for universal compatibility
1047
+ profile_manager = AWSProfileManager()
1048
+ generic_account_id = profile_manager.get_account_id()
1026
1049
  mock_cost = float(os.getenv("MOCK_TOTAL_COST", "100.00"))
1027
1050
  current_period = datetime.now().strftime("%Y-%m")
1028
1051
  return {
1029
- 'cost_breakdown': [{'Service': 'S3', 'Account': generic_account_id, 'Amount': mock_cost, 'Period': current_period}],
1030
- 'total_cost': mock_cost,
1031
- 'account_data': {generic_account_id: mock_cost}
1052
+ "cost_breakdown": [
1053
+ {"Service": "S3", "Account": generic_account_id, "Amount": mock_cost, "Period": current_period}
1054
+ ],
1055
+ "total_cost": mock_cost,
1056
+ "account_data": {generic_account_id: mock_cost},
1032
1057
  }
1033
1058
 
1034
1059
  async def _get_time_synchronized_cost_data(self, finops_data: Dict) -> Dict[str, Any]:
1035
1060
  """Get time-synchronized MCP cost data for enhanced accuracy."""
1036
1061
  print_info("🕐 Implementing enhanced time synchronization for MCP validation...")
1037
-
1062
+
1038
1063
  # Time period synchronization (critical for 99.5% accuracy)
1039
- end_date = datetime.now().strftime('%Y-%m-%d')
1040
- start_date = (datetime.now() - timedelta(days=90)).strftime('%Y-%m-%d')
1041
-
1064
+ end_date = datetime.now().strftime("%Y-%m-%d")
1065
+ start_date = (datetime.now() - timedelta(days=90)).strftime("%Y-%m-%d")
1066
+
1042
1067
  # Get MCP cost data with time alignment
1043
1068
  mcp_billing_client = MCPAWSClient(self.billing_profile)
1044
-
1069
+
1045
1070
  # Enhanced time sync: align periods exactly
1046
1071
  cost_data = mcp_billing_client.get_cost_data_raw(start_date, end_date)
1047
-
1072
+
1048
1073
  return {
1049
- 'status': cost_data.get('status', 'unknown'),
1050
- 'data': cost_data.get('data', {}),
1051
- 'time_period': {'start': start_date, 'end': end_date},
1052
- 'sync_timestamp': datetime.now().isoformat(),
1053
- 'accuracy_enhancement': 'time_synchronized_periods'
1074
+ "status": cost_data.get("status", "unknown"),
1075
+ "data": cost_data.get("data", {}),
1076
+ "time_period": {"start": start_date, "end": end_date},
1077
+ "sync_timestamp": datetime.now().isoformat(),
1078
+ "accuracy_enhancement": "time_synchronized_periods",
1054
1079
  }
1055
1080
 
1056
1081
  # Validation implementation methods
@@ -1058,17 +1083,17 @@ class Comprehensive2WayValidator:
1058
1083
  """Validate account discovery against MCP Organizations."""
1059
1084
  try:
1060
1085
  org_data = self.mcp_multi_account.management_client.get_organizations_data()
1061
-
1062
- inventory_accounts = len(inventory_data.get('account_summary', {}))
1063
- mcp_accounts = org_data.get('total_accounts', 0)
1064
-
1086
+
1087
+ inventory_accounts = len(inventory_data.get("account_summary", {}))
1088
+ mcp_accounts = org_data.get("total_accounts", 0)
1089
+
1065
1090
  if inventory_accounts == mcp_accounts:
1066
- return {'status': 'validated', 'message': 'Account discovery validated'}
1091
+ return {"status": "validated", "message": "Account discovery validated"}
1067
1092
  else:
1068
1093
  variance_pct = abs(inventory_accounts - mcp_accounts) / max(mcp_accounts, 1) * 100
1069
1094
  return {
1070
- 'status': 'variance_detected',
1071
- 'discrepancy': ValidationDiscrepancy(
1095
+ "status": "variance_detected",
1096
+ "discrepancy": ValidationDiscrepancy(
1072
1097
  source_name="inventory_module",
1073
1098
  mcp_name="organizations_api",
1074
1099
  field_name="account_count",
@@ -1077,114 +1102,116 @@ class Comprehensive2WayValidator:
1077
1102
  variance_percentage=variance_pct,
1078
1103
  severity="medium" if variance_pct < 20 else "high",
1079
1104
  recommendation=f"Investigate account discovery logic - {variance_pct:.1f}% variance",
1080
- business_impact="May affect multi-account reporting accuracy"
1081
- )
1105
+ business_impact="May affect multi-account reporting accuracy",
1106
+ ),
1082
1107
  }
1083
1108
  except Exception as e:
1084
- return {'status': 'validation_error', 'error': str(e)}
1109
+ return {"status": "validation_error", "error": str(e)}
1085
1110
 
1086
- async def _validate_service_resources(self, service_type: str, inventory_data: Dict, account_scope: List[str]) -> Dict[str, Any]:
1111
+ async def _validate_service_resources(
1112
+ self, service_type: str, inventory_data: Dict, account_scope: List[str]
1113
+ ) -> Dict[str, Any]:
1087
1114
  """Validate service resource counts."""
1088
1115
  # Real AWS service validation implementation required
1089
1116
  # Remove random simulation - use actual AWS API validation
1090
1117
  try:
1091
1118
  # TODO: Implement actual AWS service resource validation
1092
1119
  # This should validate against real AWS API responses
1093
- return {'status': 'validated', 'message': f'{service_type} resources validated'}
1120
+ return {"status": "validated", "message": f"{service_type} resources validated"}
1094
1121
  except Exception as e:
1095
1122
  return {
1096
- 'status': 'variance_detected',
1097
- 'discrepancy': ValidationDiscrepancy(
1123
+ "status": "variance_detected",
1124
+ "discrepancy": ValidationDiscrepancy(
1098
1125
  source_name="inventory_module",
1099
1126
  mcp_name="aws_api_direct",
1100
1127
  field_name=f"{service_type}_count",
1101
- source_value=inventory_data['service_summary'].get(service_type, 0),
1102
- mcp_value=inventory_data['service_summary'].get(service_type, 0) + 1,
1128
+ source_value=inventory_data["service_summary"].get(service_type, 0),
1129
+ mcp_value=inventory_data["service_summary"].get(service_type, 0) + 1,
1103
1130
  variance_percentage=5.0,
1104
1131
  severity="low",
1105
1132
  recommendation=f"Minor {service_type} count variance detected",
1106
- business_impact="Minimal impact on resource management"
1107
- )
1133
+ business_impact="Minimal impact on resource management",
1134
+ ),
1108
1135
  }
1109
1136
 
1110
1137
  async def _validate_vpc_configuration(self, vpc: Dict) -> Dict[str, Any]:
1111
1138
  """
1112
1139
  Validate individual VPC configuration with enhanced accuracy.
1113
-
1140
+
1114
1141
  Following proven patterns from Cost Explorer and Organizations fixes:
1115
- - Enhanced data structure validation
1142
+ - Enhanced data structure validation
1116
1143
  - Comprehensive accuracy scoring
1117
1144
  - Real validation logic instead of hardcoded responses
1118
1145
  """
1119
- vpc_id = vpc.get('VpcId', 'unknown')
1120
-
1146
+ vpc_id = vpc.get("VpcId", "unknown")
1147
+
1121
1148
  try:
1122
1149
  # Enhanced validation using multiple data points (following Cost Explorer pattern)
1123
1150
  validation_score = 0.0
1124
1151
  validation_checks = 0
1125
1152
  validation_details = {}
1126
-
1153
+
1127
1154
  # Check 1: VPC ID format validation (critical for accuracy)
1128
- if vpc_id.startswith('vpc-') and len(vpc_id) >= 8:
1155
+ if vpc_id.startswith("vpc-") and len(vpc_id) >= 8:
1129
1156
  validation_score += 1.0
1130
- validation_details['vpc_id_valid'] = True
1157
+ validation_details["vpc_id_valid"] = True
1131
1158
  else:
1132
- validation_details['vpc_id_valid'] = False
1159
+ validation_details["vpc_id_valid"] = False
1133
1160
  validation_checks += 1
1134
-
1161
+
1135
1162
  # Check 2: VPC state validation (enterprise requirement)
1136
- vpc_state = vpc.get('State', 'unknown')
1137
- if vpc_state in ['available', 'pending']:
1163
+ vpc_state = vpc.get("State", "unknown")
1164
+ if vpc_state in ["available", "pending"]:
1138
1165
  validation_score += 1.0
1139
- validation_details['state_valid'] = True
1140
- elif vpc_state in ['unknown']:
1166
+ validation_details["state_valid"] = True
1167
+ elif vpc_state in ["unknown"]:
1141
1168
  validation_score += 0.5 # Partial credit for missing data
1142
- validation_details['state_valid'] = 'partial'
1169
+ validation_details["state_valid"] = "partial"
1143
1170
  else:
1144
- validation_details['state_valid'] = False
1171
+ validation_details["state_valid"] = False
1145
1172
  validation_checks += 1
1146
-
1173
+
1147
1174
  # Check 3: CIDR block validation (network configuration accuracy)
1148
- cidr_block = vpc.get('CidrBlock', '')
1149
- if cidr_block and '/' in cidr_block:
1175
+ cidr_block = vpc.get("CidrBlock", "")
1176
+ if cidr_block and "/" in cidr_block:
1150
1177
  try:
1151
1178
  # Basic CIDR format validation
1152
- parts = cidr_block.split('/')
1179
+ parts = cidr_block.split("/")
1153
1180
  if len(parts) == 2 and parts[1].isdigit():
1154
1181
  subnet_bits = int(parts[1])
1155
1182
  if 8 <= subnet_bits <= 32: # Valid CIDR range
1156
1183
  validation_score += 1.0
1157
- validation_details['cidr_valid'] = True
1184
+ validation_details["cidr_valid"] = True
1158
1185
  else:
1159
1186
  validation_score += 0.7 # Partial credit for format
1160
- validation_details['cidr_valid'] = 'partial'
1187
+ validation_details["cidr_valid"] = "partial"
1161
1188
  else:
1162
1189
  validation_score += 0.3 # Minimal credit for having CIDR
1163
- validation_details['cidr_valid'] = 'format_error'
1190
+ validation_details["cidr_valid"] = "format_error"
1164
1191
  except:
1165
1192
  validation_score += 0.3 # Minimal credit for having CIDR
1166
- validation_details['cidr_valid'] = 'parse_error'
1193
+ validation_details["cidr_valid"] = "parse_error"
1167
1194
  else:
1168
- validation_details['cidr_valid'] = False
1195
+ validation_details["cidr_valid"] = False
1169
1196
  validation_checks += 1
1170
-
1197
+
1171
1198
  # Check 4: Account ownership validation (security validation)
1172
- owner_id = vpc.get('OwnerId', '')
1199
+ owner_id = vpc.get("OwnerId", "")
1173
1200
  if owner_id and owner_id.isdigit() and len(owner_id) == 12:
1174
1201
  validation_score += 1.0
1175
- validation_details['owner_valid'] = True
1202
+ validation_details["owner_valid"] = True
1176
1203
  elif owner_id:
1177
1204
  validation_score += 0.5 # Partial credit for having owner
1178
- validation_details['owner_valid'] = 'partial'
1205
+ validation_details["owner_valid"] = "partial"
1179
1206
  else:
1180
- validation_details['owner_valid'] = False
1207
+ validation_details["owner_valid"] = False
1181
1208
  validation_checks += 1
1182
-
1209
+
1183
1210
  # Check 5: VPC attributes validation (configuration completeness)
1184
- is_default = vpc.get('IsDefault', None)
1185
- dhcp_options_id = vpc.get('DhcpOptionsId', '')
1186
- instance_tenancy = vpc.get('InstanceTenancy', '')
1187
-
1211
+ is_default = vpc.get("IsDefault", None)
1212
+ dhcp_options_id = vpc.get("DhcpOptionsId", "")
1213
+ instance_tenancy = vpc.get("InstanceTenancy", "")
1214
+
1188
1215
  attributes_score = 0.0
1189
1216
  if is_default is not None: # Boolean field present
1190
1217
  attributes_score += 0.4
@@ -1192,46 +1219,46 @@ class Comprehensive2WayValidator:
1192
1219
  attributes_score += 0.3
1193
1220
  if instance_tenancy:
1194
1221
  attributes_score += 0.3
1195
-
1222
+
1196
1223
  validation_score += attributes_score
1197
- validation_details['attributes_complete'] = attributes_score >= 0.8
1224
+ validation_details["attributes_complete"] = attributes_score >= 0.8
1198
1225
  validation_checks += 1
1199
-
1226
+
1200
1227
  # Check 6: Tags validation (governance and compliance)
1201
- tags = vpc.get('Tags', [])
1228
+ tags = vpc.get("Tags", [])
1202
1229
  tags_score = 0.0
1203
1230
  if isinstance(tags, list):
1204
1231
  if tags: # Has tags
1205
1232
  tags_score = 1.0
1206
- validation_details['has_tags'] = True
1233
+ validation_details["has_tags"] = True
1207
1234
  # Bonus for Name tag
1208
- name_tag = any(tag.get('Key') == 'Name' for tag in tags)
1235
+ name_tag = any(tag.get("Key") == "Name" for tag in tags)
1209
1236
  if name_tag:
1210
1237
  tags_score = 1.0 # Full score for proper tagging
1211
- validation_details['has_name_tag'] = True
1238
+ validation_details["has_name_tag"] = True
1212
1239
  else:
1213
- validation_details['has_name_tag'] = False
1240
+ validation_details["has_name_tag"] = False
1214
1241
  else:
1215
1242
  tags_score = 0.7 # Partial credit for empty but valid tags structure
1216
- validation_details['has_tags'] = False
1243
+ validation_details["has_tags"] = False
1217
1244
  else:
1218
- validation_details['has_tags'] = False
1219
-
1245
+ validation_details["has_tags"] = False
1246
+
1220
1247
  validation_score += tags_score
1221
1248
  validation_checks += 1
1222
-
1249
+
1223
1250
  # Calculate accuracy percentage (following proven accuracy pattern)
1224
1251
  accuracy_percentage = (validation_score / validation_checks) * 100
1225
-
1252
+
1226
1253
  # Determine validation status based on accuracy (enterprise thresholds)
1227
1254
  if accuracy_percentage >= 95.0:
1228
- status = 'validated'
1255
+ status = "validated"
1229
1256
  message = f"VPC {vpc_id} validation passed with {accuracy_percentage:.1f}% accuracy"
1230
1257
  elif accuracy_percentage >= 80.0:
1231
- status = 'validated_with_warnings'
1258
+ status = "validated_with_warnings"
1232
1259
  message = f"VPC {vpc_id} validation passed with {accuracy_percentage:.1f}% accuracy (minor issues)"
1233
1260
  else:
1234
- status = 'validation_issues'
1261
+ status = "validation_issues"
1235
1262
  message = f"VPC {vpc_id} validation accuracy {accuracy_percentage:.1f}% below enterprise threshold"
1236
1263
  # Create discrepancy for tracking
1237
1264
  discrepancy = ValidationDiscrepancy(
@@ -1243,30 +1270,30 @@ class Comprehensive2WayValidator:
1243
1270
  variance_percentage=100.0 - accuracy_percentage,
1244
1271
  severity="medium" if accuracy_percentage >= 70.0 else "high",
1245
1272
  recommendation=f"Improve VPC {vpc_id} configuration validation",
1246
- business_impact="May affect network cost correlation accuracy"
1273
+ business_impact="May affect network cost correlation accuracy",
1247
1274
  )
1248
1275
  return {
1249
- 'status': status,
1250
- 'message': message,
1251
- 'accuracy_percentage': accuracy_percentage,
1252
- 'discrepancy': discrepancy,
1253
- 'validation_details': validation_details
1276
+ "status": status,
1277
+ "message": message,
1278
+ "accuracy_percentage": accuracy_percentage,
1279
+ "discrepancy": discrepancy,
1280
+ "validation_details": validation_details,
1254
1281
  }
1255
-
1282
+
1256
1283
  return {
1257
- 'status': status,
1258
- 'message': message,
1259
- 'accuracy_percentage': accuracy_percentage,
1260
- 'validation_details': validation_details
1284
+ "status": status,
1285
+ "message": message,
1286
+ "accuracy_percentage": accuracy_percentage,
1287
+ "validation_details": validation_details,
1261
1288
  }
1262
-
1289
+
1263
1290
  except Exception as e:
1264
1291
  print_warning(f"VPC {vpc_id} validation error: {e}")
1265
1292
  return {
1266
- 'status': 'validation_error',
1267
- 'message': f"VPC {vpc_id} validation failed: {str(e)}",
1268
- 'accuracy_percentage': 0.0,
1269
- 'discrepancy': ValidationDiscrepancy(
1293
+ "status": "validation_error",
1294
+ "message": f"VPC {vpc_id} validation failed: {str(e)}",
1295
+ "accuracy_percentage": 0.0,
1296
+ "discrepancy": ValidationDiscrepancy(
1270
1297
  source_name="vpc_module",
1271
1298
  mcp_name="aws_ec2_api",
1272
1299
  field_name=f"vpc_validation_{vpc_id}",
@@ -1275,15 +1302,15 @@ class Comprehensive2WayValidator:
1275
1302
  variance_percentage=100.0,
1276
1303
  severity="critical",
1277
1304
  recommendation=f"Fix VPC {vpc_id} validation error: {str(e)}",
1278
- business_impact="Critical validation failure affects accuracy"
1305
+ business_impact="Critical validation failure affects accuracy",
1279
1306
  ),
1280
- 'validation_details': {'error': str(e)}
1307
+ "validation_details": {"error": str(e)},
1281
1308
  }
1282
1309
 
1283
1310
  async def _validate_vpc_cost_correlation(self, vpc_data: Dict) -> Dict[str, Any]:
1284
1311
  """
1285
1312
  Validate VPC cost correlation with FinOps data using enhanced accuracy patterns.
1286
-
1313
+
1287
1314
  Following proven patterns from Cost Explorer and Organizations fixes:
1288
1315
  - Real correlation analysis instead of hardcoded responses
1289
1316
  - Enhanced accuracy calculation with multiple validation points
@@ -1294,88 +1321,88 @@ class Comprehensive2WayValidator:
1294
1321
  correlation_score = 0.0
1295
1322
  correlation_checks = 0
1296
1323
  validation_details = {}
1297
-
1324
+
1298
1325
  # Check 1: VPC data structure validation
1299
1326
  if isinstance(vpc_data, dict) and vpc_data:
1300
1327
  correlation_score += 1.0
1301
- validation_details['data_structure_valid'] = True
1328
+ validation_details["data_structure_valid"] = True
1302
1329
  else:
1303
- validation_details['data_structure_valid'] = False
1330
+ validation_details["data_structure_valid"] = False
1304
1331
  correlation_checks += 1
1305
-
1332
+
1306
1333
  # Check 2: Cost-relevant VPC attributes presence
1307
- cost_relevant_attrs = ['VpcId', 'OwnerId', 'CidrBlock', 'State']
1334
+ cost_relevant_attrs = ["VpcId", "OwnerId", "CidrBlock", "State"]
1308
1335
  present_attrs = sum(1 for attr in cost_relevant_attrs if vpc_data.get(attr))
1309
-
1336
+
1310
1337
  if present_attrs == len(cost_relevant_attrs):
1311
1338
  correlation_score += 1.0
1312
- validation_details['cost_attributes_complete'] = True
1339
+ validation_details["cost_attributes_complete"] = True
1313
1340
  elif present_attrs >= len(cost_relevant_attrs) * 0.8:
1314
1341
  correlation_score += 0.8
1315
- validation_details['cost_attributes_complete'] = 'partial'
1342
+ validation_details["cost_attributes_complete"] = "partial"
1316
1343
  else:
1317
- validation_details['cost_attributes_complete'] = False
1344
+ validation_details["cost_attributes_complete"] = False
1318
1345
  correlation_checks += 1
1319
-
1346
+
1320
1347
  # Check 3: VPC resources for cost correlation (enhanced detection)
1321
- vpcs_list = vpc_data.get('vpcs', [])
1348
+ vpcs_list = vpc_data.get("vpcs", [])
1322
1349
  if vpcs_list:
1323
1350
  # Enhanced cost correlation analysis across all VPCs
1324
1351
  total_cost_indicators = 0
1325
1352
  vpcs_with_indicators = 0
1326
-
1353
+
1327
1354
  for vpc in vpcs_list:
1328
- vpc_id = vpc.get('VpcId', '')
1355
+ vpc_id = vpc.get("VpcId", "")
1329
1356
  potential_cost_indicators = []
1330
-
1357
+
1331
1358
  # Check VPC ID pattern (cost-related services often have specific patterns)
1332
1359
  if vpc_id:
1333
- potential_cost_indicators.append('vpc_identity')
1334
-
1360
+ potential_cost_indicators.append("vpc_identity")
1361
+
1335
1362
  # Check VPC state (active VPCs have cost implications)
1336
- vpc_state = vpc.get('State', '')
1337
- if vpc_state == 'available':
1338
- potential_cost_indicators.append('active_vpc')
1339
-
1363
+ vpc_state = vpc.get("State", "")
1364
+ if vpc_state == "available":
1365
+ potential_cost_indicators.append("active_vpc")
1366
+
1340
1367
  # Check CIDR block (larger networks may have more resources)
1341
- cidr_block = vpc.get('CidrBlock', '')
1368
+ cidr_block = vpc.get("CidrBlock", "")
1342
1369
  if cidr_block:
1343
1370
  try:
1344
- parts = cidr_block.split('/')
1371
+ parts = cidr_block.split("/")
1345
1372
  if len(parts) == 2 and parts[1].isdigit():
1346
1373
  subnet_bits = int(parts[1])
1347
1374
  if subnet_bits <= 20: # Larger networks
1348
- potential_cost_indicators.append('large_network')
1375
+ potential_cost_indicators.append("large_network")
1349
1376
  else:
1350
- potential_cost_indicators.append('standard_network')
1377
+ potential_cost_indicators.append("standard_network")
1351
1378
  except:
1352
- potential_cost_indicators.append('network_config')
1353
-
1379
+ potential_cost_indicators.append("network_config")
1380
+
1354
1381
  # Check tenancy (dedicated instances have higher costs)
1355
- tenancy = vpc.get('InstanceTenancy', '')
1356
- if tenancy == 'dedicated':
1357
- potential_cost_indicators.append('dedicated_tenancy')
1358
- elif tenancy == 'default':
1359
- potential_cost_indicators.append('shared_tenancy')
1360
-
1382
+ tenancy = vpc.get("InstanceTenancy", "")
1383
+ if tenancy == "dedicated":
1384
+ potential_cost_indicators.append("dedicated_tenancy")
1385
+ elif tenancy == "default":
1386
+ potential_cost_indicators.append("shared_tenancy")
1387
+
1361
1388
  # Check tags (well-tagged resources often correlate with cost tracking)
1362
- tags = vpc.get('Tags', [])
1389
+ tags = vpc.get("Tags", [])
1363
1390
  if isinstance(tags, list) and tags:
1364
- potential_cost_indicators.append('tagged_resource')
1391
+ potential_cost_indicators.append("tagged_resource")
1365
1392
  # Look for cost-related tag keys
1366
- tag_keys = [tag.get('Key', '').lower() for tag in tags]
1367
- if any(key in tag_keys for key in ['cost', 'billing', 'project', 'environment']):
1368
- potential_cost_indicators.append('cost_tracking_tags')
1369
-
1393
+ tag_keys = [tag.get("Key", "").lower() for tag in tags]
1394
+ if any(key in tag_keys for key in ["cost", "billing", "project", "environment"]):
1395
+ potential_cost_indicators.append("cost_tracking_tags")
1396
+
1370
1397
  if potential_cost_indicators:
1371
1398
  vpcs_with_indicators += 1
1372
1399
  total_cost_indicators += len(potential_cost_indicators)
1373
-
1400
+
1374
1401
  # Calculate correlation score based on comprehensive analysis
1375
1402
  if vpcs_with_indicators > 0:
1376
1403
  vpc_coverage = vpcs_with_indicators / len(vpcs_list)
1377
1404
  indicator_density = total_cost_indicators / len(vpcs_list)
1378
-
1405
+
1379
1406
  # Score based on coverage and indicator density
1380
1407
  if vpc_coverage >= 0.8 and indicator_density >= 3.0:
1381
1408
  correlation_score += 1.0 # Excellent correlation
@@ -1385,62 +1412,62 @@ class Comprehensive2WayValidator:
1385
1412
  correlation_score += 0.8 # Acceptable correlation
1386
1413
  else:
1387
1414
  correlation_score += 0.7 # Basic correlation
1388
-
1389
- validation_details['cost_indicators_present'] = {
1390
- 'vpcs_with_indicators': vpcs_with_indicators,
1391
- 'total_vpcs': len(vpcs_list),
1392
- 'coverage_percentage': vpc_coverage * 100,
1393
- 'average_indicators_per_vpc': indicator_density
1415
+
1416
+ validation_details["cost_indicators_present"] = {
1417
+ "vpcs_with_indicators": vpcs_with_indicators,
1418
+ "total_vpcs": len(vpcs_list),
1419
+ "coverage_percentage": vpc_coverage * 100,
1420
+ "average_indicators_per_vpc": indicator_density,
1394
1421
  }
1395
1422
  else:
1396
1423
  correlation_score += 0.5 # Minimal correlation
1397
- validation_details['cost_indicators_present'] = {
1398
- 'vpcs_with_indicators': 0,
1399
- 'total_vpcs': len(vpcs_list),
1400
- 'coverage_percentage': 0.0,
1401
- 'average_indicators_per_vpc': 0.0
1424
+ validation_details["cost_indicators_present"] = {
1425
+ "vpcs_with_indicators": 0,
1426
+ "total_vpcs": len(vpcs_list),
1427
+ "coverage_percentage": 0.0,
1428
+ "average_indicators_per_vpc": 0.0,
1402
1429
  }
1403
1430
  else:
1404
1431
  # Check if VPC data structure itself indicates cost correlation potential
1405
- cost_impact = vpc_data.get('cost_impact', 0)
1432
+ cost_impact = vpc_data.get("cost_impact", 0)
1406
1433
  if cost_impact > 0:
1407
1434
  correlation_score += 0.8 # Has cost impact data
1408
- validation_details['cost_indicators_present'] = {'cost_impact_available': True}
1435
+ validation_details["cost_indicators_present"] = {"cost_impact_available": True}
1409
1436
  else:
1410
1437
  correlation_score += 0.3 # Minimal correlation without VPC data
1411
- validation_details['cost_indicators_present'] = {'cost_impact_available': False}
1412
-
1438
+ validation_details["cost_indicators_present"] = {"cost_impact_available": False}
1439
+
1413
1440
  correlation_checks += 1
1414
-
1441
+
1415
1442
  # Check 4: Enhanced network topology and infrastructure indicators
1416
1443
  # Analyze overall infrastructure complexity for cost correlation
1417
1444
  infrastructure_score = 0.0
1418
1445
  infrastructure_indicators = []
1419
-
1446
+
1420
1447
  # Check VPC-level cost factors
1421
1448
  if vpcs_list:
1422
1449
  # Multi-VPC environment indicates higher complexity and costs
1423
1450
  if len(vpcs_list) > 1:
1424
1451
  infrastructure_score += 0.2
1425
- infrastructure_indicators.append('multi_vpc_environment')
1426
-
1452
+ infrastructure_indicators.append("multi_vpc_environment")
1453
+
1427
1454
  # Analyze network topology complexity
1428
1455
  total_network_capacity = 0
1429
1456
  dedicated_tenancy_count = 0
1430
1457
  well_tagged_count = 0
1431
-
1458
+
1432
1459
  for vpc in vpcs_list:
1433
1460
  # Network size analysis
1434
- cidr_block = vpc.get('CidrBlock', '')
1461
+ cidr_block = vpc.get("CidrBlock", "")
1435
1462
  if cidr_block:
1436
1463
  try:
1437
- parts = cidr_block.split('/')
1464
+ parts = cidr_block.split("/")
1438
1465
  if len(parts) == 2 and parts[1].isdigit():
1439
1466
  subnet_bits = int(parts[1])
1440
1467
  # Calculate potential IP capacity as cost indicator
1441
1468
  capacity = 2 ** (32 - subnet_bits)
1442
1469
  total_network_capacity += capacity
1443
-
1470
+
1444
1471
  if subnet_bits <= 16: # Large networks
1445
1472
  infrastructure_score += 0.15
1446
1473
  elif subnet_bits <= 20: # Medium-large networks
@@ -1449,86 +1476,90 @@ class Comprehensive2WayValidator:
1449
1476
  infrastructure_score += 0.05
1450
1477
  except:
1451
1478
  infrastructure_score += 0.02 # Minimal credit for having CIDR
1452
-
1479
+
1453
1480
  # Tenancy model analysis
1454
- tenancy = vpc.get('InstanceTenancy', '')
1455
- if tenancy == 'dedicated':
1481
+ tenancy = vpc.get("InstanceTenancy", "")
1482
+ if tenancy == "dedicated":
1456
1483
  dedicated_tenancy_count += 1
1457
1484
  infrastructure_score += 0.1
1458
-
1485
+
1459
1486
  # Governance and tracking analysis
1460
- tags = vpc.get('Tags', [])
1487
+ tags = vpc.get("Tags", [])
1461
1488
  if isinstance(tags, list) and len(tags) >= 2:
1462
1489
  well_tagged_count += 1
1463
1490
  infrastructure_score += 0.05
1464
-
1491
+
1465
1492
  # Infrastructure complexity bonuses
1466
1493
  if total_network_capacity > 65536: # > /16 network equivalent
1467
1494
  infrastructure_score += 0.1
1468
- infrastructure_indicators.append('large_network_capacity')
1469
-
1495
+ infrastructure_indicators.append("large_network_capacity")
1496
+
1470
1497
  if dedicated_tenancy_count > 0:
1471
1498
  infrastructure_score += 0.1
1472
- infrastructure_indicators.append('dedicated_tenancy_present')
1473
-
1499
+ infrastructure_indicators.append("dedicated_tenancy_present")
1500
+
1474
1501
  if well_tagged_count / len(vpcs_list) >= 0.8: # 80%+ well-tagged
1475
1502
  infrastructure_score += 0.1
1476
- infrastructure_indicators.append('strong_governance')
1477
-
1503
+ infrastructure_indicators.append("strong_governance")
1504
+
1478
1505
  # Cost impact metadata bonus
1479
- cost_impact = vpc_data.get('cost_impact', 0)
1506
+ cost_impact = vpc_data.get("cost_impact", 0)
1480
1507
  if cost_impact > 0:
1481
1508
  infrastructure_score += 0.15
1482
- infrastructure_indicators.append('documented_cost_impact')
1483
-
1509
+ infrastructure_indicators.append("documented_cost_impact")
1510
+
1484
1511
  # Analysis metadata bonus (indicates professional assessment)
1485
- metadata = vpc_data.get('analysis_metadata', {})
1512
+ metadata = vpc_data.get("analysis_metadata", {})
1486
1513
  if metadata:
1487
1514
  infrastructure_score += 0.1
1488
- infrastructure_indicators.append('comprehensive_analysis')
1489
-
1515
+ infrastructure_indicators.append("comprehensive_analysis")
1516
+
1490
1517
  # Normalize infrastructure score to 0-1 range
1491
1518
  infrastructure_score = min(1.0, infrastructure_score)
1492
1519
  correlation_score += infrastructure_score
1493
-
1494
- validation_details['infrastructure_complexity'] = {
1495
- 'score': infrastructure_score,
1496
- 'indicators': infrastructure_indicators,
1497
- 'total_network_capacity': total_network_capacity if 'total_network_capacity' in locals() else 0,
1498
- 'dedicated_tenancy_count': dedicated_tenancy_count if 'dedicated_tenancy_count' in locals() else 0,
1499
- 'governance_coverage': (well_tagged_count / len(vpcs_list) * 100) if vpcs_list and 'well_tagged_count' in locals() else 0
1520
+
1521
+ validation_details["infrastructure_complexity"] = {
1522
+ "score": infrastructure_score,
1523
+ "indicators": infrastructure_indicators,
1524
+ "total_network_capacity": total_network_capacity if "total_network_capacity" in locals() else 0,
1525
+ "dedicated_tenancy_count": dedicated_tenancy_count if "dedicated_tenancy_count" in locals() else 0,
1526
+ "governance_coverage": (well_tagged_count / len(vpcs_list) * 100)
1527
+ if vpcs_list and "well_tagged_count" in locals()
1528
+ else 0,
1500
1529
  }
1501
-
1530
+
1502
1531
  correlation_checks += 1
1503
-
1532
+
1504
1533
  # Check 5: VPC state impact on cost correlation
1505
- vpc_state = vpc_data.get('State', 'unknown')
1506
- if vpc_state == 'available':
1534
+ vpc_state = vpc_data.get("State", "unknown")
1535
+ if vpc_state == "available":
1507
1536
  correlation_score += 1.0 # Active VPC, full cost correlation expected
1508
- validation_details['state_cost_impact'] = 'active'
1509
- elif vpc_state == 'pending':
1537
+ validation_details["state_cost_impact"] = "active"
1538
+ elif vpc_state == "pending":
1510
1539
  correlation_score += 0.8 # Transitional state, partial correlation
1511
- validation_details['state_cost_impact'] = 'transitional'
1512
- elif vpc_state == 'deleting':
1540
+ validation_details["state_cost_impact"] = "transitional"
1541
+ elif vpc_state == "deleting":
1513
1542
  correlation_score += 0.3 # Minimal correlation expected
1514
- validation_details['state_cost_impact'] = 'terminating'
1543
+ validation_details["state_cost_impact"] = "terminating"
1515
1544
  else:
1516
1545
  correlation_score += 0.1 # Unknown state, minimal correlation
1517
- validation_details['state_cost_impact'] = 'unknown'
1546
+ validation_details["state_cost_impact"] = "unknown"
1518
1547
  correlation_checks += 1
1519
-
1548
+
1520
1549
  # Calculate correlation accuracy percentage
1521
1550
  correlation_accuracy = (correlation_score / correlation_checks) * 100
1522
-
1551
+
1523
1552
  # Determine validation status based on correlation accuracy
1524
1553
  if correlation_accuracy >= 95.0:
1525
- status = 'validated'
1554
+ status = "validated"
1526
1555
  message = f"VPC cost correlation validated with {correlation_accuracy:.1f}% accuracy"
1527
1556
  elif correlation_accuracy >= 80.0:
1528
- status = 'validated_with_warnings'
1529
- message = f"VPC cost correlation validated with {correlation_accuracy:.1f}% accuracy (minor correlation gaps)"
1557
+ status = "validated_with_warnings"
1558
+ message = (
1559
+ f"VPC cost correlation validated with {correlation_accuracy:.1f}% accuracy (minor correlation gaps)"
1560
+ )
1530
1561
  else:
1531
- status = 'correlation_issues'
1562
+ status = "correlation_issues"
1532
1563
  message = f"VPC cost correlation accuracy {correlation_accuracy:.1f}% below enterprise threshold"
1533
1564
  # Create discrepancy for tracking
1534
1565
  discrepancy = ValidationDiscrepancy(
@@ -1540,29 +1571,29 @@ class Comprehensive2WayValidator:
1540
1571
  variance_percentage=100.0 - correlation_accuracy,
1541
1572
  severity="medium" if correlation_accuracy >= 70.0 else "high",
1542
1573
  recommendation=f"Improve VPC cost correlation methodology for {vpc_data.get('VpcId', 'unknown')}",
1543
- business_impact="May affect network cost optimization accuracy"
1574
+ business_impact="May affect network cost optimization accuracy",
1544
1575
  )
1545
1576
  return {
1546
- 'status': status,
1547
- 'message': message,
1548
- 'correlation_accuracy': correlation_accuracy,
1549
- 'discrepancy': discrepancy,
1550
- 'validation_details': validation_details
1577
+ "status": status,
1578
+ "message": message,
1579
+ "correlation_accuracy": correlation_accuracy,
1580
+ "discrepancy": discrepancy,
1581
+ "validation_details": validation_details,
1551
1582
  }
1552
-
1583
+
1553
1584
  return {
1554
- 'status': status,
1555
- 'message': message,
1556
- 'correlation_accuracy': correlation_accuracy,
1557
- 'validation_details': validation_details
1585
+ "status": status,
1586
+ "message": message,
1587
+ "correlation_accuracy": correlation_accuracy,
1588
+ "validation_details": validation_details,
1558
1589
  }
1559
-
1590
+
1560
1591
  except Exception as e:
1561
1592
  return {
1562
- 'status': 'correlation_error',
1563
- 'message': f"VPC cost correlation validation failed: {str(e)}",
1564
- 'correlation_accuracy': 0.0,
1565
- 'discrepancy': ValidationDiscrepancy(
1593
+ "status": "correlation_error",
1594
+ "message": f"VPC cost correlation validation failed: {str(e)}",
1595
+ "correlation_accuracy": 0.0,
1596
+ "discrepancy": ValidationDiscrepancy(
1566
1597
  source_name="vpc_module",
1567
1598
  mcp_name="finops_cost_explorer",
1568
1599
  field_name="vpc_cost_correlation",
@@ -1571,38 +1602,38 @@ class Comprehensive2WayValidator:
1571
1602
  variance_percentage=100.0,
1572
1603
  severity="critical",
1573
1604
  recommendation=f"Fix VPC cost correlation validation error: {str(e)}",
1574
- business_impact="Critical correlation failure affects cost optimization"
1605
+ business_impact="Critical correlation failure affects cost optimization",
1575
1606
  ),
1576
- 'validation_details': {'error': str(e)}
1607
+ "validation_details": {"error": str(e)},
1577
1608
  }
1578
1609
 
1579
1610
  async def _validate_total_cost_with_time_sync(self, finops_data: Dict, mcp_data: Dict) -> Dict[str, Any]:
1580
1611
  """Validate total cost with enhanced time synchronization."""
1581
- if mcp_data.get('status') != 'success':
1582
- return {'status': 'mcp_unavailable', 'message': 'MCP Cost Explorer unavailable'}
1583
-
1584
- finops_total = finops_data.get('total_cost', 0.0)
1585
-
1612
+ if mcp_data.get("status") != "success":
1613
+ return {"status": "mcp_unavailable", "message": "MCP Cost Explorer unavailable"}
1614
+
1615
+ finops_total = finops_data.get("total_cost", 0.0)
1616
+
1586
1617
  # Calculate MCP total with time sync
1587
1618
  mcp_total = 0.0
1588
- mcp_results = mcp_data.get('data', {}).get('ResultsByTime', [])
1589
-
1619
+ mcp_results = mcp_data.get("data", {}).get("ResultsByTime", [])
1620
+
1590
1621
  for result in mcp_results:
1591
- if 'Groups' in result:
1592
- for group in result['Groups']:
1593
- mcp_total += float(group['Metrics']['BlendedCost']['Amount'])
1622
+ if "Groups" in result:
1623
+ for group in result["Groups"]:
1624
+ mcp_total += float(group["Metrics"]["BlendedCost"]["Amount"])
1594
1625
  else:
1595
- mcp_total += float(result['Total']['BlendedCost']['Amount'])
1596
-
1626
+ mcp_total += float(result["Total"]["BlendedCost"]["Amount"])
1627
+
1597
1628
  if finops_total > 0:
1598
1629
  variance_pct = abs(finops_total - mcp_total) / finops_total * 100
1599
-
1630
+
1600
1631
  if variance_pct <= 5.0: # Enhanced tolerance for accuracy
1601
- return {'status': 'validated', 'message': f'Total cost validated: {variance_pct:.1f}% variance'}
1632
+ return {"status": "validated", "message": f"Total cost validated: {variance_pct:.1f}% variance"}
1602
1633
  else:
1603
1634
  return {
1604
- 'status': 'variance_detected',
1605
- 'discrepancy': ValidationDiscrepancy(
1635
+ "status": "variance_detected",
1636
+ "discrepancy": ValidationDiscrepancy(
1606
1637
  source_name="finops_module",
1607
1638
  mcp_name="cost_explorer_api",
1608
1639
  field_name="total_monthly_cost",
@@ -1611,160 +1642,170 @@ class Comprehensive2WayValidator:
1611
1642
  variance_percentage=variance_pct,
1612
1643
  severity="high" if variance_pct > 20 else "medium",
1613
1644
  recommendation=f"Investigate cost calculation discrepancy: {variance_pct:.1f}% variance",
1614
- business_impact=f"Potential ${abs(finops_total - mcp_total):,.2f} reporting discrepancy"
1615
- )
1645
+ business_impact=f"Potential ${abs(finops_total - mcp_total):,.2f} reporting discrepancy",
1646
+ ),
1616
1647
  }
1617
-
1618
- return {'status': 'insufficient_data', 'message': 'Insufficient cost data for validation'}
1648
+
1649
+ return {"status": "insufficient_data", "message": "Insufficient cost data for validation"}
1619
1650
 
1620
1651
  async def _validate_service_breakdown_accuracy(self, finops_data: Dict, mcp_data: Dict) -> Dict[str, Any]:
1621
1652
  """Validate service-level cost breakdown accuracy."""
1622
- return {'status': 'validated', 'message': 'Service breakdown validated'}
1653
+ return {"status": "validated", "message": "Service breakdown validated"}
1623
1654
 
1624
1655
  async def _validate_account_cost_distribution(self, finops_data: Dict, mcp_data: Dict) -> Dict[str, Any]:
1625
1656
  """Validate account-level cost distribution."""
1626
- return {'status': 'validated', 'message': 'Account cost distribution validated'}
1657
+ return {"status": "validated", "message": "Account cost distribution validated"}
1627
1658
 
1628
1659
  async def _validate_quarterly_intelligence(self, finops_data: Dict, mcp_data: Dict) -> Dict[str, Any]:
1629
1660
  """Validate quarterly intelligence integration."""
1630
- return {'status': 'validated', 'message': 'Quarterly intelligence validated'}
1661
+ return {"status": "validated", "message": "Quarterly intelligence validated"}
1631
1662
 
1632
1663
  async def _validate_cost_optimization_accuracy(self, finops_data: Dict, mcp_data: Dict) -> Dict[str, Any]:
1633
1664
  """Validate cost optimization recommendation accuracy."""
1634
- return {'status': 'validated', 'message': 'Cost optimization accuracy validated'}
1665
+ return {"status": "validated", "message": "Cost optimization accuracy validated"}
1635
1666
 
1636
1667
  # Evidence generation methods
1637
- async def _generate_inventory_evidence(self, validation_id: str, inventory_data: Dict,
1638
- discrepancies: List, accuracy: float) -> List[str]:
1668
+ async def _generate_inventory_evidence(
1669
+ self, validation_id: str, inventory_data: Dict, discrepancies: List, accuracy: float
1670
+ ) -> List[str]:
1639
1671
  """Generate inventory validation evidence."""
1640
1672
  evidence_files = []
1641
1673
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
1642
-
1674
+
1643
1675
  # JSON evidence
1644
1676
  json_evidence = {
1645
- 'validation_id': validation_id,
1646
- 'module': 'inventory',
1647
- 'timestamp': timestamp,
1648
- 'accuracy_percentage': accuracy,
1649
- 'inventory_summary': inventory_data,
1650
- 'discrepancies': [asdict(d) for d in discrepancies],
1651
- 'enterprise_compliance': {
1652
- 'accuracy_target_met': accuracy >= self.accuracy_target,
1653
- 'evidence_generated': True,
1654
- 'audit_trail': 'complete'
1655
- }
1677
+ "validation_id": validation_id,
1678
+ "module": "inventory",
1679
+ "timestamp": timestamp,
1680
+ "accuracy_percentage": accuracy,
1681
+ "inventory_summary": inventory_data,
1682
+ "discrepancies": [asdict(d) for d in discrepancies],
1683
+ "enterprise_compliance": {
1684
+ "accuracy_target_met": accuracy >= self.accuracy_target,
1685
+ "evidence_generated": True,
1686
+ "audit_trail": "complete",
1687
+ },
1656
1688
  }
1657
-
1689
+
1658
1690
  json_path = self.evidence_dir / f"inventory_validation_{timestamp}.json"
1659
- with open(json_path, 'w') as f:
1691
+ with open(json_path, "w") as f:
1660
1692
  json.dump(json_evidence, f, indent=2, default=str)
1661
1693
  evidence_files.append(str(json_path))
1662
-
1694
+
1663
1695
  return evidence_files
1664
1696
 
1665
- async def _generate_vpc_evidence(self, validation_id: str, vpc_data: Dict,
1666
- discrepancies: List, accuracy: float) -> List[str]:
1697
+ async def _generate_vpc_evidence(
1698
+ self, validation_id: str, vpc_data: Dict, discrepancies: List, accuracy: float
1699
+ ) -> List[str]:
1667
1700
  """Generate VPC validation evidence."""
1668
1701
  evidence_files = []
1669
1702
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
1670
-
1703
+
1671
1704
  json_evidence = {
1672
- 'validation_id': validation_id,
1673
- 'module': 'vpc',
1674
- 'timestamp': timestamp,
1675
- 'accuracy_percentage': accuracy,
1676
- 'vpc_summary': vpc_data,
1677
- 'discrepancies': [asdict(d) for d in discrepancies]
1705
+ "validation_id": validation_id,
1706
+ "module": "vpc",
1707
+ "timestamp": timestamp,
1708
+ "accuracy_percentage": accuracy,
1709
+ "vpc_summary": vpc_data,
1710
+ "discrepancies": [asdict(d) for d in discrepancies],
1678
1711
  }
1679
-
1712
+
1680
1713
  json_path = self.evidence_dir / f"vpc_validation_{timestamp}.json"
1681
- with open(json_path, 'w') as f:
1714
+ with open(json_path, "w") as f:
1682
1715
  json.dump(json_evidence, f, indent=2, default=str)
1683
1716
  evidence_files.append(str(json_path))
1684
-
1717
+
1685
1718
  return evidence_files
1686
1719
 
1687
- async def _generate_finops_evidence(self, validation_id: str, finops_data: Dict,
1688
- mcp_data: Dict, discrepancies: List, accuracy: float) -> List[str]:
1720
+ async def _generate_finops_evidence(
1721
+ self, validation_id: str, finops_data: Dict, mcp_data: Dict, discrepancies: List, accuracy: float
1722
+ ) -> List[str]:
1689
1723
  """Generate comprehensive FinOps validation evidence."""
1690
1724
  evidence_files = []
1691
1725
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
1692
-
1726
+
1693
1727
  # Enhanced FinOps evidence with MCP cross-validation
1694
1728
  json_evidence = {
1695
- 'validation_id': validation_id,
1696
- 'module': 'finops',
1697
- 'timestamp': timestamp,
1698
- 'accuracy_percentage': accuracy,
1699
- 'accuracy_improvement': '0.0% → ≥99.5% target implementation',
1700
- 'finops_summary': finops_data,
1701
- 'mcp_validation_data': mcp_data,
1702
- 'discrepancies': [asdict(d) for d in discrepancies],
1703
- 'time_synchronization': {
1704
- 'enabled': True,
1705
- 'method': 'enhanced_period_alignment',
1706
- 'accuracy_impact': 'critical_for_enterprise_target'
1729
+ "validation_id": validation_id,
1730
+ "module": "finops",
1731
+ "timestamp": timestamp,
1732
+ "accuracy_percentage": accuracy,
1733
+ "accuracy_improvement": "0.0% → ≥99.5% target implementation",
1734
+ "finops_summary": finops_data,
1735
+ "mcp_validation_data": mcp_data,
1736
+ "discrepancies": [asdict(d) for d in discrepancies],
1737
+ "time_synchronization": {
1738
+ "enabled": True,
1739
+ "method": "enhanced_period_alignment",
1740
+ "accuracy_impact": "critical_for_enterprise_target",
1741
+ },
1742
+ "enterprise_compliance": {
1743
+ "accuracy_target_met": accuracy >= self.accuracy_target,
1744
+ "mcp_integration": mcp_data.get("status") == "success",
1745
+ "evidence_generated": True,
1746
+ "audit_trail": "comprehensive",
1707
1747
  },
1708
- 'enterprise_compliance': {
1709
- 'accuracy_target_met': accuracy >= self.accuracy_target,
1710
- 'mcp_integration': mcp_data.get('status') == 'success',
1711
- 'evidence_generated': True,
1712
- 'audit_trail': 'comprehensive'
1713
- }
1714
1748
  }
1715
-
1749
+
1716
1750
  json_path = self.evidence_dir / f"finops_validation_{timestamp}.json"
1717
- with open(json_path, 'w') as f:
1751
+ with open(json_path, "w") as f:
1718
1752
  json.dump(json_evidence, f, indent=2, default=str)
1719
1753
  evidence_files.append(str(json_path))
1720
-
1754
+
1721
1755
  # CSV summary for business stakeholders
1722
1756
  csv_path = self.evidence_dir / f"finops_validation_summary_{timestamp}.csv"
1723
- with open(csv_path, 'w') as f:
1724
- f.write("Validation_ID,Module,Accuracy_Percentage,Target_Met,Discrepancies,Cost_Impact,Business_Confidence\n")
1725
- f.write(f"{validation_id},finops,{accuracy:.1f}%,{'YES' if accuracy >= self.accuracy_target else 'NO'},{len(discrepancies)},${sum(abs(d.source_value - d.mcp_value) for d in discrepancies if isinstance(d.source_value, (int, float)) and isinstance(d.mcp_value, (int, float))):.2f},{'HIGH' if accuracy >= 95 else 'MEDIUM' if accuracy >= 85 else 'LOW'}\n")
1757
+ with open(csv_path, "w") as f:
1758
+ f.write(
1759
+ "Validation_ID,Module,Accuracy_Percentage,Target_Met,Discrepancies,Cost_Impact,Business_Confidence\n"
1760
+ )
1761
+ f.write(
1762
+ f"{validation_id},finops,{accuracy:.1f}%,{'YES' if accuracy >= self.accuracy_target else 'NO'},{len(discrepancies)},${sum(abs(d.source_value - d.mcp_value) for d in discrepancies if isinstance(d.source_value, (int, float)) and isinstance(d.mcp_value, (int, float))):.2f},{'HIGH' if accuracy >= 95 else 'MEDIUM' if accuracy >= 85 else 'LOW'}\n"
1763
+ )
1726
1764
  evidence_files.append(str(csv_path))
1727
-
1765
+
1728
1766
  return evidence_files
1729
1767
 
1730
1768
  async def _generate_suite_report(self, suite_results: Dict, execution_time: float) -> str:
1731
1769
  """Generate comprehensive suite validation report."""
1732
1770
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
1733
1771
  report_path = self.evidence_dir / f"comprehensive_validation_suite_{timestamp}.json"
1734
-
1772
+
1735
1773
  comprehensive_report = {
1736
1774
  **suite_results,
1737
- 'execution_metadata': {
1738
- 'total_execution_time_seconds': execution_time,
1739
- 'validation_system_version': '1.0.0',
1740
- 'enterprise_framework': 'FAANG_SDLC_compliant',
1741
- 'accuracy_target': self.accuracy_target,
1742
- 'performance_target': self.performance_target_seconds
1775
+ "execution_metadata": {
1776
+ "total_execution_time_seconds": execution_time,
1777
+ "validation_system_version": "1.0.0",
1778
+ "enterprise_framework": "FAANG_SDLC_compliant",
1779
+ "accuracy_target": self.accuracy_target,
1780
+ "performance_target": self.performance_target_seconds,
1781
+ },
1782
+ "enterprise_assessment": {
1783
+ "stakeholder_ready": suite_results.get("enterprise_target_met", False),
1784
+ "compliance_documentation": "complete",
1785
+ "audit_trail": "comprehensive",
1786
+ "business_confidence": "high" if suite_results.get("overall_accuracy", 0) >= 95 else "medium",
1743
1787
  },
1744
- 'enterprise_assessment': {
1745
- 'stakeholder_ready': suite_results.get('enterprise_target_met', False),
1746
- 'compliance_documentation': 'complete',
1747
- 'audit_trail': 'comprehensive',
1748
- 'business_confidence': 'high' if suite_results.get('overall_accuracy', 0) >= 95 else 'medium'
1749
- }
1750
1788
  }
1751
-
1752
- with open(report_path, 'w') as f:
1789
+
1790
+ with open(report_path, "w") as f:
1753
1791
  json.dump(comprehensive_report, f, indent=2, default=str)
1754
-
1792
+
1755
1793
  print_success(f"📊 Comprehensive validation report: {report_path}")
1756
1794
  return str(report_path)
1757
1795
 
1758
1796
  # Business analysis methods
1759
1797
  def _assess_inventory_cost_impact(self, discrepancies: List[ValidationDiscrepancy]) -> float:
1760
1798
  """Assess cost impact of inventory discrepancies."""
1761
- return sum(abs(d.source_value - d.mcp_value) for d in discrepancies
1762
- if isinstance(d.source_value, (int, float)) and isinstance(d.mcp_value, (int, float)))
1799
+ return sum(
1800
+ abs(d.source_value - d.mcp_value)
1801
+ for d in discrepancies
1802
+ if isinstance(d.source_value, (int, float)) and isinstance(d.mcp_value, (int, float))
1803
+ )
1763
1804
 
1764
1805
  def _assess_vpc_cost_impact(self, discrepancies: List[ValidationDiscrepancy]) -> float:
1765
1806
  """Assess cost impact of VPC discrepancies."""
1766
1807
  # VPC discrepancies could have significant network cost implications
1767
- return sum(100.0 for d in discrepancies if d.severity in ['high', 'critical'])
1808
+ return sum(100.0 for d in discrepancies if d.severity in ["high", "critical"])
1768
1809
 
1769
1810
  def _assess_finops_cost_impact(self, discrepancies: List[ValidationDiscrepancy]) -> float:
1770
1811
  """Assess cost impact of FinOps discrepancies."""
@@ -1792,56 +1833,53 @@ class Comprehensive2WayValidator:
1792
1833
  def _calculate_stakeholder_confidence(self, accuracy: float, risk_level: str) -> float:
1793
1834
  """Calculate stakeholder confidence score."""
1794
1835
  base_score = accuracy / 100.0
1795
-
1796
- risk_adjustments = {
1797
- "low": 0.0,
1798
- "medium": -0.1,
1799
- "high": -0.2,
1800
- "critical": -0.4
1801
- }
1802
-
1836
+
1837
+ risk_adjustments = {"low": 0.0, "medium": -0.1, "high": -0.2, "critical": -0.4}
1838
+
1803
1839
  return max(0.0, min(1.0, base_score + risk_adjustments.get(risk_level, -0.2)))
1804
1840
 
1805
1841
  # Recommendation generation methods
1806
- def _generate_inventory_recommendations(self, accuracy: float, discrepancies: List, performance_met: bool) -> List[str]:
1842
+ def _generate_inventory_recommendations(
1843
+ self, accuracy: float, discrepancies: List, performance_met: bool
1844
+ ) -> List[str]:
1807
1845
  """Generate inventory-specific recommendations."""
1808
1846
  recommendations = []
1809
-
1847
+
1810
1848
  if accuracy >= self.accuracy_target:
1811
1849
  recommendations.append("✅ Inventory validation passed enterprise standards")
1812
1850
  recommendations.append("📊 Inventory data suitable for stakeholder reporting")
1813
1851
  else:
1814
1852
  recommendations.append("⚠️ Inventory accuracy below enterprise target - investigate discrepancies")
1815
1853
  recommendations.append("🔍 Review account discovery and resource enumeration logic")
1816
-
1854
+
1817
1855
  if not performance_met:
1818
1856
  recommendations.append("⚡ Consider optimization for enterprise performance targets")
1819
-
1857
+
1820
1858
  if discrepancies:
1821
1859
  recommendations.append(f"🔧 Address {len(discrepancies)} validation discrepancies for improved accuracy")
1822
-
1860
+
1823
1861
  return recommendations
1824
1862
 
1825
1863
  def _generate_vpc_recommendations(self, accuracy: float, discrepancies: List) -> List[str]:
1826
1864
  """Generate VPC-specific recommendations."""
1827
1865
  recommendations = []
1828
-
1866
+
1829
1867
  if accuracy >= self.accuracy_target:
1830
1868
  recommendations.append("✅ VPC validation meets enterprise accuracy standards")
1831
1869
  recommendations.append("🌐 Network cost correlation validated for financial reporting")
1832
1870
  else:
1833
1871
  recommendations.append("⚠️ VPC validation requires attention - network cost implications")
1834
1872
  recommendations.append("💰 Review VPC cost attribution and optimization logic")
1835
-
1873
+
1836
1874
  if discrepancies:
1837
1875
  recommendations.append("🔧 Address VPC configuration discrepancies for network accuracy")
1838
-
1876
+
1839
1877
  return recommendations
1840
1878
 
1841
1879
  def _generate_finops_recommendations(self, accuracy: float, discrepancies: List) -> List[str]:
1842
1880
  """Generate FinOps-specific recommendations."""
1843
1881
  recommendations = []
1844
-
1882
+
1845
1883
  if accuracy >= self.accuracy_target:
1846
1884
  recommendations.append("✅ FinOps MCP validation achieved enterprise target!")
1847
1885
  recommendations.append("📈 Cost analysis ready for executive presentation")
@@ -1850,41 +1888,49 @@ class Comprehensive2WayValidator:
1850
1888
  recommendations.append("⚠️ FinOps accuracy below target - implement time synchronization")
1851
1889
  recommendations.append("🕐 Review MCP Cost Explorer integration for period alignment")
1852
1890
  recommendations.append("💰 Validate cost calculation methodology against AWS APIs")
1853
-
1891
+
1854
1892
  if discrepancies:
1855
1893
  recommendations.append("🔧 Address cost calculation discrepancies for financial accuracy")
1856
1894
  recommendations.append("📊 Review quarterly intelligence integration for strategic reporting")
1857
-
1895
+
1858
1896
  return recommendations
1859
1897
 
1860
1898
  def _consolidate_recommendations(self, results: List[Comprehensive2WayValidationResult]) -> List[str]:
1861
1899
  """Consolidate recommendations across all validation results."""
1862
1900
  all_recommendations = []
1863
-
1901
+
1864
1902
  # Add enterprise-level recommendations
1865
1903
  overall_accuracy = sum(r.validation_accuracy_percentage for r in results) / len(results) if results else 0
1866
-
1904
+
1867
1905
  if overall_accuracy >= self.accuracy_target:
1868
1906
  all_recommendations.append("🏆 ENTERPRISE SUCCESS: Overall validation accuracy meets enterprise target")
1869
1907
  all_recommendations.append("📊 All modules ready for stakeholder presentation")
1870
1908
  else:
1871
1909
  all_recommendations.append("⚠️ ENTERPRISE ATTENTION: Overall accuracy requires improvement")
1872
1910
  all_recommendations.append("🎯 Focus on modules below enterprise accuracy threshold")
1873
-
1911
+
1874
1912
  # Add module-specific top recommendations
1875
1913
  for result in results:
1876
1914
  if result.recommendations:
1877
1915
  all_recommendations.extend(result.recommendations[:2]) # Top 2 per module
1878
-
1916
+
1879
1917
  return list(set(all_recommendations)) # Remove duplicates
1880
1918
 
1881
1919
  def _consolidate_business_impact(self, results: List[Comprehensive2WayValidationResult]) -> Dict[str, Any]:
1882
1920
  """Consolidate business impact analysis."""
1883
1921
  return {
1884
- 'total_estimated_cost_impact': sum(r.estimated_cost_impact for r in results),
1885
- 'highest_risk_module': max(results, key=lambda r: {'low': 1, 'medium': 2, 'high': 3, 'critical': 4}.get(r.risk_level, 0)).module_name if results else None,
1886
- 'average_stakeholder_confidence': sum(r.stakeholder_confidence_score for r in results) / len(results) if results else 0,
1887
- 'modules_requiring_attention': [r.module_name for r in results if r.validation_accuracy_percentage < self.accuracy_target]
1922
+ "total_estimated_cost_impact": sum(r.estimated_cost_impact for r in results),
1923
+ "highest_risk_module": max(
1924
+ results, key=lambda r: {"low": 1, "medium": 2, "high": 3, "critical": 4}.get(r.risk_level, 0)
1925
+ ).module_name
1926
+ if results
1927
+ else None,
1928
+ "average_stakeholder_confidence": sum(r.stakeholder_confidence_score for r in results) / len(results)
1929
+ if results
1930
+ else 0,
1931
+ "modules_requiring_attention": [
1932
+ r.module_name for r in results if r.validation_accuracy_percentage < self.accuracy_target
1933
+ ],
1888
1934
  }
1889
1935
 
1890
1936
  # Infrastructure drift detection
@@ -1908,40 +1954,43 @@ class Comprehensive2WayValidator:
1908
1954
  if not self.validation_sessions:
1909
1955
  print_warning("No validation sessions available for export")
1910
1956
  return ""
1911
-
1957
+
1912
1958
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
1913
-
1959
+
1914
1960
  if output_format.lower() == "json":
1915
1961
  report_path = self.evidence_dir / f"stakeholder_validation_report_{timestamp}.json"
1916
-
1962
+
1917
1963
  stakeholder_report = {
1918
- 'report_metadata': {
1919
- 'generated_timestamp': datetime.now().isoformat(),
1920
- 'validation_system': 'Comprehensive 2-Way Validator',
1921
- 'version': '1.0.0',
1922
- 'enterprise_compliance': True
1964
+ "report_metadata": {
1965
+ "generated_timestamp": datetime.now().isoformat(),
1966
+ "validation_system": "Comprehensive 2-Way Validator",
1967
+ "version": "1.0.0",
1968
+ "enterprise_compliance": True,
1923
1969
  },
1924
- 'executive_summary': {
1925
- 'total_validations': len(self.validation_sessions),
1926
- 'overall_accuracy': sum(s.validation_accuracy_percentage for s in self.validation_sessions) / len(self.validation_sessions),
1927
- 'enterprise_target_met': all(s.validation_accuracy_percentage >= self.accuracy_target for s in self.validation_sessions),
1928
- 'modules_validated': [s.module_name for s in self.validation_sessions]
1970
+ "executive_summary": {
1971
+ "total_validations": len(self.validation_sessions),
1972
+ "overall_accuracy": sum(s.validation_accuracy_percentage for s in self.validation_sessions)
1973
+ / len(self.validation_sessions),
1974
+ "enterprise_target_met": all(
1975
+ s.validation_accuracy_percentage >= self.accuracy_target for s in self.validation_sessions
1976
+ ),
1977
+ "modules_validated": [s.module_name for s in self.validation_sessions],
1978
+ },
1979
+ "detailed_results": [asdict(session) for session in self.validation_sessions],
1980
+ "business_recommendations": self._consolidate_recommendations(self.validation_sessions),
1981
+ "compliance_attestation": {
1982
+ "sox_compliance": True,
1983
+ "audit_trail": "comprehensive",
1984
+ "evidence_collection": "complete",
1929
1985
  },
1930
- 'detailed_results': [asdict(session) for session in self.validation_sessions],
1931
- 'business_recommendations': self._consolidate_recommendations(self.validation_sessions),
1932
- 'compliance_attestation': {
1933
- 'sox_compliance': True,
1934
- 'audit_trail': 'comprehensive',
1935
- 'evidence_collection': 'complete'
1936
- }
1937
1986
  }
1938
-
1939
- with open(report_path, 'w') as f:
1987
+
1988
+ with open(report_path, "w") as f:
1940
1989
  json.dump(stakeholder_report, f, indent=2, default=str)
1941
-
1990
+
1942
1991
  print_success(f"📊 Stakeholder report exported: {report_path}")
1943
1992
  return str(report_path)
1944
-
1993
+
1945
1994
  else:
1946
1995
  print_error(f"Unsupported export format: {output_format}")
1947
1996
  return ""
@@ -1951,10 +2000,8 @@ class Comprehensive2WayValidator:
1951
2000
  async def main():
1952
2001
  """Main CLI interface for comprehensive validation."""
1953
2002
  import argparse
1954
-
1955
- parser = argparse.ArgumentParser(
1956
- description="Comprehensive 2-Way Validation System - Enterprise MCP Integration"
1957
- )
2003
+
2004
+ parser = argparse.ArgumentParser(description="Comprehensive 2-Way Validation System - Enterprise MCP Integration")
1958
2005
  parser.add_argument("--inventory-csv", help="Path to inventory CSV export")
1959
2006
  parser.add_argument("--vpc-analysis", help="Path to VPC analysis results")
1960
2007
  parser.add_argument("--finops-export", help="Path to FinOps export data")
@@ -1962,38 +2009,37 @@ async def main():
1962
2009
  parser.add_argument("--performance-target", type=float, default=30.0, help="Performance target in seconds")
1963
2010
  parser.add_argument("--export-report", choices=["json"], default="json", help="Export stakeholder report format")
1964
2011
  parser.add_argument("--run-full-suite", action="store_true", help="Run comprehensive validation suite")
1965
-
2012
+
1966
2013
  args = parser.parse_args()
1967
-
2014
+
1968
2015
  # Initialize validator
1969
2016
  validator = Comprehensive2WayValidator(
1970
- accuracy_target=args.accuracy_target,
1971
- performance_target_seconds=args.performance_target
2017
+ accuracy_target=args.accuracy_target, performance_target_seconds=args.performance_target
1972
2018
  )
1973
-
2019
+
1974
2020
  if args.run_full_suite:
1975
2021
  print_header("Enterprise 2-Way Validation Suite", "Full Execution")
1976
-
2022
+
1977
2023
  # Run comprehensive validation suite
1978
2024
  suite_results = await validator.run_comprehensive_validation_suite(
1979
- inventory_csv=args.inventory_csv,
1980
- vpc_analysis=args.vpc_analysis,
1981
- finops_export=args.finops_export
2025
+ inventory_csv=args.inventory_csv, vpc_analysis=args.vpc_analysis, finops_export=args.finops_export
1982
2026
  )
1983
-
2027
+
1984
2028
  # Export stakeholder report
1985
2029
  report_path = await validator.export_stakeholder_report(args.export_report)
1986
-
1987
- if suite_results['enterprise_target_met']:
2030
+
2031
+ if suite_results["enterprise_target_met"]:
1988
2032
  print_success("🏆 ENTERPRISE VALIDATION COMPLETE: All targets met!")
1989
- print_success(f"📊 Overall Accuracy: {suite_results['overall_accuracy']:.1f}% (≥{args.accuracy_target}% target)")
2033
+ print_success(
2034
+ f"📊 Overall Accuracy: {suite_results['overall_accuracy']:.1f}% (≥{args.accuracy_target}% target)"
2035
+ )
1990
2036
  else:
1991
2037
  print_warning("⚠️ ENTERPRISE ATTENTION: Review validation results")
1992
2038
  print_info("🔧 Implement recommendations to achieve enterprise targets")
1993
-
2039
+
1994
2040
  if report_path:
1995
2041
  print_success(f"📄 Stakeholder report ready: {report_path}")
1996
-
2042
+
1997
2043
  else:
1998
2044
  # Run individual module validations
1999
2045
  print_info("💡 Use --run-full-suite for comprehensive enterprise validation")
@@ -2004,4 +2050,4 @@ async def main():
2004
2050
 
2005
2051
 
2006
2052
  if __name__ == "__main__":
2007
- asyncio.run(main())
2053
+ asyncio.run(main())