feat(agent-call): implement remediation plan

This commit is contained in:
2026-09-13 19:20:28 +08:00
parent d30314c7d1
commit b95d2aee81
25 changed files with 3159 additions and 535 deletions
+38 -6
View File
@@ -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"])