Skip to content

feat(commerce 1.3)!: kill x402 Solana, add MPP solana/charge + classify+extraWarnings + x402scan discovery#8

Merged
vvillait88 merged 19 commits intomainfrom
feat/x402-settle-facilitator-error
May 5, 2026
Merged

feat(commerce 1.3)!: kill x402 Solana, add MPP solana/charge + classify+extraWarnings + x402scan discovery#8
vvillait88 merged 19 commits intomainfrom
feat/x402-settle-facilitator-error

Conversation

@vvillait88
Copy link
Copy Markdown
Contributor

@vvillait88 vvillait88 commented May 4, 2026

Summary

Major release pulling together everything that landed on this branch beyond the original facilitator-error fix. Ships as 1.3.0 (next minor after 1.2.0).

1. Kill x402 Solana, add MPP solana/charge (BREAKING)

  • Drop x402-solana-mainnet / x402-solana-devnet rails from the registry.
  • Drop SVM from validateX402NetworkConfig (now base-only) and verifyX402Request (single acceptedNetwork: string, was {base, svm} object).
  • Drop SVM from createX402Server rail union; drop the SVM extraction branch in extractPaymentSigner.
  • Add mpp-solana-mainnet / mpp-solana-devnet rails (method=solana).
  • Add solana rail to createMppxServer, wiring @solana/mpp/server charge.
  • Drop @x402/svm from devDependencies; add @solana/mpp + @solana/kit as optional peer deps.
  • Cross-rename: x402_solanasolana_mpp field across challenge builders + discovery surfaces.

2. New helpers

  • classifyX402SettleResult collapses processX402Settle failure phases (verify_failed / settle_failed / facilitator_error / no_requirements) to (status, code, message, next_steps). Maps to 400 / 503 / 503 / 500.
  • extraWarnings field on buildAgentInstructions — append per-order warnings on top of the SDK's default protocol-footgun set.
  • Solana-network rejection branch in verifyX402Request: clients presenting an x402 credential on a solana:* network get a behavior-only hint pointing at the solana/charge rail. Case-insensitive prefix match.
  • verifyX402Request now wraps facilitator throws as phase: 'facilitator_error' cleanly across build_requirements, enrich_extensions, and process_payment_request steps.

3. Solana signer recovery in extractPaymentSigner

  • New 3-step MPP recovery order: (a) EVM DID did:pkh:eip155:<chain>:<addr> source, (b) Solana DID did:pkh:solana:<genesis>:<addr> source, (c) pull-mode tx decode that reads the SPL TransferChecked authority via @solana/kit (optional peer).
  • Fixes the wallet-signer-match gap on Solana MPP: previously the recovered signer was always null on Solana credentials because @solana/mpp/client doesn't set Credential.source, which silently weakened wallet-auth security relative to EVM. Now the gate's verifyWalletSignerMatch enforces same-operator on Solana the same way it does on EVM.
  • Pull mode (payload.type === 'transaction') covered. Push mode (payload.type === 'signature') returns null (RPC fetch deferred; pay uses pull mode by default).
  • Defensive bounds-check on lookup-table account indices (v0 txs).

4. x402scan discovery (Layer 1)

  • New buildWellKnownX402 builder for the /.well-known/x402 endpoint.
  • New OpenAPI extension helpers (siwxSecurityScheme, xPaymentInfoExtension, xGuidanceExtension).

5. Internal-disclosure cleanup

  • Replaced threat-model rationale in source comments with behavior-only language across core.ts, stripe-multichain/pi-cache.ts, payment/x402_validation.ts, signer-match.test.ts.
  • Removed exact defense parameters from user-visible places.
  • Genericized customer-domain attributions baked into examples / docstrings / tests (Martin Estate / martinestate.com / wine-purchase → Example Merchant / agents.example.com / product-purchase).
  • Removed internal state name pending_identity from agent-visible warnings; agents see "the order will not complete."
  • Dropped upstream finger-pointing from README rails section.

