fix: accept the spec's in-band error model for business-level failures#59
fix: accept the spec's in-band error model for business-level failures#59vishkaty wants to merge 3 commits into
Conversation
Fixes the posture mismatch reported in Universal-Commerce-Protocol#55: test_out_of_stock, test_product_not_found, and test_structured_error_messages hard-asserted an HTTP 400, but the spec models business failures in-band — checkout-rest.md's own "Error Response" example answers an all-items-out-of-stock create with HTTP 200, ucp.status "error", and a typed messages[] entry. A merchant implementing the spec's documented posture failed these tests. A shared assert_business_error helper now accepts either posture, each validated strictly: - 4xx keeps the exact assertions the tests always made against the Flower Shop reference (which uses this posture), so reference coverage is unchanged. - 2xx requires messages[] to carry at least one type="error" entry with the full message envelope (type, code, content, severity — required by message_error.json), at least one entry using a standardized code for the scenario (checkout.md error-code table / error_code.json examples), and a ucp.status="error" response to carry no checkout resource (checkout.md: "no resource is included in the response body"). Validated: full 13-file suite results identical before and after against the Flower Shop (main, pip ucp-sdk); a minimal mock implementing the spec's canonical in-band example passes all three tests; injected defects each fail precisely (missing messages[], missing severity, non-standard code, and a resource on a status=error response).
Ensure that ucp.status is strictly 'error' and no resource ID is returned when a business-level failure is answered with a 2xx status code. This prevents false positives where a server might incorrectly create a resource but still return error messages.
|
Hi @vishkaty, thanks for adding support for the 2xx in-band error posture! Overall the changes look great, but it looks like test_update_inventory_validation in validation_test.py was missed. It currently still asserts self.assert_response_status(response, 400), which fails against servers returning a 2xx in-band error on checkout update requests (PUT /checkout-sessions/{id}). Could you update test_update_inventory_validation to also use assert_business_error. Thank you. |
Converts the update-path twin the review caught: same dual-posture assertion as the create-path tests, plus two strictness fixes to the shared helper that surfaced while validating against an in-band mock: - a resource-bearing in-band answer must not claim ucp.status 'error' (checkout.md: an error-status response includes no resource) and must report a valid non-'completed' checkout status; - the update test also accepts the spec's canonical clamp-and-warn answer (checkout-rest.md Business Outcomes: 200 + quantity clamped + a 'quantity_adjusted' warning), requiring the quantity to actually be clamped so silent over-acceptance still fails.
|
Thank you — you were right, and it's converted in 421008d: Rather than fixing just the named site, I re-swept the file for the class. Accounting:
While validating the conversion against an in-band mock, two strictness gaps in the new helper surfaced; fixed in the same commit:
Validation: full One observation for a possible follow-up rather than this PR: |
Fixes #55 (reported by @kbrackney):
test_out_of_stock,test_product_not_found, andtest_structured_error_messageshard-assert an HTTP 400, but the spec models business-level failures in-band — checkout-rest.md's own "Error Response" example answers an all-items-out-of-stock create withHTTP/1.1 200 OK,ucp.status: "error", and a typedmessages[]entry (verified against currentucpmain). A merchant implementing the spec's documented posture fails these tests today.Follows the same pattern as #57 (accept both protocol-compatible outcomes), with each posture validated strictly rather than loosened:
messages[]to carry at least onetype: "error"entry with the full message envelope (type,code,content,severity— all required bymessage_error.json), at least one entry using a standardized code for the scenario (checkout.md error-code table /error_code.jsonexamples), and aucp.status: "error"response to carry no checkout resource (checkout.md: "no resource is included in the response body").Validation
main, pipucp-sdk): results identical before and after the change.messages[], an error entry missingseverity, a non-standard code, and a resource present on astatus: "error"response.ruff check+ruff format --checkclean.