You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Summary
Mirrors `agentscore/node-commerce#8` on the Python side. Ships as
`1.3.0` (next minor after `1.2.0`).
**1. Kill x402 Solana (BREAKING)**
- Drop `x402-solana-*` rails. Add `mpp-solana-*` rails
(method=`solana`).
- `validate_x402_network_config` now base-only (`base_network: str`, was
`{base, svm}` object).
- `verify_x402_request` takes single `accepted_network: str`.
- Rename `X402SolanaConfig` → `SolanaMppConfig`, `X402SolanaRailConfig`
→ `SolanaMppRailConfig`.
- pyproject `x402[evm,fastapi]>=2.8,<3` (no `svm` extra).
- **Python parity gap (intentional):** there is no Python equivalent of
`@solana/mpp`, so `create_mppx_server` does not ship a Solana rail.
Python merchants on Solana implement MPP `solana/charge` server-side
themselves.
**2. New helpers**
- `classify_x402_settle_result` collapses `process_x402_settle` failure
phases (`verify_failed` / `settle_failed` / `facilitator_error` /
`no_requirements`) to `(status, code, message, next_steps)`. Mapping is
identical to the node side: 400 / 503 / 503 / 500.
- `extra_warnings` field on `BuildAgentInstructionsInput`; append
per-order warnings on top of defaults.
- Solana-network rejection branch in `verify_x402_request`: clients
presenting an x402 credential on a `solana:*` network get a
behavior-only hint pointing at the `solana/charge` rail.
- `process_x402_settle` wraps facilitator throws as
`phase='facilitator_error'` across all steps.
**3. x402scan discovery (Layer 1)**
- `build_well_known_x402` builder.
- OpenAPI extension helpers (`siwx_security_scheme`,
`x_payment_info_extension`, `x_guidance_extension`).
**4. Internal-disclosure cleanup**
- Replaced threat-model rationale in source docstrings with
behavior-only language (`stripe_multichain/pi_cache.py`,
`identity/types.py`, `identity/signer.py`).
- Genericized Martin Estate / martinestate.com /
martin-estate-wine-commerce / "wine-purchase" baked into examples +
tests + docstrings.
- Removed `pending_identity` internal state name from agent-visible
warnings.
- Removed `x402[evm,svm]` references from CLAUDE.md (the upstream extra
is gone; we depend on `x402[evm]`).
## Test plan
- [x] 715 pytest tests passing (3 skipped)
- [x] ruff + ty all green
- [x] CodeQL + dependency + python audit scans green
## Downstream impact
Once this lands and `agentscore-commerce==1.3.0` publishes:
- `agentscore/core#230` will pass CI (currently red on
`agentscore-commerce[mppx,x402]>=1.3.0` resolution).
- The store route's `verify_x402_request` + `process_x402_settle` +
`classify_x402_settle_result` wiring depends on this SDK release.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@@ -30,15 +30,15 @@ Single Python package, hatchling-built, published to PyPI as `agentscore-commerc
30
30
|`examples/`| Runnable single-file FastAPI apps for each common scenario |
31
31
|`tests/`| pytest, one file per surface |
32
32
33
-
Peer-dep pattern: payment/x402/mppx/stripe modules import lazily at runtime — vendors install only what they use via extras (`pip install agentscore-commerce[fastapi,stripe]` etc.). Underlying packages: `x402[evm,svm]`, `pympp[server,tempo,stripe]`, `stripe`. Missing peer dep raises a guiding `ImportError` with the install command.
33
+
Peer-dep pattern: payment/x402/mppx/stripe modules import lazily at runtime — vendors install only what they use via extras (`pip install agentscore-commerce[fastapi,stripe]` etc.). Underlying packages: `x402[evm]`, `pympp[server,tempo,stripe]`, `stripe`. Missing peer dep raises a guiding `ImportError` with the install command.
34
34
35
35
## Examples
36
36
37
37
`examples/` contains full single-file FastAPI apps for the most common merchant scenarios — copy-paste templates, not frameworks:
38
38
39
39
| Example | Scenario |
40
40
|---|---|
41
-
|`api_provider.py`| Per-call API billing on multiple rails: Tempo MPP + x402 (Base + Solana); no compliance gate |
41
+
|`api_provider.py`| Per-call API billing on multiple rails: Tempo MPP + x402 Base + Solana MPP; no compliance gate |
42
42
|`identity_only.py`| Compliance gate without payment (vendor handles their own) |
43
43
|`multi_rail_merchant.py`| Full agent-commerce: identity + Tempo MPP + x402 + Stripe SPT |
|`agentscore_commerce.identity` (package level) | Re-exports the denial helpers: `denial_reason_status`, `denial_reason_to_body`, `build_signer_mismatch_body`, `build_contact_support_next_steps`, `verification_agent_instructions`, `is_fixable_denial`, `FIXABLE_DENIAL_REASONS`. Also re-exports the per-product policy helpers: `PolicyBlock`, `GateResult`, `EnforcementMode`, `IdentityStatus`, `build_gate_from_policy`, `run_gate_with_enforcement`, `shipping_country_allowed`, `shipping_state_allowed` — for multi-product merchants where each product carries its own compliance config (hard gate vs soft vs none, per-product shipping allowlists). |
20
-
|`agentscore_commerce.payment`|`networks`, `USDC`, `rails` registries; `payment_directive`, `build_payment_directive`, `www_authenticate_header`, `payment_required_header`, `alias_amount_fields` (v1↔v2 amount field shim — emits both `amount` and `maxAmountRequired` so v1-only x402 parsers like Coinbase awal can read v2 bodies), `settlement_override_header`, `dispatch_settlement_by_network`, `extract_payment_signer` (returns `PaymentSigner({address, network})`), `register_x402_schemes_v1_v2`; drop-in x402 helpers: `validate_x402_network_config` (boot-time guard), `verify_x402_request` (parse + validate inbound X-Payment), `process_x402_settle` (verify-then-settle with one call). |
20
+
|`agentscore_commerce.payment`|`networks`, `USDC`, `rails` registries; `payment_directive`, `build_payment_directive`, `www_authenticate_header`, `payment_required_header`, `alias_amount_fields` (v1↔v2 amount field shim — emits both `amount` and `maxAmountRequired` so v1-only x402 parsers like Coinbase awal can read v2 bodies), `settlement_override_header`, `dispatch_settlement_by_network`, `extract_payment_signer` (returns `PaymentSigner({address, network})`), `register_x402_schemes_v1_v2`; drop-in x402 helpers: `validate_x402_network_config` (boot-time guard), `verify_x402_request` (parse + validate inbound X-Payment), `process_x402_settle` (verify-then-settle with one call), `classify_x402_settle_result` (maps the tagged settle result to a recommended HTTP status / code / next_steps so merchants get a controlled envelope without coupling to facilitator-specific error text). |
21
21
|`agentscore_commerce.discovery`|`is_discovery_probe_request`, `build_discovery_probe_response` (with optional `x402_sample` for x402-aware crawlers — `awal x402 details` etc.), `sample_x402_accept_for_network` (USDC sample-accept builder for known CAIP-2 networks), `build_well_known_mpp`, `build_llms_txt` + `llms_txt_identity_section` + `llms_txt_payment_section` (compact + verbose modes), `build_skill_md` (Claude-Skill-compatible `/skill.md` agent-discovery manifest — strictly agent-facing data only, no internal posture), `agentscore_openapi_snippets`, `build_bazaar_discovery_payload`, `NoindexNonDiscoveryMiddleware` (ASGI middleware that emits `X-Robots-Tag: noindex` on every path except the agent-discovery surfaces — defaults cover `/openapi.json`, `/llms.txt`, `/skill.md`, `/.well-known/{mpp.json,agent-card.json,ucp}`, `/favicon.{png,ico}`; pure helpers `is_discovery_path` + `DEFAULT_DISCOVERY_PATHS` for non-ASGI frameworks). |
22
22
|`agentscore_commerce.challenge`|`build_402_body`, `build_accepted_methods`, `build_identity_metadata`, `build_how_to_pay`, `build_agent_instructions` (auto-emits per-rail `compatible_clients` — smoke-verified CLIs the agent should use; vendor override supported), `build_pricing_block` (cents → dollar-string with optional shipping/tax), `first_encounter_agent_memory` (cross-merchant hint, returns the canonical block or `None` based on a per-merchant first-seen flag), `OrderReceipt` (dataclass for the post-settlement 200 response shape); `respond_402` — drop-in 402 emit that preserves pympp's `WWW-Authenticate` and layers x402's `PAYMENT-REQUIRED`. `build_validation_error` — structured 4xx body builder (`{error: {code, message}, required_fields?, example_body?, next_steps?, ...extra}`) so vendors compose body shapes by name instead of inlining at every validation site. |
23
23
|`agentscore_commerce.stripe_multichain`|`create_multichain_payment_intent`, `get_deposit_address`, `simulate_crypto_deposit`; `create_pi_cache` (TTL'd PI / deposit-address cache, Redis-backed when `redis_url` set, in-memory otherwise), `simulate_deposit_if_test_mode` (gates on `sk_test_` and looks up the PI for you), `STRIPE_TEST_TX_HASH_SUCCESS` / `STRIPE_TEST_TX_HASH_FAILED` constants. Peer dep on `stripe`. |
@@ -247,15 +247,14 @@ from agentscore_commerce.payment import (
247
247
ProcessX402SettleInput,
248
248
ValidateX402NetworkConfigInput,
249
249
VerifyX402RequestInput,
250
+
classify_x402_settle_result,
250
251
process_x402_settle,
251
252
validate_x402_network_config,
252
253
verify_x402_request,
253
254
)
254
255
255
256
# Boot-time guard — raises if a configured network isn't supported.
0 commit comments