Skip to content

fix: resolve zero-settle rail_key and signer_network from the bound credential (2.5.2) - #82

Merged
vvillait88 merged 2 commits into
mainfrom
fix/zero-settle-rail-key
Jul 8, 2026
Merged

fix: resolve zero-settle rail_key and signer_network from the bound credential (2.5.2)#82
vvillait88 merged 2 commits into
mainfrom
fix/zero-settle-rail-key

Conversation

@vvillait88

Copy link
Copy Markdown
Contributor

What

Two fixes to the $0 zero-settle carve-out in Checkout, plus the 2.5.2 version bump and a dev-dep refresh.

rail_key resolves from the bound credential. No receipt is minted on the $0 path, so SettleOutcome.rail_key fell back to the primary MPP rail key and mislabeled Solana zero-settles as Tempo (and Tempo as Solana when rails were declared solana-first). zero_amount_carve_out already recovers the signer network from the credential's did:pkh source; the carve-out now maps it through _rails_key_for_mppx_method so rail_key reflects the rail that was actually bound. Downstream consumers that dispatch on rail_key (network_for_outcome, simulate_deposit_for_outcome) get the correct network as a result.

signer_network is no longer hardcoded. The MPP carve-out stamped signer_network="evm" whenever a signer was recovered, mislabeling Solana signers; both carve-out branches now surface the network the credential actually carries.

Dev deps: lefthook 2.1.10, uvicorn 0.51.0. ty is held at 0.0.56; 0.0.57 newly rejects starlette Headers against the HeadersLike protocol, to revisit on the next ty release.

Tests

  • Solana did:pkh credential resolves rail_key to the solana rail (not the tempo default) and signer_network to solana; Tempo credential resolves to the tempo rail even when solana is declared first; the existing opaque-credential test still covers the fallback.
  • Full suite: 1822 passed, coverage 95.47% (bar: 95%).

🤖 Generated with Claude Code

vvillait88 and others added 2 commits July 8, 2026 05:27
…redential

No receipt is minted on the $0 carve-out path, so rail_key fell back to the
primary MPP rail key and mislabeled Solana zero-settles as Tempo (and vice
versa when rails were declared solana-first). zero_amount_carve_out already
recovers the signer network from the credential's did:pkh source; map it
through _rails_key_for_mppx_method so SettleOutcome.rail_key reflects the
rail that was actually bound.

The MPP carve-out also hardcoded signer_network to evm, mislabeling Solana
signers; surface the carve-out's recovered network on both branches.

Bump to 2.5.2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lefthook 2.1.10, uvicorn 0.51.0. ty is held at 0.0.56: 0.0.57 newly rejects
starlette Headers against the HeadersLike protocol (aip/request.py), a
checker-side strictness change to revisit on the next ty release.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vvillait88
vvillait88 merged commit 3a06dd1 into main Jul 8, 2026
7 checks passed
@vvillait88
vvillait88 deleted the fix/zero-settle-rail-key branch July 8, 2026 12:38
vvillait88 added a commit that referenced this pull request Jul 17, 2026
…l 402 fix (#89)

In-range dependency upgrades (uv.lock only; no pyproject constraint
changes). fastapi, anyio, asgiref, solders, solana, stripe, sentry-sdk,
typer, httpx2/httpcore2, ruff, etc.

ty stays pinned at 0.0.56 (deliberate hold; newer ty adds churn-prone
diagnostics).

Verified locally: ruff check, ruff format --check, ty check (clean),
vulture, pytest (1834 passed, 95.49% coverage).

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

---

**Also unpins `ty`** (`==0.0.56` -> `>=0.0.32`) to match the rest of the
python fleet. ty 0.0.60 tightened protocol-assignability checking;
starlette 1.3.1 `Headers.get` no longer matched the `HeadersLike`
protocol, so `HeadersLike.get` is narrowed to its actual single-arg
usage (`get(key, /) -> str | None`). Full gate green at ty 0.0.60: ruff,
format, ty, vulture, pytest (1834 passed, 95.49%).

---

**Also: malformed-credential 402 fix (parity with node-commerce #82).**
Stripe/MPP-team store feedback: a junk or rejected payment credential on
POST /purchase returned 400, which x402/MPP clients abort on. Now
returns a 402 with a fresh challenge, both for the malformed-shape
pre-check (emit a fresh discovery 402, stripping the junk credential so
minting/compose take the fresh path; pre_validate + gate/assess stay
skipped) and the MPP compose-reject path (return the challenge pympp
already emitted as 402). x402 settle-verify failures (forged payTo)
still 400. Rides this 2.5.7 release (no extra bump). Gate green:
ruff/format/ty/vulture/pytest (1834 passed, 95.49%).

---------

Co-authored-by: Claude Opus 4.8 <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