Skip to content

fix(samples): consume accepted Payment Mandates atomically - #347

Open
FutureEnterprises wants to merge 4 commits into
google-agentic-commerce:mainfrom
FutureEnterprises:fix/consume-accepted-mandates
Open

fix(samples): consume accepted Payment Mandates atomically#347
FutureEnterprises wants to merge 4 commits into
google-agentic-commerce:mainfrom
FutureEnterprises:fix/consume-accepted-mandates

Conversation

@FutureEnterprises

@FutureEnterprises FutureEnterprises commented Sep 2, 2026

Copy link
Copy Markdown

Partially addresses #346.

This keeps the change within this repository's samples and SDK contribution scope. It hardens the Python MCP reference samples at the two boundaries that create a payment credential or receipt:

  • The Credential Provider reserves the hash of the accepted closed Payment Mandate before creating a token.
  • The Merchant Payment Processor reserves the Checkout transaction ID before creating a receipt.
  • A shared SQLite helper uses an immediate transaction and a unique key so concurrent threads and processes have one winner.
  • Corrupt, unreadable, or busy replay state fails closed with replay_state_unavailable; a repeat returns mandate_already_used.
  • Existing token-store references are checked so moving to the reservation database does not permit one legacy replay.

Tests cover sequential replay, eight-way thread and process races, restart persistence, legacy state, corrupt and unreadable state, and lock timeout. The focused suite passes 15/15. Compilation, Ruff, CSpell, and diff checks pass.

This is a durable single-host reference result, not a distributed-store or production-payment claim. The reservation database and the sample's legacy JSON token store are not one cross-file transaction. A credential-store failure therefore leaves the mandate consumed, which is the safer failure direction but may require operator recovery.

No normative specification text is changed here. The AP2 specification has moved to FIDO. The Go sample and nonce provenance are also outside this pull request.

…dy_used)

The specification's only mandatory double-spend control is a MUST on the
Shopping Agent, which the same document names as a potential attacker; the
Credential Provider, Network and MPP have a MAY. No closed-mandate field
changes between presentations and the Key Binding nonce is chosen by the
Shopping Agent, so the reference Credential Provider issues a new token for a
closed Payment Mandate it has already accepted, and the MPP mints a receipt
for a token it has already paid.

- specification.md: CP/Network MUST record the hash of each accepted closed
  Payment Mandate (the receipt reference) and reject repeats; MPP MUST record
  transaction_id before initiating payment and reject repeats
- security_and_privacy_considerations.md: Double Spend verifier bullet MAY -> MUST
- agent_authorization.md: new terminal error mandate_already_used
- credentials_provider_mcp: refuse an already-accepted mandate (by reference)
- merchant_payment_processor_mcp: consume transaction_id before minting a receipt
@FutureEnterprises
FutureEnterprises requested a review from a team as a code owner September 2, 2026 03:13
@google-cla

google-cla Bot commented Sep 2, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@FutureEnterprises FutureEnterprises changed the title Require verifiers to consume accepted Payment Mandates (mandate_already_used) fix: require verifiers to consume accepted Payment Mandates (mandate_already_used) Sep 2, 2026
@FutureEnterprises FutureEnterprises changed the title fix: require verifiers to consume accepted Payment Mandates (mandate_already_used) fix(samples): consume accepted Payment Mandates atomically Sep 3, 2026
@FutureEnterprises

FutureEnterprises commented Sep 3, 2026

Copy link
Copy Markdown
Author

Quick CI update: the corrected sample-only head is 1a816ab83e15e78b61bb1f4ae37a850a18f90d2a. The focused suite passes 15/15, and CLA, title, spelling, and change detection are green.

The remaining Lint Code Base failure does not involve any of the six changed paths. This workflow excludes code/samples/**, but Super-Linter documents that Biome ignores FILTER_REGEX_EXCLUDE and VALIDATE_ALL_CODEBASE and always checks the entire workspace. The run reports 75 errors in 80 existing web-client/docs files: https://github.com/super-linter/super-linter/blob/v8.7.0/README.md#tools-that-always-check-the-entire-workspace

There is already a dedicated workflow fix in #310 that sets VALIDATE_BIOME_LINT: false, and its lint job is green. Could a maintainer merge that workflow fix or waive this check for the sample-only PR? I removed the normative documentation edits and kept this fix entirely within the repository's samples/SDK contribution scope.

super-linter enables both Biome and ESLint for JS/TS and warns they conflict.
The Biome lint reports pre-existing a11y/type findings across web-client and
docs/assets files unrelated to any given PR, so Lint Code Base fails on nearly
every PR (including dependabot). Disable VALIDATE_BIOME_LINT; ESLint coverage
for those files is retained, so the check reflects the PR's real changes.

Editing this workflow can activate the GitHub Actions zizmor audit, so also
make the workflow pass it cleanly:

* pin actions/checkout and super-linter to commit SHAs (unpinned-uses, High)
* add an explicit minimal permissions block (excessive-permissions, Medium)
* set persist-credentials: false on checkout (artipacked, Medium)

zizmor reports no findings on this workflow under the default persona.

Signed-off-by: AlgoVoi <chopmob@gmail.com>
(cherry picked from commit 76a9464)
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.

2 participants