Test plan

  • 660 vitest tests passing (4 skipped)
  • eslint + typecheck clean
  • CodeQL + dependency scan green

Downstream impact

Once this lands and @agent-score/commerce@1.3.0 publishes:

  • agentscore/martin-estate#56 will pass CI (currently red on acceptedNetwork, extraWarnings, solana_mpp RailKey).
  • agentscore/pay#17 consumes the new SDK shape via the rails registry.
  • Solana wallet-signer-match enforcement turns on automatically for any martin-estate Solana settle.

🤖 Generated with Claude Code

vvillait88 and others added 2 commits May 4, 2026 10:45
…or_error'

Today processX402Settle only wraps settlePayment in try/catch. The
three earlier facilitator-touching calls — buildPaymentRequirements,
enrichExtensions, processPaymentRequest — bubble exceptions unchecked,
so a facilitator that throws on a misconfigured network (e.g. Coinbase
CDP rejecting Solana devnet) lands in the merchant's outermost catch
as an opaque 500.

Add a new 'facilitator_error' tagged variant to ProcessX402SettleResult
with a 'step' discriminator (build_requirements | enrich_extensions |
process_payment_request) and the original error for diagnostics. Wrap
all three calls. Merchants get structured 503-with-recovery instead of
500.

Stays facilitator-agnostic — no vendor-name validation, no auto-select.
Merchants pick whichever facilitator they want (Coinbase CDP, public
x402.org, Nevermined, self-hosted); the SDK now just surfaces facilitator
failures cleanly regardless of which one was chosen.

Test plan:
- 8 new tests in tests/payment/x402_settle.test.ts covering all
  success + sad paths
- Full suite: 638 passed

Bumps to 1.3.0 (minor: additive variant on the result union, no
breaking change to the success path or existing failure phases).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Maps the discriminated union from processX402Settle to a recommended
{status, code, message, nextSteps} envelope so merchants stop sniffing
facilitator error message strings to decide between 400 / 503 / 500.

Phase mapping:
- verify_failed -> 400 payment_proof_invalid / regenerate_payment_credential
- facilitator_error -> 503 payment_provider_unavailable / try_different_rail
- settle_failed -> 503 payment_provider_unavailable / retry_or_swap_method
  (retry_after_seconds: 10)
- no_requirements -> 500 payment_internal_error / contact_support

Returned object is intentionally facilitator-agnostic and never carries
the raw error; merchants log result server-side and return the classified
envelope to the consumer.

Updated JSDoc on each non-success variant of ProcessX402SettleResult to
spell out the log-raw / return-controlled posture and point at the
helper. Replaced the brittle 'phase' field leak in the README example
with the helper. Mirrored the helper mention into the package-table
docs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vvillait88 and others added 3 commits May 4, 2026 11:27
Describe the helper neutrally as a controlled-envelope mapper that
decouples merchants from facilitator-specific error text, instead of
naming the prior antipattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…t-info, x-guidance, siwx)

Closes the discovery-substrate gap with x402scan: every commerce-SDK merchant
now emits everything x402scan's strict parser needs, no per-merchant boilerplate.

- buildWellKnownX402(): emits {version: 1, resources: ["METHOD /path"]} for /.well-known/x402
- xPaymentInfoExtension(): per-operation x-payment-info with fixed/dynamic price + protocols (x402, mpp)
- xGuidanceExtension(): info.x-guidance prose blob for OpenAPI top-level
- siwxSecurityScheme(): http bearer SIWX entry for components.securitySchemes
- agentscoreSecuritySchemes() now includes siwx alongside OperatorToken + WalletAddress
- /.well-known/x402 added to defaultDiscoveryPaths so the noindex middleware lets it through

Smoke verified end-to-end: spun up an http server emitting all the new docs and
ran @agentcash/discovery against it. Output:

    Source:   openapi
    Routes:   3
      POST  /purchase  paid  0.10 USD  [x402, mpp]
      POST  /quote     paid  0.01-5.00 USD  [x402]
      GET   /whoami    siwx
    Guidance: 29 tokens

x402scan classifies fixed-price, dynamic-price, multi-protocol, and SIWX-only
routes correctly. Only warning is missing favicon (cosmetic).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…al Solana path

x402 Solana was structurally broken against any payTo whose USDC ATA wasn't
pre-warmed. The upstream `@x402/svm` `ExactSvmScheme` tx-builder doesn't include
a `createAssociatedTokenIdempotent` instruction, so SPL transfers fail simulation
with `InvalidAccountData` whenever the destination ATA doesn't exist (Stripe-
multichain rotating addresses, fresh wallets, etc.). Upstream's stance per
x402-foundation/x402#1020 is that ATA pre-creation is the seller's responsibility
by design (rent-drain attack vector); they will not patch.

The cleaner architectural answer is MPP `solana/charge`. The buyer's tx-builder
includes idempotent ATA-create before TransferChecked, so payments work against
any payTo, and the spec is what Stripe officially routes Solana through per
docs.stripe.com/payments/machine.

Changes (BREAKING):
- Drop `x402-solana-mainnet` / `x402-solana-devnet` rails from the rail registry
- Drop SVM from `validateX402NetworkConfig` (now base-only) and `verifyX402Request`
  (single `acceptedNetwork`, not a `{base, svm}` object)
- Drop SVM from `createX402Server` rail union
- Drop the SVM extraction branch in `extractPaymentSigner`
- Add `mpp-solana-mainnet` / `mpp-solana-devnet` rails (method='solana')
- Add `solana` rail to `createMppxServer` wiring `@solana/mpp/server` charge
- Rename `x402_solana` -> `solana_mpp` field across challenge builders and discovery
  (accepted_methods emits `solana/charge`, agent_instructions/skill_md/llms_txt
  surface MPP Solana terminology)
- New `SolanaMppMethodEntry` type with optional `fee_payer_key`
- Drop `@x402/svm` from devDependencies; add `@solana/mpp` + `@solana/kit` as
  optional peer deps
- Trim implementation noise (ATA-create mechanics, settle internals) from
  buyer-facing surfaces (skill.md, llms.txt, agent_instructions, how_to_pay) per
  feedback that those are agent-actionable, not protocol explainers
- Bump 1.3.0 -> 1.4.0
- Update README + examples + CLAUDE.md

655 tests pass, lint + typecheck clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vvillait88 added 7 commits May 4, 2026 17:34
…adata

Tightens the audit findings post-1.4.0 release:
- README quick-start sample updated to the new single `acceptedNetwork`
  signature (was the dropped `acceptedNetworks: { base, svm }` object)
- examples/README + CLAUDE.md per-example descriptions advertise Solana
  via MPP `solana/charge`, not x402 SVM
- api-provider.ts inline comment clarifies which header carries which
  protocol now that x402 is base-only
- well_known_mpp test passes through `x402.networks: ['base']` instead of
  `['base', 'solana']`; merchant builders should advertise base only
…s hook

verifyX402Request gets a dedicated branch for incoming x402 credentials on a
solana:* network. Instead of the generic "Unsupported x402 network" message,
the response points the client at the `solana/charge` rail in the 402 challenge
so an agent on a stale x402 SVM client can recover with one re-sign.

Both the error message and next_steps stay behavior-only: no internal terminology,
no CLI vendor references, no protocol-handshake mechanics, no infra disclosure.

buildAgentInstructions gets an `extraWarnings` field so merchants can append
per-order rail-availability notes on top of the SDK's protocol-footgun defaults
(without overriding them). Set `warnings` directly to override entirely;
`extraWarnings` is ignored in that case.

- src/payment/x402_validation.ts: new solana:* branch in the network-mismatch check
- src/challenge/agent_instructions.ts: BuildAgentInstructionsInput gets
  `extraWarnings`; default-warnings concat covers both rails + extras
- tests/payment/x402_validation.test.ts: assertion updated for the new Solana hint
- tests/challenge/agent_instructions.test.ts: two new tests for extraWarnings +
  the override case
Public-package source describes behavior, not internal state names or
named-customer business attributions. Sweep across docstring examples and
agent-visible warnings:

- Removed "pending_identity" (internal order-state column value) from the
  default warnings emitted by buildAgentInstructions + buildLlmsTxt; agents
  see "the order will not complete" instead of an internal state name
- Genericized docstring examples in identity/a2a.ts, identity/ucp.ts,
  discovery/skill_md.ts, challenge/order_receipt.ts: "Martin Estate Wine
  Concierge" + "agents.martinestate.com" + "wine-purchase" placeholders
  replaced with "Example Merchant" / "agents.example.com" / generic skills
- Removed the "(Martin Estate today; Commerce7 / WooCommerce / Shopify
  plugins tomorrow)" forward-looking rollout note from order_receipt.ts

Mintlify worked-example pages and the public marketing site keep referencing
Martin Estate by name; that's allowed at the marketing/URL level per the
disclosure-posture rules.
…ocstring

buildContactSupportNextSteps usage example used a real customer's support
email address. Genericize to support@example.com per the disclosure-posture
rules; merchants supply their own address at the call site.
Public-package tests are part of the public surface (visible on the npm
tarball + GitHub source). The hono + a2a tests were using "Martin Estate" /
"https://agents.martinestate.com" / "wine-purchase" as fixture values; that
bakes a public reference customer's domain into the SDK source. Swap to
"Example Merchant" / "https://agents.example.com" / "product-purchase".
Public-package source + tests describe behavior, not threat model.

- src/core.ts: drop "malicious merchant phishing agents into attacker-
  controlled endpoints" rationale from the CANONICAL_AGENTSCORE_API
  comment; the constant is hardcoded; the why doesn't need to ship
- src/stripe-multichain/pi-cache.ts: replace "prevents agents from sending
  payment to an attacker-controlled address" with "validates the credential's
  deposit address against the addresses the merchant has minted"
- src/payment/x402_validation.ts: replace "defends against agents replaying
  credentials against attacker-controlled deposit addresses" with the
  behavior-only equivalent

Tests: genericize remaining customer references in tests/_response.test.ts,
tests/identity/ucp.test.ts, tests/payment/directive.test.ts, and the entire
tests/discovery/skill_md.test.ts fixture set. Swap "Martin Estate" /
"martinestate.com" / "wine-purchase" / "martin-estate-wine-commerce" for
"Example Merchant" / "example.com" / "product-purchase" /
"example-merchant-commerce".
…ub remaining wine ref

- tests/signer-match.test.ts: rephrase the buildAgentMemoryHint test name +
  comment from "prevent cross-merchant phishing / malicious merchant" to
  "emits the canonical AgentScore API regardless of merchant baseUrl".
  Behavior is the same; the rationale narration goes away.
- tests/express.test.ts: replace remaining 'wine purchase' context fixture
  with 'product purchase'
@vvillait88 vvillait88 changed the title feat(x402-settle): wrap verify-stage facilitator throws as 'facilitator_error' feat(commerce 1.4)!: kill x402 Solana, add MPP solana/charge + classify+extraWarnings + x402scan discovery May 5, 2026
Lands the cycle's commerce SDK changes (kill x402 Solana + add MPP
solana/charge + classify+extraWarnings + x402scan discovery + internal-
disclosure scrubs) as the next minor release after 1.2.0.
@vvillait88 vvillait88 changed the title feat(commerce 1.4)!: kill x402 Solana, add MPP solana/charge + classify+extraWarnings + x402scan discovery feat(commerce 1.3)!: kill x402 Solana, add MPP solana/charge + classify+extraWarnings + x402scan discovery May 5, 2026
vvillait88 added 6 commits May 4, 2026 21:24
…Request

A misformatted credential carrying `SOLANA:5eyk...` or `Solana:5eyk...`
would fall through to the generic 'Unsupported x402 network' message
instead of the targeted Solana hint that points at the `solana/charge`
rail. CAIP-2 spec is lowercase by convention, but defensive code costs
one `.toLowerCase()` and rescues malformed inputs.
…tSigner

Anticipatory: when an MPP credential's `source` field is a Solana CAIP-10
DID (`did:pkh:solana:<genesis-base58>:<address-base58>`), extract the
base58 address with network='solana'. Mirrors the existing EVM branch.

Why anticipatory: `@solana/mpp/client` does not currently set
`Credential.source` when serializing a `solana/charge` credential, even
though the mppx Tempo plugin does set `did:pkh:eip155:...` for tempo. So
this matcher is dead code today; it activates as soon as upstream sets
source, or as soon as a merchant/client adds source themselves.

Without this matcher, Solana MPP settles produce `capturedSigner=null`,
which silently skips `captureWallet` (no operator-wallet link forms on
Solana) and weakens wallet-auth signer-match enforcement vs the EVM rails.

Test: tests/signer.test.ts now covers the Solana DID happy path; existing
EVM-DID and non-DID null cases stand.
…l mode)

Closes the wallet-signer-match gap on Solana MPP `solana/charge`. When the
mppx credential's `source` field is unset (current `@solana/mpp/client`
behavior), fall back to decoding the credential's signed-tx payload and
read the SPL `TransferChecked` authority field. The authority is the
source-ATA owner, which is the buyer's wallet.

Pull mode only (`payload.type === 'transaction'`). Push mode
(`payload.type === 'signature'`) returns null because recovery would
require an RPC fetch by signature; pay uses pull mode by default and
no consumer in the stack opts into push today.

Why this matters: without signer recovery, the gate's wallet-auth check
on Solana could not enforce that the claimed `X-Wallet-Address` matches
who actually paid. An agent claiming a KYC'd wallet could pay with an
unverified one. Now the recovered Solana base58 address feeds
`verifyWalletSignerMatch` the same way the EVM EIP-3009 `from` does, so
operator-equivalence enforcement is uniform across rails.

Implementation:
- `@solana/kit` is dynamic-imported, matching the existing `mppx` pattern;
  optional peer dep already declared in package.json (>=6.5.0).
- Walks instructions for SPL Token Program or Token-2022 with the
  `TransferChecked` discriminator (12), then reads `accountIndices[3]`
  (authority slot) and looks it up in `staticAccounts`.
- Failure paths (missing peer dep, malformed tx, no TransferChecked,
  push-mode payload) all return null cleanly so the existing fall-through
  to x402 EVM still works.

Tests: 660 passing (up from 658). New cases:
- pull-mode Solana credential with TransferChecked → returns
  { address: <base58>, network: 'solana' }
- push-mode Solana credential (`type: 'signature'`) → returns null
…doc updates

Two issues from the round-5 review:

1. Account-index overflow on v0 transactions with address lookup tables.
   Solana v0 txs can carry instruction account indices that resolve via
   lookup tables; staticAccounts only holds the static set. If
   `accountIndices[3]` (TransferChecked authority) points outside
   staticAccounts, the previous code returned the wrong address (or
   `undefined`) silently. Now: bounds-check, log a warning, skip cleanly.
   The `@solana/mpp/client` builder uses static accounts only for fresh
   SPL transfers, so this is defensive against future tx shapes rather
   than a current-day bug.

2. Multi-recipient `splits` clarification. The loop returns the FIRST
   matched TransferChecked authority. For splits, the buyer signs ONE
   tx with N TransferChecked instructions all sharing the same authority
   (their wallet), so first-match is correct. Added a comment to make
   the assumption explicit so a future maintainer doesn't read the loop
   as buggy.

