Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion rest/python/server/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ async def validate_ucp_headers(ucp_agent: str):

if agent_version > server_version:
raise HTTPException(
status_code=400,
# version_unsupported maps to REST 422 in the overview.md error registry.
status_code=422,
detail={
"status": "error",
"errors": [
Expand Down
23 changes: 23 additions & 0 deletions rest/python/server/integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,29 @@ def test_missing_ucp_agent_header(self) -> None:
# default validation)
self.assertEqual(response.status_code, 422)

def test_unsupported_version_returns_422(self) -> None:
"""A future protocol version is rejected with 422 version_unsupported.

The error registry in overview.md maps `version_unsupported` to REST 422.
"""
with self.client:
payload = self._create_checkout_payload(
"test_checkout_bad_version", [("rose", "Red Rose", 1000, 1)]
)
headers = self._get_headers(idempotency_key="ver", request_id="ver")
headers["UCP-Agent"] = (
'profile="https://agent.example/profile"; version="2999-01-01"'
)
response = self.client.post(
"/checkout-sessions",
headers=headers,
json=payload.model_dump(mode="json", exclude_none=True),
)
self.assertEqual(response.status_code, 422, f"Response: {response.text}")
# It is the structured negotiation error, not a generic validation 422.
error = response.json()["detail"]["errors"][0]
self.assertEqual(error["severity"], "critical")

def test_discount_code_matches_case_insensitively(self) -> None:
"""Codes are matched case-insensitively by business (discount.md)."""

Expand Down
Loading