Skip to content

fix(rest/python): stop copying client supplied omit members, safely handle attribution, and return UCP error envelope on validation failures - #196

Open
damaz91 wants to merge 3 commits into
Universal-Commerce-Protocol:mainfrom
damaz91:fix/python-checkout-omit-fields
Open

fix(rest/python): stop copying client supplied omit members, safely handle attribution, and return UCP error envelope on validation failures#196
damaz91 wants to merge 3 commits into
Universal-Commerce-Protocol:mainfrom
damaz91:fix/python-checkout-omit-fields

Conversation

@damaz91

@damaz91 damaz91 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Description

The create handlers in both checkout_service and cart_service build response models by unpacking request data via **checkout_data and **cart_data.

  1. Omit Field Leakage & Keyword Collisions:
  2. Currency Determination:
  3. Line Item ID Server Assignment:
  4. Attribution model_dump AttributeError:
  5. Request Validation Error Envelope:

This change:

  • Excludes all ucp_request: omit and server-managed fields from create_checkout and create_cart.
  • Ensures currency is determined authoritatively via config.get_default_currency() across both checkout and cart create paths.
  • Ensures line item IDs on direct create are server-assigned UUIDs, ignoring client-supplied IDs.
  • Safely dumps attribution, buyer, context, signals, and discounts via hasattr(obj, "model_dump") check.
  • Registers a RequestValidationError handler in server.py returning the standard UCP error envelope on HTTP 422.
  • Adds regression unit tests across integration_test.py and cart_test.py covering omit member dropping, currency overriding, line item ID handling, attribution support, and validation error envelopes.

Category (Required)

  • Core Protocol: Changes to the base communication layer, global context, or breaking refactors. (Requires Technical Council approval)
  • Governance/Contributing: Updates to GOVERNANCE.md, CONTRIBUTING.md, or CODEOWNERS. (Requires Governance Council approval)
  • Capability: New schemas (Discovery, Cart, etc.) or extensions. (Requires Maintainer approval)
  • Documentation: Updates to README, or documentations regarding schema or capabilities. (Requires Maintainer approval)
  • Infrastructure: CI/CD, Linters, or build scripts. (Requires DevOps Maintainer approval)
  • Maintenance: Version bumps, lockfile updates, or minor bug fixes. (Requires DevOps Maintainer approval)
  • SDK: Language-specific SDK updates and releases. (Requires DevOps Maintainer approval)
  • Samples / Conformance: Maintaining samples and the conformance suite. (Requires Maintainer approval)
  • UCP Schema: Changes to the ucp-schema tool (resolver, linter, validator). (Requires Maintainer approval)
  • Community Health (.github): Updates to templates, workflows, or org-level configs. (Requires DevOps Maintainer approval)

Related Issues

Closes #188
Closes #189
Closes #190
Closes #191
Closes #195

Checklist

  • I have followed the Contributing Guide (including Conventional Commits title requirements and ! for breaking changes).
  • I have updated the documentation (if applicable).
  • My changes pass all local linting and formatting checks.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • (For Core/Capability) I have included/updated the relevant JSON schemas.
  • I have regenerated Python Pydantic models by running generate_models.sh under python_sdk.

@damaz91
damaz91 force-pushed the fix/python-checkout-omit-fields branch 2 times, most recently from 2854e83 to 6e46b55 Compare August 20, 2026 08:36
@damaz91 damaz91 changed the title fix(rest/python): stop copying client supplied omit members into the checkout response fix(rest/python): stop copying client supplied omit members into checkout and cart responses Aug 20, 2026
@damaz91
damaz91 force-pushed the fix/python-checkout-omit-fields branch from 6e46b55 to c508735 Compare August 20, 2026 08:43
@damaz91 damaz91 changed the title fix(rest/python): stop copying client supplied omit members into checkout and cart responses fix(rest/python): stop copying client supplied omit members and safely handle attribution Aug 20, 2026
…andle attribution, and return UCP error envelope on validation failures

1. Omit Field Leakage & Keyword Collisions:
   - In checkout create: continue_url, expires_at, messages, and order were not excluded from checkout_data, allowing client values to echo in the 201 response and persist to the session database (Universal-Commerce-Protocol#190).
   - In cart create: continue_url, expires_at, messages, and links were not excluded from cart_data, allowing client values to echo in the response. Furthermore, passing explicit keyword arguments caused 500 TypeError when these fields were supplied in the request (Universal-Commerce-Protocol#188).
2. Currency Determination:
   - checkout_service was reading currency from the request via getattr(checkout_req, 'currency', None), allowing clients to override merchant currency (e.g. 'currency': 'XTS') and crashing on non-string inputs (e.g. 'currency': 123) (Universal-Commerce-Protocol#189).
   - cart_service was hardcoding 'USD' rather than using config.get_default_currency().
3. Line Item ID Server Assignment:
   - checkout_service on direct requests was reading getattr(li, 'id', None), adopting client-supplied line item IDs and crashing on non-string IDs (123) (Universal-Commerce-Protocol#189).
4. Attribution model_dump AttributeError:
   - AttributionCreateRequest is a type alias (dict) in ucp-sdk, so calling source_attribution.model_dump() crashed with AttributeError on direct checkout create and cart-to-checkout conversion (Universal-Commerce-Protocol#191).
5. Request Validation Error Envelope:
   - RequestValidationError was unhandled, falling back to FastAPI's default flat {'detail': [...]} format instead of the compliant UCP error envelope carrying code, content, and severity (Universal-Commerce-Protocol#195).

This change:
- Excludes all ucp_request omit and server-managed fields from create_checkout and create_cart.
- Ensures currency is determined authoritatively via config.get_default_currency().
- Ensures line item IDs on direct create are server-assigned UUIDs.
- Safely dumps attribution, buyer, context, signals, and discounts via hasattr check.
- Registers a RequestValidationError handler in server.py returning the UCP error envelope.
- Adds regression unit tests across integration_test.py and cart_test.py.

Closes Universal-Commerce-Protocol#188, Universal-Commerce-Protocol#189, Universal-Commerce-Protocol#190, Universal-Commerce-Protocol#191, Universal-Commerce-Protocol#195
@damaz91
damaz91 force-pushed the fix/python-checkout-omit-fields branch from c508735 to b70aea0 Compare August 20, 2026 08:47
@damaz91 damaz91 changed the title fix(rest/python): stop copying client supplied omit members and safely handle attribution fix(rest/python): stop copying client supplied omit members, safely handle attribution, and return UCP error envelope on validation failures Aug 20, 2026
@damaz91 damaz91 added status:needs-triage Signal that the PR is ready for human triage status:under-review and removed status:needs-triage Signal that the PR is ready for human triage labels Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants