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