ucp-validate

End-to-end validation of a merchant's UCP integration. Tests profile schema, capability negotiation, catalog search/lookup, checkout lifecycle, and payment handler declaration. Outputs a PASS/FAIL compliance report with 40+ checks. Use after deployment to verify the integration works correctly.

UCP Validate — Integration Compliance Tester

Run 40+ validation checks against a deployed UCP integration and produce a compliance report.

Prerequisites

  • Merchant must have /.well-known/ucp deployed
  • Python 3.10+ with requests, jsonschema

Step 1: Profile Validation (Checks 1-12)

Fetch {merchant_url}/.well-known/ucp and validate:

#CheckRuleSeverity
1Profile existsGET returns 200 with JSON content-typeCRITICAL
2Valid JSONResponse parses as JSONCRITICAL
3Has ucp root keyTop-level object contains ucpCRITICAL
4Version formatucp.version matches YYYY-MM-DDCRITICAL
5Has servicesucp.services is non-empty objectCRITICAL
6Service transportEach service entry has valid transport (rest|mcp|a2a|embedded)ERROR
7Service endpointEach rest/mcp/a2a service has endpoint URLERROR
8Has capabilitiesucp.capabilities is non-empty objectWARNING
9Capability namingAll capability names follow {reverse-domain}.{service}.{capability}ERROR
10Capability versionEach capability has version in YYYY-MM-DD formatERROR
11Has payment_handlersucp.payment_handlers is non-empty objectERROR
12Payment handler fieldsEach handler has id, version, available_instrumentsERROR

Step 1 Gate Check

If checks 1-5 all FAIL → abort remaining checks, report "Profile not UCP-compliant."

Step 2: Namespace & Spec URL Validation (Checks 13-18)

#CheckRuleSeverity
13Spec URL bindingspec URL origin matches namespace authorityERROR
14Schema URL bindingschema URL origin matches namespace authorityERROR
15Spec URL reachableGET spec URL returns 200WARNING
16Schema URL reachableGET schema URL returns 200WARNING
17No dev.ucp.* misuseVendor does not declare dev.ucp.* capabilities without matching spec URLsERROR
18Extension extends validEvery extension's extends field references a declared capabilityERROR

Spec URL binding rule:

  • dev.ucp.* → spec must be at https://ucp.dev/...
  • com.example.* → spec must be at https://example.com/...
  • Match is on origin (scheme + host), not full path

Step 3: Catalog Validation (Checks 19-27)

If dev.ucp.shopping.catalog.search or dev.ucp.shopping.catalog.lookup is declared:

#CheckRuleSeverity
19Search endpoint respondsPOST to catalog search returns 200ERROR
20Search response has productsResponse contains products arrayERROR
21Products have required fieldsEach product has id, title, description, price_range, variantsERROR
22Variants have required fieldsEach variant has id, title, description, priceERROR
23Price format correctprice.amount is integer (minor units), price.currency is ISO 4217ERROR
24At least 1 variant per productvariants array is non-emptyERROR
25Lookup endpoint respondsPOST to catalog lookup with valid ID returns 200ERROR
26Lookup returns matching productResponse product ID matches requested IDERROR
27Pagination worksIf >10 products, pagination token returns next pageWARNING

Step 4: Checkout Validation (Checks 28-37)

If dev.ucp.shopping.checkout is declared:

#CheckRuleSeverity
28Create sessionPOST create with valid line_item returns 200ERROR
29Session has required fieldsResponse has id, status, line_items, currency, totalsERROR
30Status is incompleteInitial status is incompleteERROR
31Totals structureHas exactly 1 subtotal and 1 total entryERROR
32Discount amounts negativeAny discount/items_discount total has amount < 0ERROR
33Non-discount amounts non-negativeAll other total types have amount >= 0ERROR
34Update sessionPOST update with modified quantity returns 200ERROR
35Totals recalculatedAfter update, totals reflect new quantityWARNING
36Links presentResponse has links with privacy_policy and terms_of_serviceWARNING
37Cancel sessionIf supported, cancel returns appropriate statusWARNING

HARD RULE — Never call checkout complete. Validation must NOT trigger real payments. Only test create, update, retrieve, and cancel. If the merchant has a sandbox/test mode, note it in the report but still do not complete.

Step 5: Capability Negotiation Validation (Checks 38-42)

#CheckRuleSeverity
38UCP response headerCheckout response includes ucp metadata with active capabilitiesERROR
39Capability intersectionResponse capabilities are subset of profile capabilitiesERROR
40Orphan extension pruningNo extension in response whose parent is missingERROR
41Version compatibilityResponse capability versions match or are compatible with profileWARNING
42Payment handler in responseCheckout response includes at least one payment_handlerERROR

Step 6: Generate Compliance Report

Save to store/clients/{client_name}/validation-report.md:

# UCP Compliance Report — {merchant_name}

**URL:** {url}
**Date:** {date}
**Spec Version Tested:** 2026-01-23
**Result:** {PASS|FAIL} ({passed}/{total} checks passed)

## Summary
- CRITICAL: {count} passed / {count} total
- ERROR: {count} passed / {count} total
- WARNING: {count} passed / {count} total

## Results

### Profile (Checks 1-12)
| # | Check | Result | Detail |
|---|-------|--------|--------|
| 1 | Profile exists | PASS/FAIL | {detail} |
...

### Namespace (Checks 13-18)
...

### Catalog (Checks 19-27)
...

### Checkout (Checks 28-37)
...

### Negotiation (Checks 38-42)
...

## Failed Checks — Fix Guide
{For each FAIL, explain what's wrong and how to fix it}

Passing criteria:

  • PASS: All CRITICAL pass + all ERROR pass (warnings can fail)
  • CONDITIONAL PASS: All CRITICAL pass + some ERROR fail
  • FAIL: Any CRITICAL fails

Scripts

ScriptPurposeDependencies
validate_ucp.pyMain validation runnerrequests, jsonschema, json, re, sys

Collaboration

ucp-validate (this skill)
    │
    ├── inputs ← deployed merchant URL
    │
    ├── outputs → store/clients/{name}/validation-report.md
    │
    └── used after → ucp-checkout (post-deployment verification)