petter2025 commited on
Commit
1ca269b
·
verified ·
1 Parent(s): 8299ce4

Upload folder using huggingface_hub

Browse files
app/api/routes_governance.py CHANGED
@@ -307,7 +307,7 @@ async def evaluate_intent_endpoint(
307
 
308
  record = UsageRecord(
309
  api_key=api_key,
310
- tier=None,
311
  timestamp=start_time,
312
  endpoint="/api/v1/intents/evaluate",
313
  request_body=intent_req.model_dump(),
@@ -661,7 +661,7 @@ async def evaluate_healing_decision_endpoint(
661
 
662
  record = UsageRecord(
663
  api_key=api_key,
664
- tier=None,
665
  timestamp=start_time,
666
  endpoint="/api/v1/healing/evaluate",
667
  request_body=decision_req.model_dump(),
 
307
 
308
  record = UsageRecord(
309
  api_key=api_key,
310
+ tier=quota["tier"],
311
  timestamp=start_time,
312
  endpoint="/api/v1/intents/evaluate",
313
  request_body=intent_req.model_dump(),
 
661
 
662
  record = UsageRecord(
663
  api_key=api_key,
664
+ tier=quota["tier"],
665
  timestamp=start_time,
666
  endpoint="/api/v1/healing/evaluate",
667
  request_body=decision_req.model_dump(),
tests/test_governance.py CHANGED
@@ -1,7 +1,11 @@
1
  """
2
  Tests for governance endpoints: /api/v1/intents/evaluate
3
  """
 
 
4
  import pytest
 
 
5
  from app.database.models_intents import TenantDB
6
 
7
 
@@ -113,3 +117,36 @@ def test_evaluate_with_criticality(client):
113
  # context_hash is computed by the governance loop (a 64‑char hex string)
114
  ctx_hash = healing.get("context_hash")
115
  assert isinstance(ctx_hash, str) and len(ctx_hash) == 64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  """
2
  Tests for governance endpoints: /api/v1/intents/evaluate
3
  """
4
+ import tempfile
5
+
6
  import pytest
7
+ import app.core.usage_tracker as usage_tracker_module
8
+ from app.core.usage_tracker import UsageTracker
9
  from app.database.models_intents import TenantDB
10
 
11
 
 
117
  # context_hash is computed by the governance loop (a 64‑char hex string)
118
  ctx_hash = healing.get("context_hash")
119
  assert isinstance(ctx_hash, str) and len(ctx_hash) == 64
120
+
121
+
122
+ def test_evaluate_intent_against_real_tracker_does_not_crash(client, monkeypatch):
123
+ """Every other test in this file runs against tests/conftest.py's
124
+ MockTracker, whose consume_quota_and_log ignores record.tier entirely
125
+ and always returns (True, None) -- so none of them would have noticed
126
+ that this endpoint hardcoded tier=None instead of using quota["tier"]
127
+ (already resolved by the enforce_quota dependency). Against the real
128
+ UsageTracker, consume_quota_and_log evaluates tier.monthly_evaluation_limit
129
+ unconditionally, so a None tier raised AttributeError on every real
130
+ call, outside any try/except, surfacing as a raw 500. This test swaps
131
+ in a real UsageTracker (a throwaway SQLite file; the same real
132
+ Postgres the CI service provides backs api_keys/monthly_counts) to
133
+ prove the endpoint no longer crashes."""
134
+ with tempfile.NamedTemporaryFile(suffix=".db") as tmp:
135
+ monkeypatch.setattr(usage_tracker_module, "tracker", UsageTracker(db_path=tmp.name))
136
+
137
+ payload = {
138
+ "intent_type": "provision_resource",
139
+ "environment": "prod",
140
+ "resource_type": "database",
141
+ "region": "eastus",
142
+ "size": "Standard",
143
+ "estimated_cost": 1200,
144
+ "policy_violations": [],
145
+ "requester": "alice",
146
+ "provenance": {},
147
+ "configuration": {}
148
+ }
149
+ response = client.post("/api/v1/intents/evaluate", json=payload,
150
+ headers={"X-Tenant-ID": "test-tenant"})
151
+ assert response.status_code == 200, response.text
152
+ assert "risk_score" in response.json()
tests/test_healing_endpoint.py CHANGED
@@ -1,5 +1,9 @@
 
 
1
  from fastapi.testclient import TestClient
2
  from app.main import app
 
 
3
 
4
  client = TestClient(app)
5
 
@@ -18,3 +22,27 @@ def test_healing_evaluate_endpoint():
18
  response = client.post("/api/v1/healing/evaluate", json=payload,
19
  headers={"X-Tenant-ID": "test-tenant"})
20
  assert response.status_code == 200, f"Expected 200, got {response.status_code}: {response.text}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+
3
  from fastapi.testclient import TestClient
4
  from app.main import app
5
+ import app.core.usage_tracker as usage_tracker_module
6
+ from app.core.usage_tracker import UsageTracker
7
 
8
  client = TestClient(app)
9
 
 
22
  response = client.post("/api/v1/healing/evaluate", json=payload,
23
  headers={"X-Tenant-ID": "test-tenant"})
24
  assert response.status_code == 200, f"Expected 200, got {response.status_code}: {response.text}"
25
+
26
+
27
+ def test_healing_evaluate_against_real_tracker_does_not_crash(monkeypatch):
28
+ """Same regression as test_governance.py's equivalent test, for this
29
+ endpoint's own hardcoded tier=None (routes_governance.py's
30
+ /healing/evaluate handler) -- see that test's docstring for the full
31
+ explanation. Swaps in a real UsageTracker to prove
32
+ consume_quota_and_log no longer crashes on a None tier here either."""
33
+ payload = {
34
+ "event": {
35
+ "component": "my-service",
36
+ "latency_p99": 450.0,
37
+ "error_rate": 0.25,
38
+ "service_mesh": "default",
39
+ "cpu_util": 0.85,
40
+ "memory_util": 0.90
41
+ }
42
+ }
43
+ with tempfile.NamedTemporaryFile(suffix=".db") as tmp:
44
+ monkeypatch.setattr(usage_tracker_module, "tracker", UsageTracker(db_path=tmp.name))
45
+
46
+ response = client.post("/api/v1/healing/evaluate", json=payload,
47
+ headers={"X-Tenant-ID": "test-tenant"})
48
+ assert response.status_code == 200, f"Expected 200, got {response.status_code}: {response.text}"