Skip to content

pull in latest upstream - #2

Open
TtheBC01 wants to merge 825 commits into
1Shot-API:mainfrom
x402-foundation:main
Open

pull in latest upstream#2
TtheBC01 wants to merge 825 commits into
1Shot-API:mainfrom
x402-foundation:main

Conversation

@TtheBC01

Copy link
Copy Markdown

Description

Tests

Checklist

  • I have formatted and linted my code
  • All new and existing tests pass
  • My commits are signed (required for merge) -- you may need to rebase if you initially pushed unsigned commits
  • I added a changelog fragment for user-facing changes (docs-only changes can skip)

phdargen and others added 18 commits May 12, 2026 16:45
* add batch-settlement blog post

* add img
* Create TSC.md

Create TSC.md outlining the technical steering committee members as outlined by the x402 foundation charter.

* Fix spelling

---------

Co-authored-by: Erik <erikreppel@gmail.com>
* Add escrow scheme specification

Introduces the `escrow` scheme for x402, built on Base's Commerce Payments
Protocol. Supports two settlement paths: authorize (funds held in escrow)
and charge (direct to receiver), both refundable post-settlement.

Refs: #834, #1011

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address review feedback on escrow scheme specs

- Generalize scheme_escrow.md to be network-agnostic
- Tighten verification: strict amount equality, tokenCollector
  recipient check, settlement simulation
- Add error codes section and assetTransferMethod note
- Simplify nonce derivation explanation

* Rename scheme to commerce and align spec with implementation

- Rename escrow → commerce per reviewer feedback
- Add expiry fields to PaymentRequirements example
- Align expiry field descriptions and example values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* spec: rename escrow/commerce scheme to authCapture, add EVM payload schema

Renames the scheme directory from commerce/ to authCapture/ and rewrites
the EVM spec to cover both ERC-3009 and Permit2 payment-collector paths.

Key spec additions:
- extra field schema (captureAuthorizer, captureDeadline, refundDeadline,
  feeRecipient, min/maxFeeBps, autoCapture, assetTransferMethod)
- Wire format + EIP-712 derivation tables for ERC-3009 and Permit2
- Spec -> on-chain PaymentInfo field mapping (preserves canonical Solidity
  names so EIP-712 typehash matches the AuthCaptureEscrow contract)
- Universal contract addresses block (CREATE2-deterministic)
- Verification step list aligned with facilitator implementation:
  preApprovalExpiry <= captureDeadline <= refundDeadline (>= allowed,
  matching contract _validatePayment)

* spec: use canonical base/commerce-payments addresses

Defer to the live deployment from base/commerce-payments@v1.0.0 instead
of redeploying via CREATE2. Drop the now-obsolete inline address tables
and salt-scheme paragraph; the Canonical Addresses annex now links to
the upstream release notes (and Uniswap deployments docs for Permit2),
matching scheme_exact_evm.md's third-party 'Canonical Permit2' annex
pattern.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…2278)

The Permit2 erc20-approval client was hardcoding 1_000_000_000 / 100_000_000
as gas fee fallbacks. TypeScript already exposes these as
DEFAULT_MAX_FEE_PER_GAS / DEFAULT_MAX_PRIORITY_FEE_PER_GAS in evm/constants;
add the matching Python constants and use them. No behavior change.

Also adds the first unit tests for sign_erc20_approval_transaction covering
the fallback and successful estimate paths.
* add --ignore-scripts

* update to pnpm 11 and node 22

* align dep

* fix axios headers

* pin workflow actions

* fix paywall

* remove cache from publishing

* add hedera publishing

* remove e2e workflow

* increase minminimumReleaseAge to 3days
* fix uv build

