feat(agent-call): implement remediation plan
This commit is contained in:
+38
-6
@@ -42,6 +42,10 @@ class HttpContractTests(unittest.TestCase):
|
||||
"recording.complete",
|
||||
],
|
||||
},
|
||||
"replay": {
|
||||
"tenant_ids": ["tenant-demo"],
|
||||
"scopes": ["outbound.read", "outbound.replay"],
|
||||
},
|
||||
}
|
||||
)
|
||||
self.service = AgentCallService(
|
||||
@@ -73,14 +77,18 @@ class HttpContractTests(unittest.TestCase):
|
||||
path: str,
|
||||
body: dict[str, Any] | None = None,
|
||||
tenant: str | None = "tenant-demo",
|
||||
token: str | None = "local",
|
||||
auth_name: str | None = None,
|
||||
idem: str | None = None,
|
||||
include_auth: bool = True,
|
||||
) -> tuple[int, dict[str, Any]]:
|
||||
headers = {"X-Request-ID": "http-test"}
|
||||
if tenant is not None:
|
||||
headers["X-Tenant-ID"] = tenant
|
||||
if token is not None:
|
||||
headers["Authorization"] = f"Bearer {token}"
|
||||
if include_auth and auth_name is None:
|
||||
token_map = json.loads(os.environ["HTTP_TOKENS"])
|
||||
auth_name = next(iter(token_map), None)
|
||||
if include_auth and auth_name is not None:
|
||||
headers["Authorization"] = f"Bearer {auth_name}"
|
||||
encoded: bytes | None = None
|
||||
if body is not None:
|
||||
encoded = json.dumps(body, ensure_ascii=False).encode("utf-8")
|
||||
@@ -104,7 +112,7 @@ class HttpContractTests(unittest.TestCase):
|
||||
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
||||
raise AssertionError("HTTP response is not JSON") from exc
|
||||
if not isinstance(parsed, dict):
|
||||
raise AssertionError("HTTP response is not an object")
|
||||
raise TypeError("HTTP response is not an object")
|
||||
return status, parsed
|
||||
|
||||
def publish_success(self) -> dict[str, Any]:
|
||||
@@ -118,11 +126,13 @@ class HttpContractTests(unittest.TestCase):
|
||||
return self.service.get_command("tenant-demo", "http_cmd")
|
||||
|
||||
def test_health_is_public_but_business_queries_are_authenticated(self) -> None:
|
||||
status, body = self.request("GET", "/healthz/live", tenant=None, token=None)
|
||||
status, body = self.request(
|
||||
"GET", "/healthz/live", tenant=None, include_auth=False
|
||||
)
|
||||
self.assertEqual(status, 200)
|
||||
self.assertEqual(body["status"], "live")
|
||||
status, body = self.request(
|
||||
"GET", "/internal/v1/outbound/commands/missing", token=None
|
||||
"GET", "/internal/v1/outbound/commands/missing", include_auth=False
|
||||
)
|
||||
self.assertEqual(status, 401)
|
||||
self.assertEqual(body["code"], "UNAUTHORIZED")
|
||||
@@ -160,6 +170,28 @@ class HttpContractTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(status, 403)
|
||||
|
||||
def test_replay_requires_replay_scope(self) -> None:
|
||||
snapshot = self.publish_success()
|
||||
body = {"command_id": "http_replay", "reason": "retry"}
|
||||
status, response = self.request(
|
||||
"POST",
|
||||
f"/internal/v1/outbound/commands/{snapshot['command_id']}/replays",
|
||||
body,
|
||||
auth_name="local",
|
||||
idem="http_replay",
|
||||
)
|
||||
self.assertEqual(status, 403)
|
||||
self.assertEqual(response["code"], "FORBIDDEN")
|
||||
status, response = self.request(
|
||||
"POST",
|
||||
f"/internal/v1/outbound/commands/{snapshot['command_id']}/replays",
|
||||
body,
|
||||
auth_name="replay",
|
||||
idem="http_replay",
|
||||
)
|
||||
self.assertEqual(status, 202)
|
||||
self.assertEqual(response["status"], "accepted")
|
||||
|
||||
def test_recording_upload_contract_is_scoped(self) -> None:
|
||||
snapshot = self.publish_success()
|
||||
call = self.service.get_call("tenant-demo", snapshot["call_id"])
|
||||
|
||||
Reference in New Issue
Block a user