Guards Reference
QWED-UCP includes 10 verification guards that validate different aspects of UCP checkout data.
1. Money Guard
Verifies the total formula is mathematically correct.
Total = Subtotal - Discount + Tax + Shipping + Fee
Usage
driver = MoneyGuard()
result = driver.verify_cart_totals(
line_items=[{"price": 35.00, "quantity": 2}, {"price": 15.00, "quantity": 1}],
taxes=8.25,
discounts=10.00,
claimed_total=98.25
)
# Returns: {"verified": True}
Tolerance
Uses Decimal precision with 1 cent ($0.01) tolerance for floating-point errors.
2. State Guard
Verifies valid checkout state machine transitions.
Valid States
incomplete → ready_for_complete → completed
↓
failed
↓
cancelled
Usage
from qwed_ucp.guards.state_guard import StateGuard
guard = StateGuard()
# Check if we can SHIP given the current state is PAID
result = guard.verify_transition(
current_state="paid",
action="ship"
)
# Returns: {"verified": True}
Rules
incomplete: Can be empty
ready_for_complete: Must have line items
completed: Must have order object
- Cannot transition backwards
3. Schema Guard
Validates UCP JSON schema compliance.
Usage
from qwed_ucp.guards import SchemaGuard
guard = SchemaGuard()
result = guard.verify(checkout_data)
Validates
- Required fields present
- Correct types (string, number, array)
- Valid enum values (status, total types)
4. Line Items Guard
Verifies price × quantity = line total for each item.
Usage
from qwed_ucp.guards import LineItemsGuard
guard = LineItemsGuard()
result = guard.verify({
"line_items": [
{"id": "roses", "quantity": 2, "item": {"price": 35.00}},
{"id": "pot", "quantity": 1, "item": {"price": 15.00}}
],
"totals": [{"type": "subtotal", "amount": 85.00}] # 2×35 + 1×15 = 85 ✓
})
Checks
- Each item:
price × quantity = line_total
- Sum of line items = subtotal
- Quantities must be positive integers
- Prices must be non-negative
5. Discount Guard
Verifies percentage and fixed discount calculations.
Usage - Percentage Discount
from qwed_ucp.guards import DiscountGuard
from decimal import Decimal
guard = DiscountGuard()
result = guard.verify_percentage_discount(
subtotal=Decimal("100.00"),
discount_amount=Decimal("10.00"),
percentage=Decimal("10") # 10% of 100 = 10 ✓
)
Usage - Fixed Discount
result = guard.verify_fixed_discount(
subtotal=Decimal("50.00"),
discount_amount=Decimal("5.00") # Fixed $5 off ✓
)
Rules
- Percentage: Must be 0-100%
- Fixed: Cannot exceed subtotal
- Discount must be non-negative
6. Currency Guard
Validates ISO 4217 currency codes and format.
Usage
from qwed_ucp.guards import CurrencyGuard
guard = CurrencyGuard()
result = guard.verify({"currency": "USD"})
Validates
- 3-letter ISO 4217 codes (USD, EUR, GBP, JPY, etc.)
- Zero-decimal currencies (JPY, KRW) have no decimals
- Currency conversion accuracy
Zero-Decimal Currencies
# Valid - no decimals
{"currency": "JPY", "totals": [{"type": "total", "amount": 1000}]}
# Invalid - JPY shouldn't have decimals
{"currency": "JPY", "totals": [{"type": "total", "amount": 1000.50}]}
7. Refund Guard
Verifies refund amounts match original transactions.
Usage - Full refund
from qwed_ucp.guards.refund import RefundGuard
from decimal import Decimal
guard = RefundGuard()
result = guard.verify_full_refund(
original_total=Decimal("100.00"),
refund_amount=Decimal("100.00")
)
# Returns: RefundGuardResult(verified=True, details={"refund_type": "full"})
Usage - Partial refund
result = guard.verify_partial_refund(
original_total=Decimal("100.00"),
refund_amount=Decimal("50.00"),
percentage=Decimal("50") # 50% of 100 = 50 ✓
)
Usage - Tax reversal
result = guard.verify_tax_reversal(
original_tax=Decimal("10.00"),
refund_tax=Decimal("5.00"),
refund_percentage=Decimal("50") # 50% of tax reversed ✓
)
Usage - Checkout refund
checkout = {"totals": [{"type": "total", "amount": 100.00}]}
refund = {"amount": 100.00, "type": "full"}
result = guard.verify(checkout, refund)
Rules
- Full refund must exactly match original total
- Partial refund percentage must be 0-100%
- Refund cannot exceed original total
- Tax reversal must be proportional to the refund percentage
8. Tip Guard
Verifies tip calculations (pre-tax and post-tax).
Usage - Pre-tax tip
from qwed_ucp.guards.tip import TipGuard
from decimal import Decimal
guard = TipGuard()
result = guard.verify_percentage_tip(
subtotal=Decimal("50.00"),
tip_amount=Decimal("9.00"),
percentage=Decimal("18") # 18% of 50 = 9 ✓
)
# Returns: TipGuardResult(verified=True, details={"tip_type": "pre-tax"})
Usage - Post-tax tip
result = guard.verify_post_tax_tip(
total=Decimal("108.00"),
tip_amount=Decimal("21.60"),
percentage=Decimal("20") # 20% of 108 = 21.60 ✓
)
# Returns: TipGuardResult(verified=True, details={"tip_type": "post-tax"})
Usage - Bounds check
result = guard.verify_tip_bounds(
tip_amount=Decimal("20.00"),
base_amount=Decimal("100.00")
)
Rules
- Tip percentage must be 0-100%
- Tip cannot be negative
- Tip cannot exceed 100% of the base amount
- Supports both pre-tax (subtotal) and post-tax (total) calculations
9. Fee Guard
Verifies fee calculations (service, delivery, platform).
Usage - Service fee
from qwed_ucp.guards.fee import FeeGuard
from decimal import Decimal
guard = FeeGuard()
result = guard.verify_service_fee(
subtotal=Decimal("100.00"),
fee_amount=Decimal("5.00"),
percentage=Decimal("5") # 5% of 100 = 5 ✓
)
# Returns: FeeGuardResult(verified=True, details={"fee_type": "service"})
Usage - Delivery fee
# Formula: base_fee + (distance × rate_per_km)
result = guard.verify_delivery_fee(
claimed_fee=Decimal("13.00"),
distance_km=Decimal("5"),
rate_per_km=Decimal("2.00"),
base_fee=Decimal("3.00") # 3 + 5×2 = 13 ✓
)
# Returns: FeeGuardResult(verified=True, details={"fee_type": "delivery"})
result = guard.verify_platform_fee(
fee_amount=Decimal("15.00"),
subtotal=Decimal("100.00"),
max_percentage=Decimal("30") # 15% < 30% max ✓
)
Rules
- Fee percentage cannot be negative
- Distance and rate cannot be negative
- Platform fee cannot be negative
- Platform fee cannot exceed the configured maximum percentage (default 30%)
10. Attestation Guard
Generates cryptographic proofs (JWTs) for verification results.
Usage - Sign a checkout
from qwed_ucp.guards.attestation import AttestationGuard
# Production: provide a secret key or set QWED_ATTESTATION_SECRET env var
guard = AttestationGuard(secret_key="your-secret-key")
# Dev mode: use allow_insecure=True (generates a random secret)
guard = AttestationGuard(allow_insecure=True)
result = guard.sign_checkout(
checkout={"currency": "USD", "totals": [{"type": "total", "amount": 82.79}]},
verification_result={"verified": True},
guards_passed=["MoneyGuard", "StateGuard", "LineItemsGuard"]
)
print(result.token) # JWT token string
print(result.verified) # True
print(result.details) # {"checkout_hash": "...", "issued_at": ..., "expires_at": ...}
Usage - Verify an attestation
result = guard.verify_attestation(token="eyJ...")
print(result.verified) # True if valid and not expired
print(result.details) # Decoded JWT payload
Usage - Create a receipt
receipt = guard.create_receipt(
checkout=checkout_data,
verification_result={"verified": True}
)
print(receipt["receipt_id"]) # "QWED-A1B2C3D4..."
print(receipt["verified"]) # True
print(receipt["engine"]) # "QWED-Deterministic-v1"
print(receipt["verification_mode"]) # "deterministic"
JWT payload fields
| Field | Type | Description |
|---|
iss | string | Always "qwed-ucp-attestation" |
iat | int | Issued-at Unix timestamp |
exp | int | Expiration timestamp (1 hour after issuance) |
checkout_hash | string | SHA-256 hash of the checkout object |
verified | bool | Whether the checkout passed verification |
guards_passed | array | List of guard names that passed |
errors | array | List of errors (if any) |
engine | string | "QWED-Deterministic-v1" |
verification_mode | string | "deterministic" |
In production, set QWED_ATTESTATION_SECRET as an environment variable or pass secret_key directly. Without a secret, initialization raises a ValueError unless allow_insecure=True or the QWED_DEV_MODE=1 env var is set.
Verification result fields
All guard results and UCPVerificationResult include:
| Field | Type | Description |
|---|
verified | bool | Whether verification passed |
engine | string | "QWED-Deterministic-v1" |
verification_mode | string | "deterministic" |
error | string | Error message (when verified is false) |
Running all guards
Use UCPVerifier to run all guards at once:
from qwed_ucp import UCPVerifier
verifier = UCPVerifier()
result = verifier.verify_checkout(checkout_data)
print(f"Verified: {result.verified}")
print(f"Engine: {result.engine}") # "QWED-Deterministic-v1"
print(f"Mode: {result.verification_mode}") # "deterministic"
print(f"Guards passed: {len([g for g in result.guards if g.verified])}")