QWED-UCP
Deterministic Verification Middleware for Universal Commerce Protocol
Verify AI agent commerce before the money moves.
QWED-UCP sits between AI agents and payment processors — catching miscalculated totals,
invalid state transitions, and malformed checkouts before they hit production.
Quick Start · The Guards · Integration · Trust Status · 📖 Docs
🚨 The Problem
AI agents (Gemini, ChatGPT, Claude) now generate e-commerce checkouts directly — cart totals, tax, discounts, refunds, fees. These agents hallucinate on math:
| Scenario | LLM Output | Correct |
|---|---|---|
| 10% off $99.99 | "$10.00 discount" | $9.999 → $10.00 ✅ |
| 8.25% tax on $100 | "$8.00 tax" | $8.25 ❌ |
| $50 + $30 + $20 cart | "$110.00 total" | $100.00 ❌ |
| Discount applied after tax | Wrong order | Math error ❌ |
QWED-UCP blocks these errors before they reach a payment processor.
✅ What QWED-UCP Is (and Isn't)
QWED-UCP IS:
- Verification middleware that checks AI-generated UCP checkouts
- Deterministic — uses Decimal math (no floating-point errors) and state-machine logic
- Open source (Apache 2.0) — integrate into any e-commerce workflow
- A safety layer — catches calculation errors and invalid state transitions before payment
QWED-UCP is NOT:
A shopping cart— use Shopify, WooCommerce, or Stripe for thatA payment processor— use Stripe, Adyen, or Square for thatA fraud detection system— use Sift, Signifyd, or Riskified for thatA replacement for e-commerce platforms— we just verify the math
Think of QWED-UCP as the "accountant" that reviews every AI checkout before payment.
Shopify builds carts. Stripe processes payments. QWED verifies the math.
🆚 How QWED-UCP Differs from E-Commerce Platforms
| Aspect | Shopify / Stripe / Adyen | QWED-UCP |
|---|---|---|
| Purpose | Build carts, process payments | Verify calculations |
| Approach | Trust AI outputs | Deterministically verify AI outputs |
| Accuracy | ~99% (edge cases fail) | 100% deterministic |
| Tech | Standard floating-point | Decimal + JSON Schema |
| Integration | Replace your stack | Sits between AI and payment |
| Pricing | Transaction fees | Free (Apache 2.0) |
Use Together
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ AI Agent │ ──► │ QWED-UCP │ ──► │ Stripe │
│ (checkout) │ │ (verifies) │ │ (payment) │
└──────────────┘ └──────────────┘ └──────────────┘
🛡️ The Guards
QWED-UCP ships 10 verification guards. UCPVerifier.verify_checkout() runs
the 3 core guards as a fail-closed pipeline; the remaining 7 guards are
available as standalone classes for manual or middleware use.
Core Guards (run by verify_checkout())
| Guard | Engine | What It Verifies |
|---|---|---|
| Money Guard | Decimal | Cart totals against UCP formula: Total = Subtotal - Discount + Fulfillment + Tax + Fee |
| State Guard | Manual state logic | Checkout state machine (draft → ready → complete), rejects illegal transitions |
| Structure Guard | JSON Schema | UCP schema compliance (v1.0) |
Standalone Guards
| Guard | Engine | What It Verifies |
|---|---|---|
| Line Item Guard | Decimal | Item quantity × price = line total |
| Discount Guard | Decimal | Percentage and fixed discount calculations |
| Currency Guard | Decimal | Currency precision, $0.01 rounding, supported codes |
| Refund Guard | Decimal | Full/partial refund amounts, tax reversals |
| Tip Guard | Decimal | Pre/post-tax tip calculations, min/max bounds |
| Fee Guard | Decimal | Service fees, delivery fees, platform fees |
| Attestation Guard | JWT (PyJWT) | Context-bound attestation tokens with in-memory replay protection |
🚀 Quick Start
Installation
pip install qwed-ucp
Verify a Checkout
from qwed_ucp import UCPVerifier
verifier = UCPVerifier()
checkout = {
"currency": "USD",
"totals": [
{"type": "subtotal", "amount": 100.00},
{"type": "tax", "amount": 8.25},
{"type": "total", "amount": 108.25}
],
"status": "ready_for_complete"
}
result = verifier.verify_checkout(checkout)
if result.verified:
print("✅ Transaction verified — safe to process!")
else:
print(f"❌ Verification failed: {result.error}")
verify_checkout() is always a full fail-closed trust verdict: it returns
verified=True only when Money Guard, State Guard, and Structure Guard all pass.
Verify Totals Only
# Math-only check — does not verify state or schema
result = verifier.verify_totals_only(checkout)
⚠️ Do not treat
verify_totals_only()as a final transaction verdict. It only runs the Money Guard and does not check state or schema validity.
📊 Interpreting Results
Shared Fields (all results)
| Field | Type | Description |
|---|---|---|
verified |
bool |
Convenience flag — True only when status == TrustStatus.VERIFIED |
status |
TrustStatus |
Typed trust verdict — see Trust Status |
error |
Optional[str] |
Error message when verification fails |
Top-Level Only (UCPVerificationResult)
| Field | Type | Description |
|---|---|---|
engine |
str |
"QWED-Deterministic-v1" |
guards |
list[GuardResult] |
Individual guard outcomes |
verification_mode |
str |
"deterministic" |
Branching on status (preferred)
from qwed_ucp import UCPVerifier, TrustStatus
verifier = UCPVerifier()
result = verifier.verify_checkout(checkout)
if result.status == TrustStatus.VERIFIED:
proceed_to_payment(checkout)
elif result.status == TrustStatus.ENGINE_ERROR:
page_operator("Verifier crashed — manual review required")
else:
reject_transaction(f"Proof failed: {result.status}")
Aggregation
verify_checkout() propagates the most-severe guard status to the top level
(fail-closed ordering):
| Top-level status | Triggered when |
|---|---|
ENGINE_ERROR |
Any guard raised an exception |
QUARANTINED |
A guard returned QUARANTINED (reserved) |
FAILED |
A guard deterministically disproved the transaction |
UNVERIFIABLE |
Most-severe guard status is UNVERIFIABLE |
UNSUPPORTED |
Most-severe guard status is UNSUPPORTED |
PARTIAL |
Most-severe guard status is PARTIAL |
VERIFIED |
All guards passed |
🔌 Integration
FastAPI Middleware
QWED-UCP ships a configurable FastAPI/Starlette middleware (requires Starlette,
included with pip install qwed-ucp) that intercepts checkout requests and
verifies them automatically:
from fastapi import FastAPI
from qwed_ucp.middleware.fastapi import QWEDUCPMiddleware
app = FastAPI()
app.add_middleware(QWEDUCPMiddleware)
The middleware:
- Intercepts
POST/PUT/PATCHto paths matching/checkout,/cart,/payment - Returns
422 Unprocessable Entityon verification failure (configurable) - Sets headers
X-QWED-Verified,X-QWED-Guards-Passed,X-QWED-Error - Runs core guards (Money, State, Schema) plus optional advanced guards
- Always fail-closed on empty body, malformed JSON, or non-dict payload
Configuration:
app.add_middleware(QWEDUCPMiddleware,
block_on_failure=True, # Block on verification failure (default)
include_details=True, # Include guard details in error response
use_advanced_guards=True, # Also run Line Items, Discount, Currency guards
verify_paths=["/checkout"], # Override default path list
verify_methods=["POST"], # Override default method list
)
A helper dependency is also available for manual injection:
from qwed_ucp.middleware.fastapi import create_verification_dependency
verify = create_verification_dependency()
@app.post("/checkout")
async def create_checkout(
checkout: dict,
verification = Depends(verify)
):
if not verification["verified"]:
raise HTTPException(422, verification["error"])
...
Express.js Middleware
QWED-UCP also ships an Express.js middleware:
const express = require('express');
const { createQWEDUCPMiddleware } = require('qwed-ucp');
const app = express();
app.use(express.json());
app.use(createQWEDUCPMiddleware());
app.post('/checkout', (req, res) => {
res.json({ status: 'verified', checkout: req.body });
});
See examples/express_server.js for a complete
example with rate limiting and security hardening.
Stripe
import stripe
from qwed_ucp import UCPVerifier
def create_payment_intent(ucp_checkout):
verifier = UCPVerifier()
result = verifier.verify_checkout(ucp_checkout)
if not result.verified:
raise ValueError(f"Checkout math error: {result.error}")
total = next(
(item["amount"] for item in ucp_checkout["totals"]
if item["type"] == "total"),
None
)
if total is None:
raise ValueError("Missing required 'total' entry in checkout.totals")
return stripe.PaymentIntent.create(
amount=int(total * 100),
currency=ucp_checkout["currency"].lower()
)
CI/CD
# .github/workflows/verify-checkout.yml
name: Verify UCP Checkouts
on: [push]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: QWED-AI/qwed-ucp@v1
with:
test-script: tests/verify_checkouts.py
🔏 AttestationGuard
For environments that need cryptographic proof of verification:
from qwed_ucp import AttestationGuard, UCPVerifier
import uuid
attester = AttestationGuard(
secret_key="your-256-bit-secret",
allow_insecure=True # Set False in production
)
verifier = UCPVerifier()
result = verifier.verify_checkout(checkout)
attestation = attester.sign_checkout(
checkout=checkout,
verification_result=result, # Accepts UCPVerificationResult directly
transaction_attempt_id=str(uuid.uuid4()),
request_nonce=str(uuid.uuid4()),
session_id="sess_abc123"
)
# attestation.token is a signed JWT
transaction_attempt_id and request_nonce are required for context
binding and in-memory replay protection (not shared across replicas or
restarts — use an external store for multi-instance deployment).
Set QWED_ATTESTATION_SECRET env var instead of passing secret_key in code.
🏷️ Trust Status
QWED-UCP v0.3.0+ exposes a typed TrustStatus enum on every verification
result, replacing the old verified: bool-only model:
| State | Meaning |
|---|---|
VERIFIED |
Deterministic proof succeeded under supported conditions |
FAILED |
Proof was attempted and disproved (e.g. totals mismatch) |
UNVERIFIABLE |
Proof could not be established (e.g. missing proof basis) |
UNSUPPORTED |
Input or state is outside supported semantics |
PARTIAL |
Some checks ran, but no final verdict is justified |
ENGINE_ERROR |
A verifier dependency or the runtime crashed |
QUARANTINED |
Reserved for policy-level rejection |
verified: bool is preserved as a backward-compatible derived field:
result.verified == True only when result.status == TrustStatus.VERIFIED.
🔒 Security & Privacy
Your checkout data never leaves your machine.
| Concern | QWED-UCP Approach |
|---|---|
| Data Transmission | No API calls, no cloud processing |
| Storage | Nothing stored — pure computation |
| Dependencies | Local-only (Decimal, JSON Schema, PyJWT, Starlette) |
| PCI Compliance | No cardholder data processed |
Perfect for: e-commerce with strict privacy requirements, transactions containing PII, PCI-DSS compliant environments.
🗺️ Roadmap
v0.3.0 (Current)
- UCPVerifier with 3 core guards (Money, State, Structure)
- All 10 guards shipped and tested
- TrustStatus enum on every result
- FastAPI middleware (fail-closed on unparseable bodies)
- Express.js middleware
- AttestationGuard with context-bound JWT + replay protection
In Progress
- Multi-currency support (exchange rates)
- Subscription/recurring payment validation
- TypeScript/npm SDK
Planned
- Shopify webhook integration
- Stripe Checkout session verification
- WooCommerce plugin
- Real-time cart verification API
❓ FAQ
Is QWED-UCP free?
Yes! Apache 2.0 license. Use it in commercial products, modify it, distribute it — no restrictions.
Does it handle floating-point precision issues?
Yes! Uses Python's Decimal type with ROUND_HALF_UP to 2 decimal places. No 0.1 + 0.2 = 0.30000000000000004 issues.
What is the UCP total formula?
Total = Subtotal - Discount + Fulfillment + Tax + Fee
QWED-UCP's Money Guard verifies AI outputs against this formula exactly.
Can I use it without Google UCP?
Yes! The guards work with any JSON checkout format that has a totals array
with type and amount fields.
How fast is verification?
Sub-millisecond to low milliseconds per checkout, depending on the guard set. The Decimal math engine is optimized for currency calculations.
Does QWED-UCP expose TrustStatus in the Python SDK?
Yes. qwed_ucp.TrustStatus is a 7-state enum on every result dataclass.
The verified: bool field is preserved for backward compatibility.
🔗 Related QWED Packages
| Package | Purpose |
|---|---|
| qwed-verification | Core verification engine |
| qwed-finance | Banking & financial verification |
| qwed-legal | Legal contract verification |
| qwed-infra | Infrastructure-as-code verification |
| qwed-tax | Tax compliance verification |
| qwed-mcp | Claude Desktop MCP integration |
| qwed-open-responses | OpenAI Responses API guards |
🔗 Links
| Resource | Link |
|---|---|
| Universal Commerce Protocol | ucp.dev |
| Google UCP Docs | developers.google.com/merchant/ucp |
| QWED Documentation | docs.qwedai.com |
| QWED-AI Organization | github.com/QWED-AI |
🧑💻 Development
From Source
git clone https://github.com/QWED-AI/qwed-ucp.git
cd qwed-ucp
pip install -e ".[dev]"
Running Tests
pytest tests/ -v # All tests
pytest tests/ -v --cov=src/qwed_ucp --cov-report=html # With coverage
pytest tests/test_money_guard.py -v # Single guard
Linting
ruff check src/ tests/
📄 License
Apache 2.0 — See LICENSE
Built with ❤️ by QWED-AI
"AI agents shouldn't guess at math. QWED makes commerce verifiable."
Metadata
Release files for qwed-ucp 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qwed_ucp-0.3.0.tar.gz | 104.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qwed_ucp-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 146.0 kB
Release files / qwed_ucp-0.3.0.tar.gz
| Download URL | qwed_ucp-0.3.0.tar.gz |
|---|---|
| Size | 104.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
65abc2f0708c54f7c571b09675b821ac2f9f171acb7e024683e38f5cb0005ec6
|
|
BLAKE2b-256 checksum How to use checksums |
376ad1c19943e3a2d5d11942f7316821a5ec8521741e848a7e6c67c347d4b4bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.
Transparency logRelease files / qwed_ucp-0.3.0-py3-none-any.whl
| Download URL | qwed_ucp-0.3.0-py3-none-any.whl |
|---|---|
| Size | 41.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d0f771d1678484411fb308176a4ec98b35c7d1faa27882f0bde5e85326ee16f2
|
|
BLAKE2b-256 checksum How to use checksums |
3cc757aff4af078dadb7aef16aacf0995cd1f4f9dae3dd2f313c2cfdafc8c73e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 20, 2026.
Transparency log