What your agent platform must present for the gate to verify an
agent_payment. Distilled from the pinned specification
(google-agentic-commerce/AP2, tag v0.2.0 = commit
b4587ac1d055888a73b4b21750973cffba961793) and the wire-format notes in the FARIGATE
repository (docs/adr/ADR-003-ap2-spec-pin.md,
core/crates/farigate-mandate/spec/WIRE-NOTES.md).
Claim discipline. FARIGATE implements the AP2 v0.2.0 mandate profile as published at that tag — nothing here claims AP2 certification or Google/FIDO endorsement. AP2 has been contributed to the FIDO Alliance; re-evaluate when v0.3 appears.
AP2 v0.1 press described Intent/Cart/Payment mandates as W3C Verifiable Credentials. v0.2 is different and is what the gate enforces:
open or closed, identified by
an SD-JWT vct claim: mandate.checkout.1,
mandate.checkout.open.1, mandate.payment.1,
mandate.payment.open.1. Unknown vct values are
rejected.cnf; delegation chains follow
draft-gco-oauth-delegate-sd-jwt-00 with the
~~ segment delimiter.*.open.1 mandates and the
cnf-bound agent key signs the closed mandates derived from
them. The gate derives presence from chain shape and the pack records
it.checkout_hash =
b64url(sha-256(checkout_jwt)) and the payment mandate's
transaction_id must equal it.4999 + USD = $49.99).| Check | Detail |
|---|---|
| SD-JWT signatures | ES256 over each hop; root key from your registered user trust (P-256 JWK), later hops from the previous hop's verified cnf.jwk. |
| Disclosure digests | Hashes of the exact wire bytes of each disclosure; unreferenced disclosures and unmatched digests are rejected outright (stricter than the reference SDK, which drops them silently). |
| Chain binding | sd_hash/issuer_jwt_hash over the previous segment's exact bytes; typ whitelist per hop; terminal hops must not carry cnf, intermediate hops must. |
| Time validity | iat/exp on every hop and inside every resolved delegate payload, with 300 s skew, evaluated at decision time — and re-evaluated at the SAME recorded time by offline verifiers later. |
| Checkout/payment linkage | transaction_id == checkout_hash, recomputed from checkout_jwt. |
| Constraints | Allowed merchants/payees, amount ranges, execution-date windows. FARIGATE is deliberately stricter than the SDK: a missing execution_date is derived as the decision date (immediate execution) and still checked — never skipped. |
| Replay fields | expected_aud / nonces are enforced on terminal hops when supplied; when a presentation carries none (e.g. the frozen demo vectors), the pack records those checks as skipped — never as passed. |
The agent_payment context of the gate
request:
{
"action_type": "agent_payment",
"action_digest": "sha256:<canonical digest over the agent_payment context>",
"agent_payment": {
"checkout_mandate": "<SD-JWT or ~~-joined chain>",
"payment_mandate": "<SD-JWT or ~~-joined chain>",
"expected_aud": "did:ap2:...", // optional, recommended
"checkout_nonce": "...", // optional, recommended
"payment_nonce": "..." // optional, recommended
},
...
}
ap2 Python
package at the pinned tag) or an implementation that matches its wire
format exactly. The doc-embedded example tokens in the spec carry
transcription drift — round-trip through the SDK instead.~ included for sd_hash).deploy/cloud/mandate-trust/ in the bundle; the demo
vector keys are seeded there by default and should be replaced for a
real integration).action_digest is the canonical digest over the exact
agent_payment context; the gate re-derives and enforces
it, so any drift between what the agent signed and what you submit is
rejected upstream.
Open-mandate constraints that need cross-presentation state
(payment.budget, payment.agent_recurrence) are
recorded in the evidence pack; gate-side stateful enforcement is on the
roadmap (Phase 7) and not part of FARIGATE Cloud v0. The pack states what
was and was not enforced.