* exclude-newer = 3 days
…d fix two→three typo (#2044)

The exact-EVM scheme spec documented the extra object only by example,
leaving readers unable to tell which fields are required vs conditional
vs optional for each of the three asset transfer methods (eip3009,
permit2, erc7710). Per-method classification is authoritative in the
code but was not documented in the spec.

Adds three field-definition blocks (one per assetTransferMethod) after
each method's PAYMENT-SIGNATURE example, classifying:

  - extra.assetTransferMethod
  - extra.name
  - extra.version

Classification per method:

  - eip3009:   name and version are REQUIRED (needed for
               transferWithAuthorization signature construction).
  - permit2:   name and version are CONDITIONAL (required when the
               token supports EIP-2612 for gasless Permit2 approval).
  - erc7710:   name and version are OPTIONAL (not used by delegation-
               based transfers).

Also fixes a stale count: 'one of two asset transfer methods' →
'one of three', since erc7710 was added without updating the summary
sentence.

Pure documentation. No new fields. No code changes.
…D 181228) support with USDC.e (#2309)

Add USDC.e (Bridged USDC) as the default stablecoin for HPP mainnet
(chain ID 190415) and HPP Sepolia (chain ID 181228) across all three SDKs:

- TypeScript: DEFAULT_STABLECOINS map in @x402/evm + regenerated NETWORK_DECIMALS in @x402/paywall
- Go: ChainIDHPP / ChainIDHPPSepolia constants, NetworkConfigs entries
- Python: NETWORK_CONFIGS dict in x402.mechanisms.evm

Contract details (verified on-chain):
- Token: USDC.e (Bridged USDC, FiatTokenV2_2)
- Address: 0x401eCb1D350407f13ba348573E5630B83638E30D (identical on both networks)
- EIP-712 domain: name="Bridged USDC", version="2"
- Decimals: 6
- EIP-3009: transferWithAuthorization supported

Chain details:
- HPP is an Arbitrum Orbit L2 operated by the HPP team
- Mainnet (190415): https://mainnet.hpp.io | Explorer: https://explorer.hpp.io
- Sepolia (181228): https://sepolia.hpp.io | Explorer: https://sepolia-explorer.hpp.io
- Portal: https://portal.hpp.io

USDC.e is the official bridged USDC issued by HPP, submitted by the HPP chain
team (chain-endorsed asset per DEFAULT_ASSETS.md).
Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
* Fix: invoke lifecycle hooks in payment payload creation

* fix: invoke lifecycle hooks with correct context types in V1 and V2

* fix: suppress unhandled hook errors to satisfy errcheck linter

* fix: handle hook errors and recovery on payment creation failure
* spec: added reference spec

* feat: added x402BatchSettlement contract

* feat: added tests

* feat: mining 0x4020...0003 vanity & deploy to base sepolia

* feat: updaded spec/contract per recommendations

* feat: updated tests

* feat: update x402BatchSettlement

* feat: add peripheral contracts

* feat: updated spec

* feat: updated tests and deploy

* feat: removed extra.receiver from spec

* spec v1.2 (#44)

* feat: added 4th deposit; renamed others

* feat: updated tests

* feat: add collectors model

* feat: removed periphery contracts

* feat: rename cooperativeWithdraw to refund

* feat: added multicall to x402BatchSettlement for migration support

* feat: added multichannel & migration test scenarios

* feat: add deploy for peripery contracts

* feat: pr feedback

* feat: pr review feedback

* feat: update settlement tye from address to x402BatchSettlement

* feat: generate EIP3009 nonces from channelId & salt

* feat: removed DOS vector for withdrawals

* feat: deduplicate token/amount from permit2 call data

* feat: using ReentrancyGuardTransient over ReetrancyGuard for gas efficiency

* feat: added comment regarding unsupported tokens

* feat: added nonces to refund signature

* feat: updated CLAIM_BATCH_TYPEHASH to use full EIP-712 nested types

* feat: merge Permit2DepositCollector's into one contract

* feat: gate finalizeWithdraw to payer/payerAuthorizer

* feat: added partial refunds

* feat: updated spec

* fix: unit tests & format

* feat: revert settlement address from x402BatchSettlement to address type

* feat: pr feedback

* feat: pr feedback

* chore: format

* feat: deployed new contracts

* feat: final PR reviews + styling doc

* feat: pr feedback

* feat: re-mine salts

* fix: refunds could grief withdrawals

* fix: a signature replay attach with refund nonces

* fix: add balance check at initiateWithdraw time

* fix: removed duplicate code for type hash getters

* fix: avoid cross-chain channelId overlap

* feat: remine & redeploy contracts to testnet

* chore: move deposit events to after balance checks

* feat: add nonReentrant modifier to initiateWithdraw

* feat: add ChannelClosed event when balance returns to 0 with 0 claims

* doc: natspec note for getClaimBatchDigest called with empty array

* feat: added gas tests for x402BatchSettlement

* feat: removed unused caller param from IDepositCollector.collect

* feat: 100% test coverage for batch settlement across branches/functions/statemments/lines

* chore: removed batch settlement spec

* doc: document claim/finalizeWithdraw details and add x402-batch-settlement-implementers.md

* feat: fix Permit2DepositCollector typehash

* feat: documenting refund nonce behavior

* feat: remine & deploy batch settlement contracts

* chore: add audit reports

* feat: deployed to base, polygon, arbitrum, world and world-chain

* feat: removed old spec

---------

Co-authored-by: phdargen <pdargent@icloud.com>
* fix paywall regen for new chains

* changeset

* fix format

* fix paywall
* improve extension readmes

* Add extension hook adapters for client and HTTP flows

* Make SIWX extension self-register hooks

* changeset
phdargen and others added 30 commits July 22, 2026 15:34
* limit s array size

* go/py

* add changeset

* fix fmt
* Update docs/extensions/builder-code.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

* Update docs/extensions/builder-code.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

---------

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
* fix(python): preserve streaming bodies on payment retry

Buffer request content before the initial send so a 402 retry replays the same body.

* chore(python): use pull request number for changelog
* docs(svm): add `upto` SVM scheme specification

SVM profile of the network-agnostic `upto` scheme: a single-authorization
payment channel whose escrow deposit is the ceiling, settled at most once with
an operator-signed voucher. Companion to scheme_upto.md and scheme_upto_evm.md.

* docs(svm/upto): address review feedback on the upto spec

Squashed response to the review on #2697:

- Reframe the operator as "server/facilitator" and define it up front; a server
  can self-facilitate — nothing in the scheme requires a separate facilitator.
- Drop the `permit` profile and all EVM/Permit2 framing; `payment-channel` is the
  single v1 profile and the spec is single-mechanism throughout.
- Remove pay-kit attribution, the hardcoded program id, and "we control" — the
  channel program is identified via `extra.channelProgram`.
- Require `channel.authorizedSigner == operator` at verify and clarify the
  anti-grief / escape-hatch properties; correct channel-rent ownership (funded by
  and refunded to the payer; the operator sponsors only the transaction fee).
- Use USDC as the `asset` example; point multi-settlement to `batch-settlement`;
  remove the stray multi-delegator aside.

* docs(svm/upto): align with payment-channels program semantics

Addresses @notorious-d-e-v's program-grounded review:

1. Role model: the operator is the channel `payee` (the program requires the
   `settle_and_finalize` merchant == `channel.payee`), as well as the voucher
   `authorizedSigner`, fee payer, and `rentPayer`. The x402 `payTo` is realized
   as the payee (self-facilitating) or a program-enforced distribution split
   (separate facilitator) — so a third-party facilitator needs no program change.
2. Verifier pins `deposit == maxAmount` (was `≥`): `topUp` can raise an open
   channel's deposit, so equality is required to keep the ceiling enforced.
3. Time bounds are not client-bound: `expiresAt` is the operator's voucher value
   (on-chain enforced); `validAfter` is off-chain verify policy. The client signs
   only `open`.
4. `settle_and_finalize`/`finalize` only advance status; `distribute` is what
   moves funds (splits, payer refund, rent return) and closes the channel.
5. Zero-amount settlement uses the no-voucher path (`has_voucher = 0`) +
   `distribute`, since a `cumulative = 0` voucher is non-monotonic and invalid.

* docs(svm/upto): note the v1 reference is self-facilitating (operator == payTo)

The separate-facilitator model (payTo as a program-enforced distribution split)
is specified but not yet implemented; the reference rejects an open whose payTo
is not the operator. Matches the deposit==maxAmount + recipient guard added to
the implementation (PR #2694).

* docs: clarify upto svm channelProgram

* docs: remove upto svm decimals field

* docs: trim upto svm wire format text

* docs: explain upto svm channel id derivation

* docs: clarify upto svm settlement transaction

* docs: align upto svm asset transfer method

* docs: clarify upto svm open timing

* docs: document upto svm rent cleanup

* docs: document upto svm facilitator splits

* docs(svm): align upto spec with payment channels

* doc: channel discovery

* docs(svm): facilitator as zero-share payee for upto scheme

Set payee = extra.feePayer (zero-share) instead of receiverAuthorizer so
the rent sponsor gains a unilateral cleanup path: settle_and_seal with
has_voucher = 0, then distribute and reclaim. A client/server pair can no
longer strand the facilitator's rent by leaving channels open. Nonzero
settlement still requires the server voucher, and the distribution always
sends 100% to payTo, so the facilitator holds lifecycle authority but no
payment authority. Documents the residual trust: early close refunds the
unsettled remainder to the client, so servers must settle promptly.

* docs(svm): define upto open acceptance policy
…utside DEFAULT_STABLECOINS (#2924)

* fix and tests

* fix a slight permit2 regression

* Create batch-settlement-explicit-asset.md
…2462) (#2811)

* docs: add signed offers & receipts to seller quickstart, expand signer authorization guidance

* spec(offer-receipt): clarify signer authorization with attack vector and concrete mechanisms

* spec(offer-receipt): evaluate signer authorization as of issuedAt in §5.5
#2693)

Let the resource server embed a recent blockhash in the `exact` 402 challenge
so the client can build its payment transaction without its own RPC round-trip
and against a blockhash the settling RPC has already observed.

- utils: `resolveBlockhash(rpc, requirements)` — prefer `extra.recentBlockhash`
  (+ `extra.lastValidBlockHeight`) from the challenge, fall back to
  `getLatestBlockhash`. The `exact` client uses it instead of an unconditional
  RPC call.
- exact/server: `ExactSvmScheme` takes an optional `{ rpcUrl }`. When set,
  `enhancePaymentRequirements` fetches a fresh blockhash and emits
  `extra.recentBlockhash` + `extra.lastValidBlockHeight` alongside `feePayer`
  (best-effort — omitted on RPC failure so the client falls back). Threaded
  through `registerExactSvmScheme({ rpcUrl })`.
- spec: document the optional `extra.recentBlockhash` / `extra.lastValidBlockHeight`
  fields and the client's use of them in scheme_exact_svm.md.
* fix avm caip2

* update examples
* feat: add Solana support to cloudfront-lambda-edge example

Each route now offers both Base Sepolia and Solana Devnet payment
options via per-route accepts arrays; schemes are registered per
namespace (eip155:*/solana:*) so concrete networks come from config.
Updates the guides for dual-network setup, mainnet facilitators, and
the real v2 402 response shape.

* chore: update examples pnpm-lock for @x402 2.19 bump

* docs: keep facilitator guidance neutral, name Solana wallet examples

Revert the mainnet facilitator guidance to the neutral ecosystem-list
phrasing the example shipped with (no facilitator is singled out) and
name Phantom/Solflare as example Solana wallets alongside MetaMask.
…2849)

* specs(exact): add Starknet exact scheme for x402 v2 (spec-only)

Adds the `exact` payment scheme specification for Starknet (spec-only, PR 1 of the New Chains workflow). Mechanism: the client signs a SNIP-9 Outside Execution (SNIP-12 typed data) authorizing exactly one `transfer`; the facilitator submits it via `execute_from_outside_v2` with sponsored gas — the Starknet-native analog of EIP-3009. CAIP-2 networks, exact-amount transfer, on-chain SNIP-9 nonce replay protection, canonical typed-data reconstruction, mandatory settlement simulation, and receipt-confirmed settlement effect. Sponsored-only (extra.areFeesSponsored); unsponsored is a documented follow-up.

Constants verified against SNIP-9/12/6/29, the CAIP-2 registry, and Circle's docs. The reference implementation follows in a subsequent PR after spec approval. Drafted with AI assistance and human-reviewed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): clarify paymaster caller model and complete error codes

- extra.caller: in the paymaster flow the paymaster sets the OutsideExecution Caller to its forwarder; the client verifies rather than injects (resolves the field-note vs rule-4 inconsistency)
- add unexpected_verify_error / unexpected_settle_error to the error-code table
- tighten wording; demote the local signature-length cap from MUST to SHOULD

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* specs(exact): align simulation wording, tighten timeout bounds, transport-agnostic flow

- reconcile the index simulation bullet with rule 8: event-based criterion (exactly one asset Transfer), full call-tree simulation preferred with the documented transfer-only fallback; drop the incorrect 'plus fees'
- timeout mapping: freshness band at /verify (Execute Before within skewMargin of now + maxTimeoutSeconds); minimum remaining window at settlement re-verification
- strip HTTP header names from flow steps and section headings (transport-agnostic)
- define absent extra.areFeesSponsored (= sponsored); name the paymaster forwarder contract as the extra.caller value; restate the settlement receipt check with rule 8's exact criterion

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): use core v2 error vocabulary and response field names

- human-readable verify context travels in the core invalidMessage field (matches @x402/core VerifyResponse), not a scheme-invented detail field
- malformed PaymentRequirements are rejected with the dedicated core code invalid_payment_requirements, not invalid_payload
- reclassify unexpected_verify_error / unexpected_settle_error as standard core codes (were listed under Starknet-specific values)
- document settlement_pending's intentional non-empty transaction on success:false (pending is non-terminal; the hash enables on-chain reconciliation)
- drop the base64 mention from flow step 5 (transport detail, lives in the transport mapping appendix)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): close verification edge cases from adversarial review

- apply the minimum-remaining-window floor at /verify too (was settlement-only), closing the small-maxTimeoutSeconds edge where an expired payload could pass the freshness band
- require the step-4 receipt effect check before reporting a front-runner's consuming transaction as success (step 5)
- areFeesSponsored:false is a requirements defect: invalid_payment_requirements (missed in the previous pass)
- retention of a pending-nonce guard entry is explicitly REQUIRED; correct the idempotent-retry wording (duplicate_settlement while the guard holds)
- pin ambiguous error-code mappings (accepted-mismatch, account_not_deployed vs signature-revert)
- align flow step 3 and the index expiry bullet with the timeout band; anchor invalidMessage/errorMessage to the @x402/core types; tighten the settlement_pending row

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): tighten the Starknet index block to sibling length

Match the headline style of the SVM/Stellar/TON blocks in Critical Validation
Requirements: one invariant per bullet, details defer to scheme_exact_starknet.md
(calldata layout, simulation topology, settlement margins live there).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): repair settlement retry, define Transfer, client checks

Adversarial re-read of the previous two fix commits surfaced regressions and two deeper gaps; all verified against the text before fixing:

- step 5 now triggers on consumed-nonce at settlement re-verification too (the idempotent-retry promise previously routed through an unreachable step 5)
- step 5's rescue check is containment-scoped: a third party's consuming transaction may batch unrelated calls, and the receipt-global exactly-one criterion let a front-runner force paid-but-denied
- paymaster clients MUST verify the built message against their intent before signing (Caller alone was insufficient; the signature authorizes what the message says)
- define the Transfer event (selector + keyed/legacy layouts, fail closed on neither) for rule 8 and step 4
- restore index-bullet precision lost in the trim (conjunctive caller binding, settlement floor, payTo calldata)
- pin remaining unmapped error codes (REVERTED, missing balance getter, failed nonce call); expired row covers the both-phases floor; smaller wording fixes (guard framing, rule-4 trusted-config predicate, RPC deployment row, eviction skew, L1 latency honesty)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): single-home the pending-nonce tracking requirement

The pending-nonce tracking requirement had two normative homes (settlement step 4 and the Duplicate Settlement Mitigation closing paragraph). Single-home it in step 4; the mitigation section now cross-references instead of restating the MUST. Zero protection change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): align settlement retry, timeout, and sponsored-flag wording

Three consistency fixes surfaced by the implementation pass:
- step 5 also triggers on a post-eviction retry rejected with outside_execution_expired (matches the settlement re-verification path)
- name the freshness lower bound explicitly and note the upper bound still applies at settlement re-verification
- extra.areFeesSponsored is not matched between requirements and the accepted echo (absent is equivalent to true); each side is independently rejected if present and not true

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): fix step-4 retry wording and areFeesSponsored codes

Two consistency fixes from the final delta review:
- step 4: a post-eviction retry fails the minimum-remaining-window check (outside_execution_expired) before the nonce check; name that instead of the impossible finds-the-nonce-consumed mechanism
- rule 1: give the areFeesSponsored independent-rejection codes (invalid_payment_requirements server-side, invalid_payload for the accepted echo)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* specs(exact): define a single canonical payload path for Starknet

Address review feedback.

- Replace the optional `extra.caller` with a REQUIRED `extra.feePayer`,
  matching the wire naming used by SVM and other networks. Resource servers
  copy it verbatim from their facilitator's `/supported` entry.
- Collapse the paymaster-built vs direct construction fork into one path: the
  client always builds and signs the OutsideExecution itself from the
  PaymentRequirements alone, and never communicates with the facilitator
  directly. Whether the sponsor settles from its own account or routes through
  a forwarder/paymaster is facilitator-local and never touches the wire.
- Drop `extra.areFeesSponsored`; a required `feePayer` already implies it.
- Forbid the SNIP-9 ANY_CALLER sentinel as a `feePayer` value, so a
  caller-bound authorization cannot silently become a bearer one.
- Remove the HTTP header table; the scheme stays transport agnostic.
- Remove the USDC address table and describe `asset` generically via SNIP-2
  rather than ERC-20.
- State response-field requirements behaviourally instead of referring to
  `@x402/core` types.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…xample (#2876)

Adds service_name / tags to both RouteConfigs (parity with the TypeScript
advanced bazaar example) and documents the resource-block service metadata
and its indexer caps in the README. Without these fields a discovered
service is catalogued under its raw domain with no name, tags, or icon.
…ry) (#2941)

* docs: add NEAR x402 Facilitator to the facilitators table

* site: add NEAR x402 Facilitator ecosystem partner entry

* listing: drop ecosystem-page entry (page deprecated per maintainer)
The repo moved from coinbase/x402 to x402-foundation/x402; the console
guide's clone command still pointed at the old location.
* add facilitator faq

* minor fixes
)

HTTPFacilitatorClient's `createAuthHeaders` callback must return an object
keyed by facilitator path (`verify`/`settle`/`supported`). Returning a flat
headers object silently indexed to `undefined` and dropped auth on every
request, surfacing as an unexplained 401. Throw a clear error on the wrong
shape and document the expected shape.

Fixes #2762
…it rejection (#2974)

* fix: add request timeouts to HTTPFacilitatorClient and guard eager init rejection

verify(), settle(), and getSupported() previously called fetch() with no
deadline, so a facilitator that accepted a connection but never completed
the response hung the operation indefinitely — and, through the eagerly
created initPromise shared by the Hono/Express/Fastify/Next middlewares,
wedged every protected route until restart.

- Add FacilitatorConfig.timeoutMs (default 30s, matching the Go and
  Python facilitator clients), applied via a fresh AbortSignal.timeout()
  per HTTP attempt, covering response headers and body consumption.
- Reject with a typed FacilitatorTimeoutError (a FacilitatorResponseError
  subclass the middlewares already surface as 502) instead of a raw
  DOMException; settle() timeouts are documented as indeterminate.
- Attach a rejection handler to the eager initPromise in all four
  middlewares so an early init failure cannot become an unhandled
  rejection; the first protected request still observes it and retries.

Closes #2961

* fix: surface deadline aborts from error-body reads and validate timer-safe timeoutMs

Review follow-ups on #2974:

- getSupported() swallowed a deadline abort raised while reading a non-2xx
  error body, reporting it as a generic HTTP failure — which middleware
  surfaces as a 500 instead of the typed 502, and which the 429 path would
  even retry after the deadline had fired. Abort/timeout rejections from
  response.text() are now rethrown so the FacilitatorTimeoutError
  conversion applies; statusText remains the fallback for other body-read
  failures.
- timeoutMs now requires a positive safe integer of at most 2^31 - 1:
  AbortSignal.timeout() throws ERR_OUT_OF_RANGE on non-integers at request
  time, and larger values overflow Node's 32-bit timers into an effective
  ~1ms deadline while reporting the configured duration.
* fix enrichPaymentPayload

* same for go

* same for py
* fix(go/http): add Cache-Control: no-store to 402 responses

* add cache-control policy for payment HTTP responses

---------

Co-authored-by: Philippe d'Argent <pdargent@icloud.com>
* fix(ts/py): add cache control, no-store for 402, private for 200

* add changeset
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.