petter2025 commited on
Commit
f4ec74a
·
verified ·
1 Parent(s): aa90f50

Delete infrastructure

Browse files
infrastructure/__init__.py DELETED
@@ -1,23 +0,0 @@
1
- from .intents import (
2
- ResourceType, PermissionLevel, Environment, ChangeScope,
3
- ProvisionResourceIntent, DeployConfigurationIntent, GrantAccessIntent,
4
- InfrastructureIntent
5
- )
6
- from .policies import (
7
- Policy, RegionAllowedPolicy, ResourceTypeRestrictedPolicy,
8
- MaxPermissionLevelPolicy, CostThresholdPolicy, PolicyEvaluator,
9
- allow_all, deny_all
10
- )
11
- from .cost_estimator import CostEstimator
12
- from .risk_engine import RiskEngine
13
- from .healing_intent import HealingIntent, RecommendedAction, IntentSource
14
- from .azure.azure_simulator import AzureInfrastructureSimulator
15
-
16
- __all__ = [
17
- "ResourceType", "PermissionLevel", "Environment", "ChangeScope",
18
- "ProvisionResourceIntent", "DeployConfigurationIntent", "GrantAccessIntent",
19
- "InfrastructureIntent", "Policy", "RegionAllowedPolicy",
20
- "ResourceTypeRestrictedPolicy", "MaxPermissionLevelPolicy", "CostThresholdPolicy",
21
- "PolicyEvaluator", "allow_all", "deny_all", "CostEstimator", "RiskEngine",
22
- "HealingIntent", "RecommendedAction", "IntentSource", "AzureInfrastructureSimulator"
23
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/azure/__init__.py DELETED
@@ -1,4 +0,0 @@
1
- from .azure_simulator import AzureInfrastructureSimulator
2
- from .azure_models import AzureResource, AzureDeployment
3
-
4
- __all__ = ["AzureInfrastructureSimulator", "AzureResource", "AzureDeployment"]
 
 
 
 
 
infrastructure/azure/azure_models.py DELETED
@@ -1,17 +0,0 @@
1
- """
2
- Azure-specific models (minimal for simulation).
3
- """
4
- from pydantic import BaseModel
5
- from typing import Optional, Dict, Any
6
-
7
- class AzureResource(BaseModel):
8
- resource_id: str
9
- resource_type: str
10
- location: str
11
- tags: Dict[str, str] = {}
12
-
13
- class AzureDeployment(BaseModel):
14
- deployment_id: str
15
- template: Dict[str, Any]
16
- parameters: Dict[str, Any]
17
- resource_group: str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/azure/azure_simulator.py DELETED
@@ -1,89 +0,0 @@
1
- """
2
- Azure Infrastructure Simulator – Main orchestration engine.
3
- """
4
-
5
- from typing import List, Optional, Dict, Any
6
-
7
- from ..intents import (
8
- InfrastructureIntent,
9
- ProvisionResourceIntent,
10
- )
11
- from ..policies import (
12
- Policy,
13
- PolicyEvaluator,
14
- CostThresholdPolicy,
15
- )
16
- from ..cost_estimator import CostEstimator
17
- from ..risk_engine import RiskEngine
18
- from ..healing_intent import (
19
- HealingIntent,
20
- RecommendedAction,
21
- IntentSource,
22
- )
23
- from ..constants import MAX_POLICY_VIOLATIONS
24
-
25
-
26
- class AzureInfrastructureSimulator:
27
- def __init__(
28
- self,
29
- policy: Policy,
30
- pricing_file: Optional[str] = None,
31
- risk_factors: Optional[List] = None,
32
- ):
33
- self._policy_evaluator = PolicyEvaluator(policy)
34
- self._cost_estimator = CostEstimator(pricing_file)
35
- self._risk_engine = RiskEngine(risk_factors if risk_factors else RiskEngine.DEFAULT_FACTORS)
36
-
37
- def evaluate(self, intent: InfrastructureIntent) -> HealingIntent:
38
- cost = None
39
- if isinstance(intent, ProvisionResourceIntent):
40
- cost = self._cost_estimator.estimate_monthly_cost(intent)
41
-
42
- context = {"cost_estimate": cost} if cost is not None else {}
43
- violations = self._policy_evaluator.evaluate(intent, context)
44
-
45
- if len(violations) > MAX_POLICY_VIOLATIONS:
46
- violations = violations[:MAX_POLICY_VIOLATIONS]
47
-
48
- risk_score, explanation, contributions = self._risk_engine.calculate_risk(
49
- intent, cost, violations
50
- )
51
-
52
- if risk_score > 0.8 or violations:
53
- recommended_action = RecommendedAction.DENY
54
- elif risk_score > 0.4:
55
- recommended_action = RecommendedAction.ESCALATE
56
- else:
57
- recommended_action = RecommendedAction.APPROVE
58
-
59
- justification_parts = [f"Risk score: {risk_score:.2f}."]
60
- if cost is not None:
61
- justification_parts.append(f"Estimated monthly cost: ${cost:.2f}.")
62
- if violations:
63
- justification_parts.append(f"Policy violations: {'; '.join(violations)}.")
64
- justification_parts.append(explanation)
65
- justification = " ".join(justification_parts)
66
-
67
- intent_summary = f"{intent.intent_type} requested by {intent.requester}"
68
-
69
- details = {
70
- "cost_estimate": cost,
71
- "violations": violations,
72
- "risk_score": risk_score,
73
- "factor_contributions": contributions,
74
- }
75
-
76
- healing_intent = HealingIntent(
77
- intent_id=intent.intent_id,
78
- intent_summary=intent_summary,
79
- cost_projection=cost,
80
- risk_score=risk_score,
81
- policy_violations=violations,
82
- recommended_action=recommended_action,
83
- justification=justification,
84
- confidence_score=0.9,
85
- evaluation_details=details,
86
- source=IntentSource.INFRASTRUCTURE_ANALYSIS,
87
- )
88
-
89
- return healing_intent.mark_as_oss_advisory()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/constants.py DELETED
@@ -1,21 +0,0 @@
1
- """
2
- ARF OSS constants – shared across modules.
3
- """
4
-
5
- OSS_EDITION = "OSS"
6
- OSS_LICENSE = "Apache 2.0"
7
- ENTERPRISE_UPGRADE_URL = "https://huggingface.co/spaces/petter2025/agentic-reliability-framework?enterprise"
8
- EXECUTION_ALLOWED = False
9
-
10
- # Limits
11
- MAX_SIMILARITY_CACHE = 100
12
- SIMILARITY_THRESHOLD = 0.7
13
- MAX_POLICY_VIOLATIONS = 10
14
- MAX_RISK_FACTORS = 20
15
- MAX_COST_PROJECTIONS = 5
16
- MAX_DECISION_TREE_DEPTH = 5
17
- MAX_ALTERNATIVE_ACTIONS = 5
18
-
19
- class OSSBoundaryError(Exception):
20
- """Raised when OSS edition attempts an enterprise-only operation."""
21
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/cost_estimator.py DELETED
@@ -1,102 +0,0 @@
1
- """
2
- Cost Estimation Engine – Deterministic pricing with Bayesian uncertainty.
3
- """
4
-
5
- import os
6
- from functools import lru_cache
7
- from typing import Dict, Optional, Union, Any
8
- import yaml
9
-
10
- from .intents import ProvisionResourceIntent, ResourceType
11
-
12
- class CostEstimator:
13
- DEFAULT_PRICING = {
14
- ResourceType.VM: {
15
- "Standard_D2s_v3": 70.0,
16
- "Standard_D4s_v3": 140.0,
17
- "Standard_D8s_v3": 280.0,
18
- "Standard_D16s_v3": 560.0,
19
- },
20
- ResourceType.STORAGE_ACCOUNT: {
21
- "50GB": 5.0,
22
- "100GB": 10.0,
23
- "1TB": 100.0,
24
- "10TB": 900.0,
25
- },
26
- ResourceType.DATABASE: {
27
- "Basic": 15.0,
28
- "Standard": 50.0,
29
- "Premium": 200.0,
30
- },
31
- ResourceType.KUBERNETES_CLUSTER: {
32
- "Small": 100.0,
33
- "Medium": 300.0,
34
- "Large": 600.0,
35
- },
36
- ResourceType.FUNCTION_APP: {
37
- "Consumption": 0.0,
38
- "Premium": 75.0,
39
- },
40
- ResourceType.VIRTUAL_NETWORK: {
41
- "default": 0.0,
42
- },
43
- }
44
-
45
- def __init__(self, pricing_file: Optional[str] = None):
46
- if pricing_file and os.path.exists(pricing_file):
47
- with open(pricing_file, 'r') as f:
48
- raw = yaml.safe_load(f)
49
- self._pricing = {}
50
- for res_str, sizes in raw.items():
51
- try:
52
- res_type = ResourceType(res_str)
53
- except ValueError:
54
- continue
55
- self._pricing[res_type] = sizes
56
- else:
57
- self._pricing = self.DEFAULT_PRICING.copy()
58
-
59
- # Cache for estimate_monthly_cost using a hashable key
60
- self._cost_cache = {}
61
-
62
- def estimate_monthly_cost(self, intent: ProvisionResourceIntent) -> Optional[float]:
63
- # Create a hashable key from the intent's immutable fields
64
- # (resource_type, size, region, environment) – configuration is omitted as it doesn't affect cost in this demo.
65
- key = (intent.resource_type, intent.size, intent.region, intent.environment)
66
- if key in self._cost_cache:
67
- return self._cost_cache[key]
68
-
69
- resource_pricing = self._pricing.get(intent.resource_type)
70
- if not resource_pricing:
71
- self._cost_cache[key] = None
72
- return None
73
- cost = resource_pricing.get(intent.size)
74
- self._cost_cache[key] = cost
75
- return cost
76
-
77
- def cost_delta_vs_baseline(
78
- self,
79
- intent: ProvisionResourceIntent,
80
- baseline_intent: Optional[ProvisionResourceIntent] = None,
81
- ) -> Optional[float]:
82
- proposed = self.estimate_monthly_cost(intent)
83
- if proposed is None:
84
- return None
85
-
86
- if baseline_intent:
87
- baseline = self.estimate_monthly_cost(baseline_intent)
88
- if baseline is None:
89
- return None
90
- return proposed - baseline
91
- else:
92
- resource_pricing = self._pricing.get(intent.resource_type)
93
- if not resource_pricing:
94
- return None
95
- min_cost = min(resource_pricing.values())
96
- return proposed - min_cost
97
-
98
- def estimate_cost_distribution(self, intent: ProvisionResourceIntent) -> Dict[str, float]:
99
- cost = self.estimate_monthly_cost(intent)
100
- if cost is None:
101
- return {}
102
- return {str(cost): 1.0}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/healing_intent.py DELETED
@@ -1,848 +0,0 @@
1
- """
2
- Healing Intent - OSS creates, Enterprise executes
3
- """
4
-
5
- from dataclasses import dataclass, field, asdict
6
- from typing import Dict, Any, Optional, List, ClassVar, Tuple, Union
7
- from datetime import datetime
8
- import hashlib
9
- import json
10
- import time
11
- import uuid
12
- from enum import Enum
13
- import numpy as np
14
-
15
- from .intents import InfrastructureIntent
16
- from .constants import (
17
- OSS_EDITION,
18
- OSS_LICENSE,
19
- ENTERPRISE_UPGRADE_URL,
20
- EXECUTION_ALLOWED,
21
- MAX_SIMILARITY_CACHE,
22
- SIMILARITY_THRESHOLD,
23
- MAX_POLICY_VIOLATIONS,
24
- MAX_RISK_FACTORS,
25
- MAX_COST_PROJECTIONS,
26
- MAX_DECISION_TREE_DEPTH,
27
- MAX_ALTERNATIVE_ACTIONS,
28
- OSSBoundaryError,
29
- )
30
-
31
- class HealingIntentError(Exception): pass
32
- class SerializationError(HealingIntentError): pass
33
- class ValidationError(HealingIntentError): pass
34
-
35
- class IntentSource(str, Enum):
36
- OSS_ANALYSIS = "oss_analysis"
37
- HUMAN_OVERRIDE = "human_override"
38
- AUTOMATED_LEARNING = "automated_learning"
39
- SCHEDULED_ACTION = "scheduled_action"
40
- RAG_SIMILARITY = "rag_similarity"
41
- INFRASTRUCTURE_ANALYSIS = "infrastructure_analysis"
42
- POLICY_VIOLATION = "policy_violation"
43
- COST_OPTIMIZATION = "cost_optimization"
44
-
45
- class IntentStatus(str, Enum):
46
- CREATED = "created"
47
- PENDING_EXECUTION = "pending_execution"
48
- EXECUTING = "executing"
49
- EXECUTING_PARTIAL = "executing_partial"
50
- COMPLETED = "completed"
51
- COMPLETED_PARTIAL = "completed_partial"
52
- FAILED = "failed"
53
- REJECTED = "rejected"
54
- CANCELLED = "cancelled"
55
- ROLLED_BACK = "rolled_back"
56
- OSS_ADVISORY_ONLY = "oss_advisory_only"
57
- PENDING_APPROVAL = "pending_approval"
58
- APPROVED = "approved"
59
- APPROVED_WITH_OVERRIDES = "approved_with_overrides"
60
-
61
- class RecommendedAction(str, Enum):
62
- APPROVE = "approve"
63
- DENY = "deny"
64
- ESCALATE = "escalate"
65
- DEFER = "defer"
66
-
67
- class ConfidenceDistribution:
68
- def __init__(self, mean: float, std: float = 0.05, samples: Optional[List[float]] = None):
69
- self.mean = max(0.0, min(mean, 1.0))
70
- self.std = max(0.0, min(std, 0.5))
71
- self._samples = samples or list(np.random.normal(self.mean, self.std, 1000).clip(0, 1))
72
-
73
- @property
74
- def p5(self) -> float:
75
- return float(np.percentile(self._samples, 5))
76
-
77
- @property
78
- def p50(self) -> float:
79
- return float(np.percentile(self._samples, 50))
80
-
81
- @property
82
- def p95(self) -> float:
83
- return float(np.percentile(self._samples, 95))
84
-
85
- @property
86
- def confidence_interval(self) -> Tuple[float, float]:
87
- return (self.p5, self.p95)
88
-
89
- def to_dict(self) -> Dict[str, float]:
90
- return {
91
- "mean": self.mean,
92
- "std": self.std,
93
- "p5": self.p5,
94
- "p50": self.p50,
95
- "p95": self.p95
96
- }
97
-
98
- @classmethod
99
- def from_dict(cls, data: Dict[str, float]) -> "ConfidenceDistribution":
100
- return cls(mean=data["mean"], std=data.get("std", 0.05), samples=None)
101
-
102
- def __repr__(self) -> str:
103
- return f"ConfidenceDistribution(mean={self.mean:.3f}, 95% CI=[{self.p5:.3f}, {self.p95:.3f}])"
104
-
105
- @dataclass(frozen=True, slots=True)
106
- class HealingIntent:
107
- action: str
108
- component: str
109
- parameters: Dict[str, Any] = field(default_factory=dict)
110
- justification: str = ""
111
- confidence: float = 0.85
112
- confidence_distribution: Optional[Dict[str, float]] = None
113
- incident_id: str = ""
114
- detected_at: float = field(default_factory=time.time)
115
- risk_score: Optional[float] = None
116
- risk_factors: Optional[Dict[str, float]] = None
117
- cost_projection: Optional[float] = None
118
- cost_confidence_interval: Optional[Tuple[float, float]] = None
119
- recommended_action: Optional[RecommendedAction] = None
120
- decision_tree: Optional[List[Dict[str, Any]]] = None
121
- alternative_actions: Optional[List[Dict[str, Any]]] = None
122
- risk_profile: Optional[str] = None
123
- reasoning_chain: Optional[List[Dict[str, Any]]] = None
124
- similar_incidents: Optional[List[Dict[str, Any]]] = None
125
- rag_similarity_score: Optional[float] = None
126
- source: IntentSource = IntentSource.OSS_ANALYSIS
127
- intent_id: str = field(default_factory=lambda: f"intent_{uuid.uuid4().hex[:16]}")
128
- created_at: float = field(default_factory=time.time)
129
- status: IntentStatus = IntentStatus.CREATED
130
- execution_id: Optional[str] = None
131
- executed_at: Optional[float] = None
132
- execution_result: Optional[Dict[str, Any]] = None
133
- enterprise_metadata: Dict[str, Any] = field(default_factory=dict)
134
- human_overrides: List[Dict[str, Any]] = field(default_factory=list)
135
- approvals: List[Dict[str, Any]] = field(default_factory=list)
136
- comments: List[Dict[str, Any]] = field(default_factory=list)
137
- oss_edition: str = OSS_EDITION
138
- oss_license: str = OSS_LICENSE
139
- requires_enterprise: bool = True
140
- execution_allowed: bool = EXECUTION_ALLOWED
141
- infrastructure_intent_id: Optional[str] = None
142
- policy_violations: List[str] = field(default_factory=list)
143
- infrastructure_intent: Optional[Dict[str, Any]] = None
144
-
145
- MIN_CONFIDENCE: ClassVar[float] = 0.0
146
- MAX_CONFIDENCE: ClassVar[float] = 1.0
147
- MAX_JUSTIFICATION_LENGTH: ClassVar[int] = 5000
148
- MAX_PARAMETERS_SIZE: ClassVar[int] = 100
149
- MAX_SIMILAR_INCIDENTS: ClassVar[int] = MAX_SIMILARITY_CACHE
150
- VERSION: ClassVar[str] = "2.0.0"
151
-
152
- def __post_init__(self) -> None:
153
- self._validate_oss_boundaries()
154
- self._validate_risk_integration()
155
-
156
- def _validate_oss_boundaries(self) -> None:
157
- errors: List[str] = []
158
- if not (self.MIN_CONFIDENCE <= self.confidence <= self.MAX_CONFIDENCE):
159
- errors.append(f"Confidence must be between {self.MIN_CONFIDENCE} and {self.MAX_CONFIDENCE}, got {self.confidence}")
160
- if len(self.justification) > self.MAX_JUSTIFICATION_LENGTH:
161
- errors.append(f"Justification exceeds max length {self.MAX_JUSTIFICATION_LENGTH}")
162
- if not self.action or not self.action.strip():
163
- errors.append("Action cannot be empty")
164
- if not self.component or not self.component.strip():
165
- errors.append("Component cannot be empty")
166
- if len(self.parameters) > self.MAX_PARAMETERS_SIZE:
167
- errors.append(f"Too many parameters: {len(self.parameters)} > {self.MAX_PARAMETERS_SIZE}")
168
- try:
169
- json.dumps(self.parameters)
170
- except (TypeError, ValueError) as e:
171
- errors.append(f"Parameters must be JSON serializable: {e}")
172
- if self.similar_incidents and len(self.similar_incidents) > self.MAX_SIMILAR_INCIDENTS:
173
- errors.append(f"Too many similar incidents: {len(self.similar_incidents)} > {self.MAX_SIMILAR_INCIDENTS}")
174
- if self.oss_edition == OSS_EDITION:
175
- if self.execution_allowed:
176
- errors.append("Execution not allowed in OSS edition")
177
- if self.status == IntentStatus.EXECUTING:
178
- errors.append("EXECUTING status not allowed in OSS edition")
179
- if self.executed_at is not None:
180
- errors.append("executed_at should not be set in OSS edition")
181
- if self.execution_id is not None:
182
- errors.append("execution_id should not be set in OSS edition")
183
- if errors:
184
- raise ValidationError("HealingIntent validation failed:\n" + "\n".join(f" • {error}" for error in errors))
185
-
186
- def _validate_risk_integration(self) -> None:
187
- if self.risk_score is not None and not (0.0 <= self.risk_score <= 1.0):
188
- raise ValidationError(f"Risk score must be between 0 and 1, got {self.risk_score}")
189
- if self.cost_projection is not None and self.cost_projection < 0:
190
- raise ValidationError(f"Cost projection cannot be negative, got {self.cost_projection}")
191
- if self.cost_confidence_interval is not None:
192
- low, high = self.cost_confidence_interval
193
- if low > high:
194
- raise ValidationError(f"Invalid confidence interval: [{low}, {high}]")
195
-
196
- @property
197
- def deterministic_id(self) -> str:
198
- data = {
199
- "action": self.action,
200
- "component": self.component,
201
- "parameters": self._normalize_parameters(self.parameters),
202
- "incident_id": self.incident_id,
203
- "detected_at": int(self.detected_at),
204
- "oss_edition": self.oss_edition,
205
- }
206
- json_str = json.dumps(data, sort_keys=True, default=str)
207
- hash_digest = hashlib.sha256(json_str.encode()).hexdigest()
208
- return f"intent_{hash_digest[:16]}"
209
-
210
- @property
211
- def age_seconds(self) -> float:
212
- return time.time() - self.created_at
213
-
214
- @property
215
- def is_executable(self) -> bool:
216
- if self.oss_edition == OSS_EDITION:
217
- return False
218
- return self.status in [IntentStatus.CREATED, IntentStatus.PENDING_EXECUTION, IntentStatus.APPROVED]
219
-
220
- @property
221
- def is_oss_advisory(self) -> bool:
222
- return self.oss_edition == OSS_EDITION and not self.execution_allowed
223
-
224
- @property
225
- def requires_enterprise_upgrade(self) -> bool:
226
- return self.requires_enterprise and self.oss_edition == OSS_EDITION
227
-
228
- @property
229
- def confidence_interval(self) -> Optional[Tuple[float, float]]:
230
- if self.confidence_distribution:
231
- return (self.confidence_distribution.get("p5", self.confidence), self.confidence_distribution.get("p95", self.confidence))
232
- return None
233
-
234
- def to_enterprise_request(self) -> Dict[str, Any]:
235
- return {
236
- "intent_id": self.deterministic_id,
237
- "action": self.action,
238
- "component": self.component,
239
- "parameters": self.parameters,
240
- "justification": self.justification,
241
- "confidence": self.confidence,
242
- "confidence_interval": self.confidence_interval,
243
- "risk_score": self.risk_score,
244
- "cost_projection": self.cost_projection,
245
- "incident_id": self.incident_id,
246
- "detected_at": self.detected_at,
247
- "created_at": self.created_at,
248
- "source": self.source.value,
249
- "recommended_action": self.recommended_action.value if self.recommended_action else None,
250
- "oss_edition": self.oss_edition,
251
- "oss_license": self.oss_license,
252
- "requires_enterprise": self.requires_enterprise,
253
- "execution_allowed": self.execution_allowed,
254
- "version": self.VERSION,
255
- "oss_metadata": {
256
- "similar_incidents_count": len(self.similar_incidents) if self.similar_incidents else 0,
257
- "rag_similarity_score": self.rag_similarity_score,
258
- "has_reasoning_chain": self.reasoning_chain is not None,
259
- "source": self.source.value,
260
- "is_oss_advisory": self.is_oss_advisory,
261
- "risk_factors": self.risk_factors,
262
- "policy_violations_count": len(self.policy_violations) if self.policy_violations else 0,
263
- "confidence_basis": self._get_confidence_basis(),
264
- "learning_applied": False,
265
- "learning_reason": "OSS advisory mode does not persist or learn from outcomes",
266
- },
267
- "upgrade_url": ENTERPRISE_UPGRADE_URL,
268
- "enterprise_features": [
269
- "autonomous_execution",
270
- "approval_workflows",
271
- "persistent_storage",
272
- "learning_engine",
273
- "audit_trails",
274
- "compliance_reports",
275
- "multi_tenant_support",
276
- "sso_integration",
277
- "24_7_support",
278
- "probabilistic_confidence",
279
- "risk_analytics",
280
- "cost_optimization"
281
- ]
282
- }
283
-
284
- def _get_confidence_basis(self) -> str:
285
- if self.recommended_action == RecommendedAction.DENY and self.policy_violations:
286
- return "policy_violation"
287
- if self.rag_similarity_score and self.rag_similarity_score > SIMILARITY_THRESHOLD:
288
- return "historical_similarity"
289
- if self.risk_score is not None:
290
- return "risk_based"
291
- return "policy_only"
292
-
293
- def to_dict(self, include_oss_context: bool = False) -> Dict[str, Any]:
294
- data = asdict(self)
295
- if "source" in data and isinstance(data["source"], IntentSource):
296
- data["source"] = self.source.value
297
- if "status" in data and isinstance(data["status"], IntentStatus):
298
- data["status"] = self.status.value
299
- if "recommended_action" in data and isinstance(data["recommended_action"], RecommendedAction):
300
- data["recommended_action"] = self.recommended_action.value if self.recommended_action else None
301
- if not include_oss_context:
302
- data.pop("reasoning_chain", None)
303
- data.pop("similar_incidents", None)
304
- data.pop("rag_similarity_score", None)
305
- data.pop("decision_tree", None)
306
- data.pop("alternative_actions", None)
307
- data.pop("infrastructure_intent", None)
308
- data["deterministic_id"] = self.deterministic_id
309
- data["age_seconds"] = self.age_seconds
310
- data["is_executable"] = self.is_executable
311
- data["is_oss_advisory"] = self.is_oss_advisory
312
- data["requires_enterprise_upgrade"] = self.requires_enterprise_upgrade
313
- data["version"] = self.VERSION
314
- data["confidence_interval"] = self.confidence_interval
315
- return data
316
-
317
- def with_execution_result(self, execution_id: str, executed_at: float, result: Dict[str, Any],
318
- status: IntentStatus = IntentStatus.COMPLETED, metadata: Optional[Dict[str, Any]] = None) -> "HealingIntent":
319
- return HealingIntent(
320
- action=self.action, component=self.component, parameters=self.parameters, justification=self.justification,
321
- confidence=self.confidence, confidence_distribution=self.confidence_distribution, incident_id=self.incident_id,
322
- detected_at=self.detected_at, risk_score=self.risk_score, risk_factors=self.risk_factors,
323
- cost_projection=self.cost_projection, cost_confidence_interval=self.cost_confidence_interval,
324
- recommended_action=self.recommended_action, decision_tree=self.decision_tree,
325
- alternative_actions=self.alternative_actions, risk_profile=self.risk_profile,
326
- reasoning_chain=self.reasoning_chain, similar_incidents=self.similar_incidents,
327
- rag_similarity_score=self.rag_similarity_score, source=self.source, intent_id=self.intent_id,
328
- created_at=self.created_at, oss_edition=self.oss_edition, oss_license=self.oss_license,
329
- requires_enterprise=self.requires_enterprise, execution_allowed=self.execution_allowed,
330
- infrastructure_intent_id=self.infrastructure_intent_id, policy_violations=self.policy_violations,
331
- infrastructure_intent=self.infrastructure_intent, status=status, execution_id=execution_id,
332
- executed_at=executed_at, execution_result=result,
333
- enterprise_metadata={**(self.enterprise_metadata or {}), **(metadata or {})},
334
- human_overrides=self.human_overrides, approvals=self.approvals, comments=self.comments
335
- )
336
-
337
- def with_human_approval(self, approver: str, approval_time: float, comments: Optional[str] = None,
338
- overrides: Optional[Dict[str, Any]] = None) -> "HealingIntent":
339
- approval_record = {"approver": approver, "timestamp": approval_time, "comments": comments, "overrides": overrides}
340
- new_overrides = list(self.human_overrides)
341
- if overrides:
342
- new_overrides.append({"overrider": approver, "timestamp": approval_time, "overrides": overrides, "reason": comments})
343
- new_approvals = list(self.approvals) + [approval_record]
344
- new_comments = list(self.comments)
345
- if comments:
346
- new_comments.append({"author": approver, "timestamp": approval_time, "comment": comments})
347
- return HealingIntent(
348
- action=self.action, component=self.component, parameters=self.parameters, justification=self.justification,
349
- confidence=self.confidence, confidence_distribution=self.confidence_distribution, incident_id=self.incident_id,
350
- detected_at=self.detected_at, risk_score=self.risk_score, risk_factors=self.risk_factors,
351
- cost_projection=self.cost_projection, cost_confidence_interval=self.cost_confidence_interval,
352
- recommended_action=self.recommended_action, decision_tree=self.decision_tree,
353
- alternative_actions=self.alternative_actions, risk_profile=self.risk_profile,
354
- reasoning_chain=self.reasoning_chain, similar_incidents=self.similar_incidents,
355
- rag_similarity_score=self.rag_similarity_score, source=self.source, intent_id=self.intent_id,
356
- created_at=self.created_at, status=IntentStatus.APPROVED_WITH_OVERRIDES if overrides else IntentStatus.APPROVED,
357
- execution_id=self.execution_id, executed_at=self.executed_at, execution_result=self.execution_result,
358
- enterprise_metadata=self.enterprise_metadata, human_overrides=new_overrides, approvals=new_approvals,
359
- comments=new_comments, oss_edition=self.oss_edition, oss_license=self.oss_license,
360
- requires_enterprise=self.requires_enterprise, execution_allowed=self.execution_allowed,
361
- infrastructure_intent_id=self.infrastructure_intent_id, policy_violations=self.policy_violations,
362
- infrastructure_intent=self.infrastructure_intent
363
- )
364
-
365
- def mark_as_sent_to_enterprise(self) -> "HealingIntent":
366
- return HealingIntent(
367
- action=self.action, component=self.component, parameters=self.parameters, justification=self.justification,
368
- confidence=self.confidence, confidence_distribution=self.confidence_distribution, incident_id=self.incident_id,
369
- detected_at=self.detected_at, risk_score=self.risk_score, risk_factors=self.risk_factors,
370
- cost_projection=self.cost_projection, cost_confidence_interval=self.cost_confidence_interval,
371
- recommended_action=self.recommended_action, decision_tree=self.decision_tree,
372
- alternative_actions=self.alternative_actions, risk_profile=self.risk_profile,
373
- reasoning_chain=self.reasoning_chain, similar_incidents=self.similar_incidents,
374
- rag_similarity_score=self.rag_similarity_score, source=self.source, intent_id=self.intent_id,
375
- created_at=self.created_at, status=IntentStatus.PENDING_EXECUTION, execution_id=self.execution_id,
376
- executed_at=self.executed_at, execution_result=self.execution_result, enterprise_metadata=self.enterprise_metadata,
377
- human_overrides=self.human_overrides, approvals=self.approvals, comments=self.comments,
378
- oss_edition=self.oss_edition, oss_license=self.oss_license, requires_enterprise=self.requires_enterprise,
379
- execution_allowed=self.execution_allowed, infrastructure_intent_id=self.infrastructure_intent_id,
380
- policy_violations=self.policy_violations, infrastructure_intent=self.infrastructure_intent
381
- )
382
-
383
- def mark_as_oss_advisory(self) -> "HealingIntent":
384
- return HealingIntent(
385
- action=self.action, component=self.component, parameters=self.parameters, justification=self.justification,
386
- confidence=self.confidence, confidence_distribution=self.confidence_distribution, incident_id=self.incident_id,
387
- detected_at=self.detected_at, risk_score=self.risk_score, risk_factors=self.risk_factors,
388
- cost_projection=self.cost_projection, cost_confidence_interval=self.cost_confidence_interval,
389
- recommended_action=self.recommended_action, decision_tree=self.decision_tree,
390
- alternative_actions=self.alternative_actions, risk_profile=self.risk_profile,
391
- reasoning_chain=self.reasoning_chain, similar_incidents=self.similar_incidents,
392
- rag_similarity_score=self.rag_similarity_score, source=self.source, intent_id=self.intent_id,
393
- created_at=self.created_at, status=IntentStatus.OSS_ADVISORY_ONLY, execution_id=self.execution_id,
394
- executed_at=self.executed_at, execution_result=self.execution_result, enterprise_metadata=self.enterprise_metadata,
395
- human_overrides=self.human_overrides, approvals=self.approvals, comments=self.comments,
396
- oss_edition=self.oss_edition, oss_license=self.oss_license, requires_enterprise=self.requires_enterprise,
397
- execution_allowed=False, infrastructure_intent_id=self.infrastructure_intent_id,
398
- policy_violations=self.policy_violations, infrastructure_intent=self.infrastructure_intent
399
- )
400
-
401
- @classmethod
402
- def from_infrastructure_intent(cls, infrastructure_intent: Any, action: str, component: str,
403
- parameters: Dict[str, Any], justification: str, confidence: float = 0.85,
404
- risk_score: Optional[float] = None, risk_factors: Optional[Dict[str, float]] = None,
405
- cost_projection: Optional[float] = None, policy_violations: Optional[List[str]] = None,
406
- recommended_action: Optional[RecommendedAction] = None,
407
- source: IntentSource = IntentSource.INFRASTRUCTURE_ANALYSIS) -> "HealingIntent":
408
- infrastructure_intent_id = getattr(infrastructure_intent, 'intent_id', None)
409
- if hasattr(infrastructure_intent, 'model_dump'):
410
- intent_dict = infrastructure_intent.model_dump()
411
- elif hasattr(infrastructure_intent, 'to_dict'):
412
- intent_dict = infrastructure_intent.to_dict()
413
- else:
414
- intent_dict = {"type": str(type(infrastructure_intent))}
415
- return cls(
416
- action=action, component=component, parameters=parameters, justification=justification, confidence=confidence,
417
- risk_score=risk_score, risk_factors=risk_factors, cost_projection=cost_projection,
418
- policy_violations=policy_violations or [], recommended_action=recommended_action, source=source,
419
- infrastructure_intent_id=infrastructure_intent_id, infrastructure_intent=intent_dict,
420
- oss_edition=OSS_EDITION, requires_enterprise=True, execution_allowed=False
421
- )
422
-
423
- @classmethod
424
- def from_analysis(cls, action: str, component: str, parameters: Dict[str, Any], justification: str,
425
- confidence: float, confidence_std: float = 0.05,
426
- similar_incidents: Optional[List[Dict[str, Any]]] = None,
427
- reasoning_chain: Optional[List[Dict[str, Any]]] = None, incident_id: str = "",
428
- source: IntentSource = IntentSource.OSS_ANALYSIS, rag_similarity_score: Optional[float] = None,
429
- risk_score: Optional[float] = None, cost_projection: Optional[float] = None) -> "HealingIntent":
430
- if similar_incidents and len(similar_incidents) > cls.MAX_SIMILAR_INCIDENTS:
431
- similar_incidents = similar_incidents[:cls.MAX_SIMILAR_INCIDENTS]
432
- conf_dist = ConfidenceDistribution(confidence, confidence_std)
433
- enhanced_confidence = confidence
434
- if similar_incidents:
435
- similarity_scores = [inc.get("similarity", 0.0) for inc in similar_incidents if "similarity" in inc]
436
- if similarity_scores:
437
- avg_similarity = sum(similarity_scores) / len(similarity_scores)
438
- confidence_boost = min(0.2, avg_similarity * 0.3)
439
- enhanced_confidence = min(confidence * (1.0 + confidence_boost), cls.MAX_CONFIDENCE)
440
- final_rag_score = rag_similarity_score
441
- if final_rag_score is None and similar_incidents and len(similar_incidents) > 0:
442
- top_similarities = [inc.get("similarity", 0.0) for inc in similar_incidents[:3] if "similarity" in inc]
443
- if top_similarities:
444
- final_rag_score = sum(top_similarities) / len(top_similarities)
445
- return cls(
446
- action=action, component=component, parameters=parameters, justification=justification,
447
- confidence=enhanced_confidence, confidence_distribution=conf_dist.to_dict(), incident_id=incident_id,
448
- similar_incidents=similar_incidents, reasoning_chain=reasoning_chain, rag_similarity_score=final_rag_score,
449
- source=source, risk_score=risk_score, cost_projection=cost_projection,
450
- oss_edition=OSS_EDITION, requires_enterprise=True, execution_allowed=False
451
- )
452
-
453
- @classmethod
454
- def from_rag_recommendation(cls, action: str, component: str, parameters: Dict[str, Any],
455
- rag_similarity_score: float, similar_incidents: List[Dict[str, Any]],
456
- justification_template: str = "Based on {count} similar historical incidents with {success_rate:.0%} success rate",
457
- success_rate: Optional[float] = None, risk_score: Optional[float] = None,
458
- cost_projection: Optional[float] = None) -> "HealingIntent":
459
- if not similar_incidents:
460
- raise ValidationError("RAG recommendation requires similar incidents")
461
- if success_rate is None:
462
- if len(similar_incidents) == 0:
463
- success_rate = 0.0
464
- else:
465
- successful = sum(1 for inc in similar_incidents if inc.get("success", False))
466
- success_rate = successful / len(similar_incidents)
467
- justification = justification_template.format(count=len(similar_incidents), success_rate=success_rate or 0.0,
468
- action=action, component=component)
469
- base_confidence = rag_similarity_score * 0.8
470
- if success_rate:
471
- base_confidence = base_confidence * (0.7 + success_rate * 0.3)
472
- return cls.from_analysis(action=action, component=component, parameters=parameters, justification=justification,
473
- confidence=min(base_confidence, 0.95), similar_incidents=similar_incidents,
474
- incident_id=similar_incidents[0].get("incident_id", "") if similar_incidents else "",
475
- source=IntentSource.RAG_SIMILARITY, rag_similarity_score=rag_similarity_score,
476
- risk_score=risk_score, cost_projection=cost_projection)
477
-
478
- @classmethod
479
- def from_dict(cls, data: Dict[str, Any]) -> "HealingIntent":
480
- version = data.get("version", "1.0.0")
481
- clean_data = data.copy()
482
- if "source" in clean_data and isinstance(clean_data["source"], str):
483
- clean_data["source"] = IntentSource(clean_data["source"])
484
- if "status" in clean_data and isinstance(clean_data["status"], str):
485
- clean_data["status"] = IntentStatus(clean_data["status"])
486
- if "recommended_action" in clean_data and isinstance(clean_data["recommended_action"], str):
487
- try:
488
- clean_data["recommended_action"] = RecommendedAction(clean_data["recommended_action"])
489
- except ValueError:
490
- clean_data["recommended_action"] = None
491
- clean_data.pop("deterministic_id", None)
492
- clean_data.pop("age_seconds", None)
493
- clean_data.pop("is_executable", None)
494
- clean_data.pop("is_oss_advisory", None)
495
- clean_data.pop("requires_enterprise_upgrade", None)
496
- clean_data.pop("version", None)
497
- clean_data.pop("confidence_interval", None)
498
- return cls(**clean_data)
499
-
500
- def _normalize_parameters(self, params: Dict[str, Any]) -> Dict[str, Any]:
501
- normalized: Dict[str, Any] = {}
502
- for key, value in sorted(params.items()):
503
- normalized[key] = self._normalize_value(value)
504
- return normalized
505
-
506
- def _normalize_value(self, value: Any) -> Any:
507
- if isinstance(value, (int, float, str, bool, type(None))):
508
- return value
509
- elif isinstance(value, (list, tuple, set)):
510
- return tuple(sorted(self._normalize_value(v) for v in value))
511
- elif isinstance(value, dict):
512
- return self._normalize_parameters(value)
513
- elif hasattr(value, '__dict__'):
514
- return self._normalize_parameters(value.__dict__)
515
- else:
516
- try:
517
- return str(value)
518
- except Exception:
519
- return f"<unserializable:{type(value).__name__}>"
520
-
521
- def get_oss_context(self) -> Dict[str, Any]:
522
- return {
523
- "reasoning_chain": self.reasoning_chain,
524
- "similar_incidents": self.similar_incidents,
525
- "rag_similarity_score": self.rag_similarity_score,
526
- "decision_tree": self.decision_tree,
527
- "alternative_actions": self.alternative_actions,
528
- "analysis_timestamp": datetime.fromtimestamp(self.detected_at).isoformat(),
529
- "source": self.source.value,
530
- "created_at": datetime.fromtimestamp(self.created_at).isoformat(),
531
- "oss_edition": self.oss_edition,
532
- "is_oss_advisory": self.is_oss_advisory,
533
- "infrastructure_intent": self.infrastructure_intent,
534
- }
535
-
536
- def get_execution_summary(self) -> Dict[str, Any]:
537
- summary = {
538
- "intent_id": self.deterministic_id,
539
- "action": self.action,
540
- "component": self.component,
541
- "confidence": self.confidence,
542
- "confidence_interval": self.confidence_interval,
543
- "risk_score": self.risk_score,
544
- "cost_projection": self.cost_projection,
545
- "status": self.status.value,
546
- "created_at": datetime.fromtimestamp(self.created_at).isoformat(),
547
- "age_seconds": self.age_seconds,
548
- "oss_edition": self.oss_edition,
549
- "requires_enterprise": self.requires_enterprise,
550
- "is_oss_advisory": self.is_oss_advisory,
551
- "source": self.source.value,
552
- "policy_violations_count": len(self.policy_violations) if self.policy_violations else 0,
553
- "confidence_basis": self._get_confidence_basis(),
554
- }
555
- if self.executed_at:
556
- summary["executed_at"] = datetime.fromtimestamp(self.executed_at).isoformat()
557
- summary["execution_duration_seconds"] = self.executed_at - self.created_at
558
- if self.execution_result:
559
- summary["execution_success"] = self.execution_result.get("success", False)
560
- summary["execution_message"] = self.execution_result.get("message", "")
561
- if self.rag_similarity_score:
562
- summary["rag_similarity_score"] = self.rag_similarity_score
563
- if self.similar_incidents:
564
- summary["similar_incidents_count"] = len(self.similar_incidents)
565
- if self.approvals:
566
- summary["approvals_count"] = len(self.approvals)
567
- summary["approved_by"] = [a.get("approver") for a in self.approvals if a.get("approver")]
568
- if self.human_overrides:
569
- summary["overrides_count"] = len(self.human_overrides)
570
- return summary
571
-
572
- def is_immutable(self) -> bool:
573
- try:
574
- object.__setattr__(self, '_test_immutable', True)
575
- return False
576
- except Exception:
577
- return True
578
-
579
- def __repr__(self) -> str:
580
- return (f"HealingIntent(id={self.deterministic_id[:8]}..., action={self.action}, "
581
- f"component={self.component}, confidence={self.confidence:.2f}, "
582
- f"risk={self.risk_score:.2f if self.risk_score else 'N/A'}, status={self.status.value})")
583
-
584
- class HealingIntentSerializer:
585
- SCHEMA_VERSION: ClassVar[str] = "2.0.0"
586
-
587
- @classmethod
588
- def serialize(cls, intent: HealingIntent, version: str = "2.0.0") -> Dict[str, Any]:
589
- try:
590
- if version == "2.0.0":
591
- return {
592
- "version": version,
593
- "schema_version": cls.SCHEMA_VERSION,
594
- "data": intent.to_dict(include_oss_context=True),
595
- "metadata": {
596
- "serialized_at": time.time(),
597
- "deterministic_id": intent.deterministic_id,
598
- "is_executable": intent.is_executable,
599
- "is_oss_advisory": intent.is_oss_advisory,
600
- "requires_enterprise_upgrade": intent.requires_enterprise_upgrade,
601
- "oss_edition": intent.oss_edition,
602
- "has_probabilistic_confidence": intent.confidence_distribution is not None,
603
- "has_risk_assessment": intent.risk_score is not None,
604
- "has_cost_projection": intent.cost_projection is not None,
605
- }
606
- }
607
- elif version in ["1.1.0", "1.0.0"]:
608
- data = intent.to_dict(include_oss_context=True)
609
- data.pop("confidence_distribution", None)
610
- data.pop("risk_score", None)
611
- data.pop("risk_factors", None)
612
- data.pop("cost_projection", None)
613
- data.pop("cost_confidence_interval", None)
614
- data.pop("recommended_action", None)
615
- data.pop("decision_tree", None)
616
- data.pop("alternative_actions", None)
617
- data.pop("risk_profile", None)
618
- data.pop("human_overrides", None)
619
- data.pop("approvals", None)
620
- data.pop("comments", None)
621
- data.pop("infrastructure_intent_id", None)
622
- data.pop("policy_violations", None)
623
- data.pop("infrastructure_intent", None)
624
- if data.get("status") in [
625
- IntentStatus.EXECUTING_PARTIAL.value,
626
- IntentStatus.COMPLETED_PARTIAL.value,
627
- IntentStatus.ROLLED_BACK.value,
628
- IntentStatus.PENDING_APPROVAL.value,
629
- IntentStatus.APPROVED.value,
630
- IntentStatus.APPROVED_WITH_OVERRIDES.value
631
- ]:
632
- data["status"] = IntentStatus.PENDING_EXECUTION.value
633
- return {
634
- "version": version,
635
- "schema_version": "1.1.0" if version == "1.1.0" else "1.0.0",
636
- "data": data,
637
- "metadata": {
638
- "serialized_at": time.time(),
639
- "deterministic_id": intent.deterministic_id,
640
- "is_executable": intent.is_executable,
641
- "is_oss_advisory": intent.is_oss_advisory,
642
- }
643
- }
644
- else:
645
- raise SerializationError(f"Unsupported version: {version}")
646
- except Exception as e:
647
- raise SerializationError(f"Failed to serialize HealingIntent: {e}") from e
648
-
649
- @classmethod
650
- def deserialize(cls, data: Dict[str, Any]) -> HealingIntent:
651
- try:
652
- version = data.get("version", "1.0.0")
653
- intent_data = data.get("data", data)
654
- if version in ["2.0.0", "1.1.0", "1.0.0"]:
655
- if version.startswith("1."):
656
- intent_data.setdefault("confidence_distribution", None)
657
- intent_data.setdefault("risk_score", None)
658
- intent_data.setdefault("risk_factors", None)
659
- intent_data.setdefault("cost_projection", None)
660
- intent_data.setdefault("cost_confidence_interval", None)
661
- intent_data.setdefault("recommended_action", None)
662
- intent_data.setdefault("decision_tree", None)
663
- intent_data.setdefault("alternative_actions", None)
664
- intent_data.setdefault("risk_profile", None)
665
- intent_data.setdefault("human_overrides", [])
666
- intent_data.setdefault("approvals", [])
667
- intent_data.setdefault("comments", [])
668
- intent_data.setdefault("infrastructure_intent_id", None)
669
- intent_data.setdefault("policy_violations", [])
670
- intent_data.setdefault("infrastructure_intent", None)
671
- return HealingIntent.from_dict(intent_data)
672
- else:
673
- raise SerializationError(f"Unsupported version: {version}")
674
- except KeyError as e:
675
- raise SerializationError(f"Missing required field in serialized data: {e}") from e
676
- except Exception as e:
677
- raise SerializationError(f"Failed to deserialize HealingIntent: {e}") from e
678
-
679
- @classmethod
680
- def to_json(cls, intent: HealingIntent, pretty: bool = False) -> str:
681
- try:
682
- serialized = cls.serialize(intent)
683
- return json.dumps(serialized, indent=2 if pretty else None, default=str)
684
- except Exception as e:
685
- raise SerializationError(f"Failed to convert to JSON: {e}") from e
686
-
687
- @classmethod
688
- def from_json(cls, json_str: str) -> HealingIntent:
689
- try:
690
- data = json.loads(json_str)
691
- return cls.deserialize(data)
692
- except json.JSONDecodeError as e:
693
- raise SerializationError(f"Invalid JSON: {e}") from e
694
- except Exception as e:
695
- raise SerializationError(f"Failed to parse JSON: {e}") from e
696
-
697
- @classmethod
698
- def to_enterprise_json(cls, intent: HealingIntent) -> str:
699
- try:
700
- enterprise_request = intent.to_enterprise_request()
701
- return json.dumps(enterprise_request, default=str)
702
- except Exception as e:
703
- raise SerializationError(f"Failed to create Enterprise JSON: {e}") from e
704
-
705
- @classmethod
706
- def validate_for_oss(cls, intent: HealingIntent) -> bool:
707
- try:
708
- if intent.oss_edition != OSS_EDITION:
709
- return False
710
- if intent.execution_allowed:
711
- return False
712
- if intent.similar_incidents and len(intent.similar_incidents) > HealingIntent.MAX_SIMILAR_INCIDENTS:
713
- return False
714
- if not intent.is_immutable():
715
- return False
716
- if intent.executed_at is not None or intent.execution_id is not None:
717
- return False
718
- return True
719
- except Exception:
720
- return False
721
-
722
- # Factory functions
723
- def create_infrastructure_healing_intent(infrastructure_result: Any, action_mapping: Optional[Dict[str, str]] = None) -> HealingIntent:
724
- if action_mapping is None:
725
- action_mapping = {"approve": "execute", "deny": "block", "escalate": "escalate", "defer": "defer"}
726
- recommended_action = getattr(infrastructure_result, 'recommended_action', None)
727
- if recommended_action and hasattr(recommended_action, 'value'):
728
- action = action_mapping.get(recommended_action.value, "review")
729
- else:
730
- action = "review"
731
- parameters = {
732
- "infrastructure_intent_id": getattr(infrastructure_result, 'intent_id', None),
733
- "risk_score": getattr(infrastructure_result, 'risk_score', None),
734
- "cost_projection": getattr(infrastructure_result, 'cost_projection', None),
735
- "policy_violations": getattr(infrastructure_result, 'policy_violations', []),
736
- "evaluation_details": getattr(infrastructure_result, 'evaluation_details', {})
737
- }
738
- justification_parts = [getattr(infrastructure_result, 'justification', "Infrastructure analysis completed")]
739
- policy_violations = getattr(infrastructure_result, 'policy_violations', [])
740
- if policy_violations:
741
- justification_parts.append(f"Policy violations: {'; '.join(policy_violations)}")
742
- return HealingIntent.from_infrastructure_intent(
743
- infrastructure_intent=getattr(infrastructure_result, 'infrastructure_intent', None),
744
- action=action,
745
- component="infrastructure",
746
- parameters=parameters,
747
- justification=" ".join(justification_parts),
748
- confidence=getattr(infrastructure_result, 'confidence_score', 0.85),
749
- risk_score=getattr(infrastructure_result, 'risk_score', None),
750
- policy_violations=policy_violations,
751
- recommended_action=recommended_action,
752
- source=IntentSource.INFRASTRUCTURE_ANALYSIS
753
- ).mark_as_oss_advisory()
754
-
755
- def create_rollback_intent(component: str, revision: str = "previous", justification: str = "",
756
- incident_id: str = "", similar_incidents: Optional[List[Dict[str, Any]]] = None,
757
- rag_similarity_score: Optional[float] = None, risk_score: Optional[float] = None,
758
- cost_projection: Optional[float] = None) -> HealingIntent:
759
- if not justification:
760
- justification = f"Rollback {component} to {revision} revision"
761
- return HealingIntent.from_analysis(
762
- action="rollback",
763
- component=component,
764
- parameters={"revision": revision},
765
- justification=justification,
766
- confidence=0.9,
767
- similar_incidents=similar_incidents,
768
- incident_id=incident_id,
769
- rag_similarity_score=rag_similarity_score,
770
- risk_score=risk_score,
771
- cost_projection=cost_projection,
772
- ).mark_as_oss_advisory()
773
-
774
- def create_restart_intent(component: str, container_id: Optional[str] = None, justification: str = "",
775
- incident_id: str = "", similar_incidents: Optional[List[Dict[str, Any]]] = None,
776
- rag_similarity_score: Optional[float] = None, risk_score: Optional[float] = None,
777
- cost_projection: Optional[float] = None) -> HealingIntent:
778
- parameters = {}
779
- if container_id:
780
- parameters["container_id"] = container_id
781
- if not justification:
782
- justification = f"Restart container for {component}"
783
- return HealingIntent.from_analysis(
784
- action="restart_container",
785
- component=component,
786
- parameters=parameters,
787
- justification=justification,
788
- confidence=0.85,
789
- similar_incidents=similar_incidents,
790
- incident_id=incident_id,
791
- rag_similarity_score=rag_similarity_score,
792
- risk_score=risk_score,
793
- cost_projection=cost_projection,
794
- ).mark_as_oss_advisory()
795
-
796
- def create_scale_out_intent(component: str, scale_factor: int = 2, justification: str = "",
797
- incident_id: str = "", similar_incidents: Optional[List[Dict[str, Any]]] = None,
798
- rag_similarity_score: Optional[float] = None, risk_score: Optional[float] = None,
799
- cost_projection: Optional[float] = None) -> HealingIntent:
800
- if not justification:
801
- justification = f"Scale out {component} by factor {scale_factor}"
802
- return HealingIntent.from_analysis(
803
- action="scale_out",
804
- component=component,
805
- parameters={"scale_factor": scale_factor},
806
- justification=justification,
807
- confidence=0.8,
808
- similar_incidents=similar_incidents,
809
- incident_id=incident_id,
810
- rag_similarity_score=rag_similarity_score,
811
- risk_score=risk_score,
812
- cost_projection=cost_projection,
813
- ).mark_as_oss_advisory()
814
-
815
- def create_oss_advisory_intent(action: str, component: str, parameters: Dict[str, Any], justification: str,
816
- confidence: float = 0.85, incident_id: str = "", risk_score: Optional[float] = None,
817
- cost_projection: Optional[float] = None) -> HealingIntent:
818
- return HealingIntent(
819
- action=action,
820
- component=component,
821
- parameters=parameters,
822
- justification=justification,
823
- confidence=confidence,
824
- incident_id=incident_id,
825
- risk_score=risk_score,
826
- cost_projection=cost_projection,
827
- oss_edition=OSS_EDITION,
828
- requires_enterprise=True,
829
- execution_allowed=False,
830
- status=IntentStatus.OSS_ADVISORY_ONLY,
831
- )
832
-
833
- __all__ = [
834
- "HealingIntent",
835
- "ConfidenceDistribution",
836
- "HealingIntentSerializer",
837
- "IntentSource",
838
- "IntentStatus",
839
- "RecommendedAction",
840
- "HealingIntentError",
841
- "SerializationError",
842
- "ValidationError",
843
- "create_infrastructure_healing_intent",
844
- "create_rollback_intent",
845
- "create_restart_intent",
846
- "create_scale_out_intent",
847
- "create_oss_advisory_intent",
848
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/intents.py DELETED
@@ -1,168 +0,0 @@
1
- # agentic_reliability_framework/infrastructure/intents.py
2
- """
3
- Infrastructure Intent Schema – Algebraic Data Types for Change Requests.
4
-
5
- This module defines a family of intents as a discriminated union. Each intent
6
- represents a proposed infrastructure action. Intents are immutable, self-validating,
7
- and carry provenance for auditability.
8
-
9
- The design follows principles of domain-driven design and knowledge engineering,
10
- using strong typing and semantic constraints to prevent invalid states.
11
- """
12
-
13
- from __future__ import annotations
14
-
15
- import uuid
16
- from datetime import datetime
17
- from enum import Enum
18
- from typing import Annotated, Any, Dict, Literal, Optional, Union
19
-
20
- from pydantic import BaseModel, Field, field_validator
21
- from pydantic.functional_validators import AfterValidator
22
-
23
- # -----------------------------------------------------------------------------
24
- # Domain Primitives (NewTypes for type safety)
25
- # -----------------------------------------------------------------------------
26
- # These are simple wrappers that enforce type checks at runtime only if validators are added.
27
- # Here we use them as markers; actual validation occurs in field validators.
28
- Region = str
29
- Size = str
30
- Principal = str
31
- ResourceScope = str
32
- ServiceName = str
33
- ChangeScope = Literal["single_instance", "canary", "global"]
34
- Environment = Literal["dev", "staging", "prod", "test"]
35
-
36
- # -----------------------------------------------------------------------------
37
- # Enums for fixed sets (but extensible via new variants)
38
- # -----------------------------------------------------------------------------
39
- class ResourceType(str, Enum):
40
- """Azure resource types with semantic meaning."""
41
- VM = "vm"
42
- STORAGE_ACCOUNT = "storage_account"
43
- DATABASE = "database"
44
- KUBERNETES_CLUSTER = "kubernetes_cluster"
45
- FUNCTION_APP = "function_app"
46
- VIRTUAL_NETWORK = "virtual_network"
47
-
48
- # We could add methods here to return associated pricing categories, etc.
49
-
50
- class PermissionLevel(str, Enum):
51
- """Access permission levels in increasing order of privilege."""
52
- READ = "read"
53
- WRITE = "write"
54
- ADMIN = "admin"
55
-
56
- # -----------------------------------------------------------------------------
57
- # Knowledge Base Stubs (simulated – in production would be loaded from external source)
58
- # -----------------------------------------------------------------------------
59
- # These are used for semantic validation. In a real system, they would be fetched
60
- # from Azure APIs or a configuration service.
61
- VALID_AZURE_REGIONS = {
62
- "eastus", "eastus2", "westus", "westeurope", "northeurope",
63
- "southeastasia", "eastasia", "japaneast", "brazilsouth"
64
- }
65
-
66
- # Mapping of resource type to plausible size patterns (simplified)
67
- RESOURCE_SIZE_PATTERNS = {
68
- ResourceType.VM: {"Standard_D2s_v3", "Standard_D4s_v3", "Standard_D8s_v3", "Standard_D16s_v3"},
69
- ResourceType.STORAGE_ACCOUNT: {"50GB", "100GB", "1TB", "10TB"},
70
- ResourceType.DATABASE: {"Basic", "Standard", "Premium"},
71
- ResourceType.KUBERNETES_CLUSTER: {"Small", "Medium", "Large"},
72
- ResourceType.FUNCTION_APP: {"Consumption", "Premium"},
73
- ResourceType.VIRTUAL_NETWORK: {"default"},
74
- }
75
-
76
- # -----------------------------------------------------------------------------
77
- # Base Intent Class
78
- # -----------------------------------------------------------------------------
79
- class Intent(BaseModel):
80
- """Abstract base for all intents, providing common fields."""
81
- intent_id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="Unique identifier for this intent")
82
- timestamp: datetime = Field(default_factory=datetime.utcnow, description="Time the intent was created")
83
- requester: Principal = Field(..., description="User or service principal requesting the action")
84
- provenance: Dict[str, Any] = Field(
85
- default_factory=dict,
86
- description="Metadata about how the intent was generated (e.g., agent ID, session)"
87
- )
88
-
89
- class Config:
90
- frozen = True # immutable after creation
91
- extra = "forbid" # no extra fields
92
-
93
- # -----------------------------------------------------------------------------
94
- # Specific Intent Types
95
- # -----------------------------------------------------------------------------
96
- class ProvisionResourceIntent(Intent):
97
- """Request to provision a new Azure resource."""
98
- intent_type: Literal["provision_resource"] = "provision_resource"
99
- resource_type: ResourceType
100
- region: Region
101
- size: Size
102
- configuration: Dict[str, Any] = Field(default_factory=dict)
103
- environment: Environment
104
-
105
- @field_validator("region")
106
- def validate_region(cls, v: Region) -> Region:
107
- if v not in VALID_AZURE_REGIONS:
108
- raise ValueError(f"Unknown Azure region: {v}")
109
- return v
110
-
111
- @field_validator("size")
112
- def validate_size(cls, v: Size, info) -> Size:
113
- # info.data contains previously validated fields
114
- resource_type = info.data.get("resource_type")
115
- if resource_type and resource_type in RESOURCE_SIZE_PATTERNS:
116
- if v not in RESOURCE_SIZE_PATTERNS[resource_type]:
117
- raise ValueError(f"Invalid size '{v}' for resource type {resource_type}")
118
- return v
119
-
120
- class DeployConfigurationIntent(Intent):
121
- """Request to change configuration of an existing service."""
122
- intent_type: Literal["deploy_config"] = "deploy_config"
123
- service_name: ServiceName
124
- change_scope: ChangeScope
125
- deployment_target: Environment
126
- risk_level_hint: Optional[Annotated[float, Field(ge=0, le=1)]] = None
127
- configuration: Dict[str, Any] = Field(default_factory=dict)
128
-
129
- # Optional: validate that service_name follows naming conventions
130
- @field_validator("service_name")
131
- def validate_service_name(cls, v: ServiceName) -> ServiceName:
132
- if not v or len(v) < 3:
133
- raise ValueError("Service name must be at least 3 characters")
134
- return v
135
-
136
- class GrantAccessIntent(Intent):
137
- """Request to grant a permission to a principal."""
138
- intent_type: Literal["grant_access"] = "grant_access"
139
- principal: Principal
140
- permission_level: PermissionLevel
141
- resource_scope: ResourceScope
142
- justification: Optional[str] = None
143
-
144
- # Validate resource_scope format (simplified)
145
- @field_validator("resource_scope")
146
- def validate_resource_scope(cls, v: ResourceScope) -> ResourceScope:
147
- if not v.startswith("/"):
148
- raise ValueError("Resource scope must start with '/'")
149
- return v
150
-
151
- # -----------------------------------------------------------------------------
152
- # Discriminated Union of All Intents
153
- # -----------------------------------------------------------------------------
154
- InfrastructureIntent = Annotated[
155
- Union[ProvisionResourceIntent, DeployConfigurationIntent, GrantAccessIntent],
156
- Field(discriminator="intent_type")
157
- ]
158
-
159
- __all__ = [
160
- "ResourceType",
161
- "PermissionLevel",
162
- "Environment",
163
- "ChangeScope",
164
- "ProvisionResourceIntent",
165
- "DeployConfigurationIntent",
166
- "GrantAccessIntent",
167
- "InfrastructureIntent",
168
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/policies.py DELETED
@@ -1,171 +0,0 @@
1
- """
2
- Policy Algebra – Composable, typed policies for infrastructure governance.
3
- """
4
-
5
- from __future__ import annotations
6
-
7
- from abc import ABC, abstractmethod
8
- from dataclasses import dataclass
9
- from typing import Any, Callable, Dict, List, Optional, Protocol, Set, TypeVar, Union
10
-
11
- from pydantic import BaseModel
12
-
13
- # Relative imports for intents
14
- from .intents import (
15
- InfrastructureIntent,
16
- ProvisionResourceIntent,
17
- GrantAccessIntent,
18
- ResourceType,
19
- PermissionLevel,
20
- Environment,
21
- )
22
-
23
- Violation = str
24
- EvalResult = List[Violation]
25
-
26
- class Policy(ABC):
27
- @abstractmethod
28
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
29
- pass
30
-
31
- def __and__(self, other: Policy) -> Policy:
32
- return AndPolicy(self, other)
33
-
34
- def __or__(self, other: Policy) -> Policy:
35
- return OrPolicy(self, other)
36
-
37
- def __invert__(self) -> Policy:
38
- return NotPolicy(self)
39
-
40
- class AtomicPolicy(Policy, ABC):
41
- pass
42
-
43
- @dataclass(frozen=True)
44
- class RegionAllowedPolicy(AtomicPolicy):
45
- allowed_regions: Set[str]
46
-
47
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
48
- if isinstance(intent, ProvisionResourceIntent):
49
- if intent.region not in self.allowed_regions:
50
- return [f"Region '{intent.region}' not allowed. Allowed: {self.allowed_regions}"]
51
- return []
52
-
53
- @dataclass(frozen=True)
54
- class ResourceTypeRestrictedPolicy(AtomicPolicy):
55
- forbidden_types: Set[ResourceType]
56
-
57
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
58
- if isinstance(intent, ProvisionResourceIntent):
59
- if intent.resource_type in self.forbidden_types:
60
- return [f"Resource type '{intent.resource_type.value}' is forbidden."]
61
- return []
62
-
63
- @dataclass(frozen=True)
64
- class MaxPermissionLevelPolicy(AtomicPolicy):
65
- max_level: PermissionLevel
66
-
67
- _LEVEL_ORDER = {
68
- PermissionLevel.READ: 1,
69
- PermissionLevel.WRITE: 2,
70
- PermissionLevel.ADMIN: 3,
71
- }
72
-
73
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
74
- if isinstance(intent, GrantAccessIntent):
75
- if self._LEVEL_ORDER[intent.permission_level] > self._LEVEL_ORDER[self.max_level]:
76
- return [f"Permission level '{intent.permission_level.value}' exceeds max allowed '{self.max_level.value}'."]
77
- return []
78
-
79
- @dataclass(frozen=True)
80
- class CostThresholdPolicy(AtomicPolicy):
81
- max_cost_usd: float
82
-
83
- def evaluate(self, intent: InfrastructureIntent, cost: Optional[float] = None) -> EvalResult:
84
- return []
85
-
86
- @dataclass(frozen=True)
87
- class AndPolicy(Policy):
88
- left: Policy
89
- right: Policy
90
-
91
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
92
- return self.left.evaluate(intent) + self.right.evaluate(intent)
93
-
94
- @dataclass(frozen=True)
95
- class OrPolicy(Policy):
96
- left: Policy
97
- right: Policy
98
-
99
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
100
- left_violations = self.left.evaluate(intent)
101
- right_violations = self.right.evaluate(intent)
102
- if not left_violations or not right_violations:
103
- return []
104
- return left_violations + right_violations
105
-
106
- @dataclass(frozen=True)
107
- class NotPolicy(Policy):
108
- inner: Policy
109
-
110
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
111
- inner_violations = self.inner.evaluate(intent)
112
- if inner_violations:
113
- return []
114
- else:
115
- return ["Condition not met (NOT policy)"]
116
-
117
- class PolicyEvaluator:
118
- def __init__(self, root_policy: Policy):
119
- self._root = root_policy
120
-
121
- def evaluate(self, intent: InfrastructureIntent, context: Optional[Dict[str, Any]] = None) -> EvalResult:
122
- return self._evaluate_recursive(self._root, intent, context or {})
123
-
124
- def _evaluate_recursive(self, policy: Policy, intent: InfrastructureIntent, context: Dict[str, Any]) -> EvalResult:
125
- if isinstance(policy, CostThresholdPolicy):
126
- cost = context.get('cost_estimate')
127
- if cost is not None and cost > policy.max_cost_usd:
128
- return [f"Cost ${cost:.2f} exceeds threshold ${policy.max_cost_usd:.2f}"]
129
- return []
130
- if isinstance(policy, AtomicPolicy):
131
- return policy.evaluate(intent)
132
- if isinstance(policy, AndPolicy):
133
- return self._evaluate_recursive(policy.left, intent, context) + self._evaluate_recursive(policy.right, intent, context)
134
- if isinstance(policy, OrPolicy):
135
- left = self._evaluate_recursive(policy.left, intent, context)
136
- right = self._evaluate_recursive(policy.right, intent, context)
137
- if not left or not right:
138
- return []
139
- return left + right
140
- if isinstance(policy, NotPolicy):
141
- inner = self._evaluate_recursive(policy.inner, intent, context)
142
- if inner:
143
- return []
144
- return ["Condition not met (NOT policy)"]
145
- return []
146
-
147
- def allow_all() -> Policy:
148
- class _AllowAll(AtomicPolicy):
149
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
150
- return []
151
- return _AllowAll()
152
-
153
- def deny_all() -> Policy:
154
- class _DenyAll(AtomicPolicy):
155
- def evaluate(self, intent: InfrastructureIntent) -> EvalResult:
156
- return ["Action denied by default policy"]
157
- return _DenyAll()
158
-
159
- __all__ = [
160
- "Policy",
161
- "RegionAllowedPolicy",
162
- "ResourceTypeRestrictedPolicy",
163
- "MaxPermissionLevelPolicy",
164
- "CostThresholdPolicy",
165
- "AndPolicy",
166
- "OrPolicy",
167
- "NotPolicy",
168
- "PolicyEvaluator",
169
- "allow_all",
170
- "deny_all",
171
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
infrastructure/risk_engine.py DELETED
@@ -1,105 +0,0 @@
1
- """
2
- Risk Scoring Engine – Multi-factor probabilistic risk model.
3
- """
4
-
5
- from typing import Dict, List, Optional, Tuple, Any, Callable
6
- from dataclasses import dataclass, field
7
-
8
- from .intents import (
9
- InfrastructureIntent,
10
- ProvisionResourceIntent,
11
- GrantAccessIntent,
12
- DeployConfigurationIntent,
13
- PermissionLevel,
14
- Environment,
15
- )
16
-
17
- @dataclass(frozen=True)
18
- class RiskFactor:
19
- name: str
20
- weight: float
21
- score_fn: Callable[[InfrastructureIntent, Optional[float], List[str]], float]
22
- description: str = ""
23
-
24
- def __call__(self, intent: InfrastructureIntent, cost: Optional[float], violations: List[str]) -> float:
25
- return self.score_fn(intent, cost, violations)
26
-
27
- def intent_type_factor(intent: InfrastructureIntent, cost: Optional[float], violations: List[str]) -> float:
28
- mapping = {
29
- "provision_resource": 0.1,
30
- "grant_access": 0.3,
31
- "deploy_config": 0.2,
32
- }
33
- return mapping.get(intent.intent_type, 0.1)
34
-
35
- def cost_factor(intent: InfrastructureIntent, cost: Optional[float], violations: List[str]) -> float:
36
- if not isinstance(intent, ProvisionResourceIntent) or cost is None:
37
- return 0.0
38
- return min(cost / 5000.0, 1.0)
39
-
40
- def permission_factor(intent: InfrastructureIntent, cost: Optional[float], violations: List[str]) -> float:
41
- if not isinstance(intent, GrantAccessIntent):
42
- return 0.0
43
- mapping = {
44
- PermissionLevel.READ: 0.1,
45
- PermissionLevel.WRITE: 0.4,
46
- PermissionLevel.ADMIN: 0.8,
47
- }
48
- return mapping.get(intent.permission_level, 0.5)
49
-
50
- def scope_factor(intent: InfrastructureIntent, cost: Optional[float], violations: List[str]) -> float:
51
- if not isinstance(intent, DeployConfigurationIntent):
52
- return 0.0
53
- mapping = {
54
- "single_instance": 0.1,
55
- "canary": 0.2,
56
- "global": 0.6,
57
- }
58
- return mapping.get(intent.change_scope, 0.3)
59
-
60
- def environment_factor(intent: InfrastructureIntent, cost: Optional[float], violations: List[str]) -> float:
61
- if hasattr(intent, "environment") and intent.environment == Environment.PROD:
62
- return 0.1
63
- return 0.0
64
-
65
- def policy_violation_factor(intent: InfrastructureIntent, cost: Optional[float], violations: List[str]) -> float:
66
- return min(len(violations) * 0.2, 0.8)
67
-
68
- class RiskEngine:
69
- DEFAULT_FACTORS = [
70
- RiskFactor("intent_type", 1.0, intent_type_factor, "Base risk from intent type"),
71
- RiskFactor("cost", 0.3, cost_factor, "Normalized cost estimate"),
72
- RiskFactor("permission", 0.3, permission_factor, "Permission level being granted"),
73
- RiskFactor("scope", 0.2, scope_factor, "Deployment scope"),
74
- RiskFactor("environment", 0.1, environment_factor, "Production environment"),
75
- RiskFactor("policy_violations", 0.2, policy_violation_factor, "Number of policy violations"),
76
- ]
77
-
78
- def __init__(self, factors: Optional[List[RiskFactor]] = None):
79
- self.factors = factors if factors is not None else self.DEFAULT_FACTORS
80
-
81
- def calculate_risk(
82
- self,
83
- intent: InfrastructureIntent,
84
- cost_estimate: Optional[float],
85
- policy_violations: List[str],
86
- ) -> Tuple[float, str, Dict[str, float]]:
87
- total = 0.0
88
- contributions = {}
89
-
90
- for factor in self.factors:
91
- raw_score = factor(intent, cost_estimate, policy_violations)
92
- weighted = raw_score * factor.weight
93
- contributions[factor.name] = weighted
94
- total += weighted
95
-
96
- total = max(0.0, min(total, 1.0))
97
-
98
- lines = [f"Total risk score: {total:.2f}"]
99
- for factor in self.factors:
100
- contrib = contributions[factor.name]
101
- if contrib > 0.0:
102
- lines.append(f" - {factor.name}: {contrib:.2f} ({factor.description})")
103
- explanation = "\n".join(lines)
104
-
105
- return total, explanation, contributions