Doc updates pulling the Solana signer-recovery work into the canonical
descriptions:
- README.md `extractPaymentSigner` snippet now mentions x402 EVM, Tempo
  MPP, and Solana MPP (DID-or-tx-decode) coverage.
- CLAUDE.md wallet-signer-match paragraph spells out the three recovery
  paths and the optional `@solana/kit` peer dep.
…able, throw)

Three new tests for `extractSolanaSignerFromCredential`:

1. `@solana/kit` peer dep stub missing required exports →
   getBase64Codec/getTransactionDecoder/getCompiledTransactionMessageDecoder
   undefined; returns null without throwing.
2. SPL TransferChecked authority resolves through an address lookup
   table (accountIndices[3] >= staticAccounts.length); skips with a
   warning log instead of returning a wrong address.
3. @solana/kit decoder throws on malformed tx bytes; outer try/catch
   catches and logs, returns null cleanly.

Closes the branch-coverage gap that was blocking PR CI (89.95% → 90.1%,
above the 90% threshold).
…9.1 → 8.59.2

Within-semver patch bumps. eslint 9 → 10 + @eslint/js 9 → 10 are
available but held back as a separate major-bump decision (eslint 10
removed several deprecated APIs and changed the rule meta-format; needs
its own validation pass).

Tests: 663 vitest passing, lint + typecheck clean.
@vvillait88 vvillait88 merged commit ea867b3 into main May 5, 2026
6 checks passed
@vvillait88 vvillait88 deleted the feat/x402-settle-facilitator-error branch May 5, 2026 08:41
vvillait88 added a commit to agentscore/pay that referenced this pull request May 5, 2026
## Summary

Pairs with agentscore/node-commerce#8 + agentscore/python-commerce#7 +
agentscore/martin-estate#56.

\`--chain solana\` no longer registers \`@x402/svm\`'s
\`ExactSvmScheme\`. It now registers \`@solana/mpp/client\`'s \`charge\`
method on \`Mppx\` and pays via MPP \`solana/charge\`. Reason:
\`@x402/svm\`'s tx-builder omits the idempotent
\`createAssociatedTokenAccount\` instruction, so SPL transfers fail
against any payTo whose USDC ATA isn't pre-warmed (every
Stripe-multichain rotating deposit address). Upstream won't fix this per
x402-foundation/x402#1020 (rent-drain attack vector).

## Changes

- Drop \`@x402/svm\` dep
- Add \`@solana/mpp\` client peer dep
- \`wallet.chain === 'solana'\` now goes through \`payViaMpp\` (was
\`payViaX402\`)
- \`payViaMpp\` registers \`solanaCharge({signer, rpcUrl})\` for Solana
wallets, \`tempo({account})\` for Tempo
- \`Protocol\` is \`'x402'\` for base, \`'mpp'\` for Solana + Tempo
- \`payViaX402\` throws \`unsupported_rail\` for non-base chains
- Everything else unchanged (passport attach, \`--max-spend\`,
idempotency, retries, dry-run)

Agent UX is identical: \`agentscore-pay pay POST <url> --chain solana
...\` continues to work; pay handles the protocol switch transparently.

## Test plan

- [x] 352 tests pass (vitest)
- [x] Local dry-run shows \`protocol: mpp\` for \`--chain solana\`
- [x] Local live-run reaches simulate against martin-estate (broadcast
deferred on devnet RPC reliability)
- [ ] On-chain settle smoke (mainnet or alternate devnet RPC)
- [ ] Coordinate release with martin-estate#56 deploy + new
\`@agent-score/pay\` rc tag

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vvillait88 added a commit to agentscore/python-commerce that referenced this pull request May 5, 2026
…fy+extra_warnings + x402scan discovery (#7)

## 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant