Repository navigation
Support parsed-chain secrets in x402 payments - #77
Conversation
…nywallet-module/src/service/mod Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…s,crates/tinywallet-module/src/ Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Extend the end-to-end lifecycle test with a Solana x402 challenge so the module must pick the matching secret from the additional secrets and report the parsed chain through the approval callback. The test host now answers getLatestBlockhash so the Solana path can be exercised. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Move the Solana challenge preparation and approval assertions later in the end-to-end test so the EVM payment flow is exercised first. The block is unchanged in content, only relocated to keep the chain coverage in a consistent order. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a test asserting that an x402 prepare-payment request carrying only the legacy secret field deserializes with empty additional secrets and round-trips back to the original JSON, guarding the extension against breaking existing payloads. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The Solana USDC mint used by the end-to-end signing test was wrong, so the fixture did not match the real token. It now uses the canonical mint address. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a task-local slot holding the host-provided secrets for module-selected x402 payment rails, scoped alongside the quote owner, and expose a helper that clones only the secret matching the chain chosen by the parsed challenge. The slot zeroizes every mnemonic and derivation path on drop, and the existing single-secret slot now zeroizes its derivation path too. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…es/tinywallet-module/src/servic Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Raise CONTRACT_VERSION to 1.12 to reflect the current wire contract, and update the compatibility test to expect the new minor version. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Document contract 1.12, which adds optional additional_secrets to the confidential X402PreparePayment request while preserving the prior JSON shape when it is omitted or empty. A test now covers rejection of duplicate secrets for the same chain. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret cloned for account derivation is now bound as mutable so it can be zeroized after use, while the secret passed into the signing request is no longer marked mutable since it is moved rather than wiped. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Moved the duplicate-chain validation and secret gathering out of the prepare-payment path into a take_request_secrets helper that also drains the secrets from the request. This keeps the secrets owned by the caller so they can be wiped on every exit path instead of being left behind in the request struct. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The legacy serialization test no longer asserts that additional_secrets is empty, since the round-trip equality check already covers the field. The secrets binding in the x402 runtime is now mutable so it can be consumed later in the request flow. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing (12)
✨ Finishing Touches
Comment |
Tiny Sweeper reviewTiny Sweeper completed its review; deterministic results follow. State: Incomplete Review snapshot
Completeness: Incomplete What changedContract 1.12 introduces optional `additional_secrets` on the confidential `X402PreparePayment` request (`crates/tinywallet-bus/src/wire/host.rs#pub struct X402PreparePaymentRequest`, `crates/tinywallet-bus/README.md#Contract 1.2 adds stateless ConstructEvmTransaction for native/ERC-20/contract`); the bus contract version advances to 1.12 with matching tests (`crates/tinywallet-bus/src/version/mod.rs#pub const CONTRACT_VERSION`, `crates/tinywallet-bus/src/lib_tests.rs#async fn assert_admission_is_held_through_durable_commit`). The module takes and wipes the request secrets, rejects duplicate per-chain secrets, and runs the x402 flow inside a task-local secret scope that selects the secret matching the parsed challenge chain (`crates/tinywallet-module/src/service/x402.rs#impl PaymentSigner for ModulePaymentSigner`, `crates/tinywallet-module/src/service/web3.rs#pub(crate) async fn with_execution_context<F: Future>`, `crates/tinywallet-module/src/service/web3.rs#pub(super) fn clone_secret() -> Result<SecretMaterial, String> {`). The signer now derives the expected chain from the payment chain and clones only the matching x402 secret. Secret wiping is extended to zeroize `derivation_path` alongside the mnemonic. FeaturesNone identified with supported citations. Tests
FindingsNo active actionable findings. Could not review: crates/tinywallet-bus/README.md, crates/tinywallet-bus/src/lib_tests.rs, crates/tinywallet-bus/src/wire/mod_tests.rs, crates/tinywallet-module/src/service/mod.rs, crates/tinywallet-module/src/service/web3.rs, crates/tinywallet-module/src/service/x402.rs, crates/tinywallet-module/src/service/x402_tests.rs, crates/tinywallet-module/tests/lifecycle_e2e.rs Before merge
How this fits togetherflowchart LR
n0["..._legacy_json_and_omits_unset_endpoint_url<br/>changed"]:::changed
n1["X402PreparePaymentRequest<br/>changed"]:::changed
n2["...ed_sender_and_preserves_default_recipient<br/>changed"]:::changed
n3["Wallet<br/>changed"]:::changed
n4["...erations_fail_closed_before_configuration<br/>changed"]:::changed
n5["X402Runtime<br/>changed"]:::changed
n6["...fore_authorization_and_released_on_cancel"]:::impacted
n7["lock"]:::impacted
n8["json"]:::impacted
n9["prepare"]:::impacted
n10["x402_prepare_payment"]:::impacted
n11["secret"]:::impacted
n0 -->|calls| n8
n0 -->|tests| n8
n2 -->|calls| n8
n2 -->|tests| n8
n3 -->|uses| n5
n4 -->|uses| n3
n4 -->|calls| n8
n4 -->|tests| n8
n6 -->|uses| n1
n6 -->|uses| n3
n6 -->|calls| n7
n6 -->|tests| n7
n6 -->|calls| n9
n6 -->|tests| n9
n6 -->|calls| n10
n6 -->|tests| n10
n6 -->|calls| n11
n6 -->|tests| n11
n9 -->|uses| n1
n10 -->|uses| n1
n10 -->|calls| n9
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
There was a problem hiding this comment.
tinysweeper found nothing blocking, but could not review everything, so this is not an approval: crates/tinywallet-bus/README.md, crates/tinywallet-bus/src/lib_tests.rs, crates/tinywallet-bus/src/wire/mod_tests.rs, crates/tinywallet-module/src/service/mod.rs, crates/tinywallet-module/src/service/web3.rs, crates/tinywallet-module/src/service/x402.rs, crates/tinywallet-module/src/service/x402_tests.rs, crates/tinywallet-module/tests/lifecycle_e2e.rs.
$0.0108 · 1,071,553 in / 102,114 out · 327,296 cached (31%) · ladder/vectors-oai3, deepseek-v4.1-flash · 764 embedded
critique: $0.0058 · 398,339 in / 37,214 out · 107,392 cached (27%) · deepseek-v4.1-flash
security: $0.0034 · 535,211 in / 42,280 out · 190,720 cached (36%) · deepseek-v4.1-flash
tests: $0.0010 · 78,823 in / 15,290 out · 24,576 cached (31%) · deepseek-v4.1-flash
description: $0.0003 · 47,919 in / 4,598 out · 4,608 cached (10%) · deepseek-v4.1-flash
Summary
x402 can now authorize and sign a payment on the chain selected by the parsed payment challenge, even when the wallet’s primary secret is for another chain. The request adds an optional list of additional chain secrets; an empty or omitted list keeps the prior serialized JSON unchanged, and the TinyBus method arity is unchanged. The bus contract version advances to 1.12.
The module rejects duplicate secrets for one chain, selects the secret only after parsing the payment rail, and zeroizes supplied and scoped secret material on error and completion. Existing admission, approval, and signing behavior remains in the module.
API and compatibility
Public wire change: additive
additional_secrets, defaulting to empty and omitted during serialization when empty. Existing requests deserialize and serialize to the same JSON. No TinyBus member arity changed.Validation
cargo +stable test --locked --all-featurespassed.cargo +stable build --locked --all-targets --all-featurespassed.cargo +stable clippy --locked --all-targets --all-features -- -D warningspassed.cargo +stable fmt --all -- --checkandgit diff --checkpassed.Detailed local logs are retained in the owner worktree under
.migration-validation/.