feat(web3): compile-time web3 feature gate for wallet/web3/x402 (#4802)#4855
feat(web3): compile-time web3 feature gate for wallet/web3/x402 (#4802)#4855oxoxDev wants to merge 15 commits into
Conversation
…tinyhumansai#4802) Introduces the compile-time `web3` feature (default-ON, so the desktop build is byte-identical). Makes the exclusive `bitcoin` (BTC P2WPKH PSBT) and `curve25519-dalek` (Solana off-curve ATA) crates optional, dropped when the gate is off. Shared crypto crates (ethers-*, coins-bip39, bs58, ed25519-dalek, ripemd) stay always-on — Polymarket + tinyplace depend on them.
Keeps `pub mod wallet` always-compiled as a facade; real submodules move
behind `#[cfg(feature = "web3")]`. A `stub.rs` mirrors the always-on
caller surface (WALLET_NOT_CONFIGURED_MESSAGE, status, secret_material,
WalletChain, prepare_transfer/execute_prepared + param/result types,
solana_cluster/SolanaCluster, tinyplace_solana_rpc_endpoints,
tinyplace_signer_seed, rpc::{redact_rpc_url, with_tinyplace_solana_endpoints},
prepared_quotes_for_test, controller-registration entry points) with
disabled-error / empty bodies so tinyplace payments + Polymarket writes
degrade gracefully instead of failing to compile.
…ansai#4802) Real submodules gated behind `web3`; stub returns empty controllers, schemas, and agent tools when off (swap/bridge/dapp RPCs become unknown-method, the web3 agent tools are absent). No per-call-site cfg needed — the aggregator entry points return empty.
…nsai#4802) Real submodules gated behind `web3`; stub no-ops `init_ledger` and returns empty controller/schema lists when off. The X402RequestTool registration and the http_request 402-retry path are cfg-gated at their call sites (concrete gated types).
…ansai#4802) Concrete gated types can't be stubbed via return-empty, so the six Wallet*Tool + X402RequestTool registrations, the wallet::tools::* glob, and the http_request x402 402-retry path (+ its base64 import) are `#[cfg(feature = "web3")]` — mirroring the voice gate. With web3 off a 402 passes through unpaid. Polymarket's wallet-signing tests are gated too (they seed a real wallet); the tool itself compiles against the stub in both configs.
Adds the web3 gate-table row (drops bitcoin + curve25519-dalek) and a facade note: graceful tinyplace/Polymarket degradation, the shared crypto deps kept always-on, and the two caller families still needing per-call cfg.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughThe PR adds a default-enabled ChangesWeb3 feature gating
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7a9cddc1ee
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/openhuman/wallet/stub.rs (2)
93-165: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd diagnostics to the disabled-path error returns.
secret_material,prepare_transfer,execute_prepared, andtinyplace_signer_seedall returnErr(DISABLED_MSG)with no log statement, unlikestatus()at line 86. Per the repo's logging rule, these new/changed flows should log at entry/error so operators can grep why a tinyplace payment or Polymarket write silently degraded in a slim build.🔎 Example for one of the affected functions
pub(crate) async fn secret_material(_chain: WalletChain) -> Result<WalletSecretMaterial, String> { + log::debug!("[wallet-stub] secret_material requested (web3 disabled)"); Err(DISABLED_MSG.to_string()) }As per coding guidelines, "New or changed flows should include verbose, grep-friendly diagnostics covering entry/exit, branches, external calls, retries/timeouts, state transitions, and errors" and "Changes lacking logging are incomplete."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/openhuman/wallet/stub.rs` around lines 93 - 165, Add grep-friendly diagnostics to the disabled error paths in secret_material, prepare_transfer, execute_prepared, and tinyplace_signer_seed, matching the existing logging approach used by status(). Log the function entry or disabled-branch reason before returning DISABLED_MSG, while preserving each function’s current return behavior and avoiding changes to prepared_quotes_for_test.Source: Coding guidelines
1-256: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd unit tests for the stub's own behavior.
This new file has no
#[cfg(test)]module verifying, e.g., thatstatus()returns empty accounts,prepare_transfer/execute_prepared/secret_material/tinyplace_signer_seedreturn the disabled error, or thatprepared_quotes_for_test/tinyplace_solana_rpc_endpointsare empty.core/all_tests.rsonly checks registry-level emptiness, not these individual behaviors.As per coding guidelines, "Add tests for new or changed Rust behavior using inline
#[cfg(test)] mod testsor sibling*_tests.rsfiles."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/openhuman/wallet/stub.rs` around lines 1 - 256, Add an inline #[cfg(test)] mod tests to the stub module covering its disabled behavior: verify status returns an empty account list, prepare_transfer, execute_prepared, secret_material, and tinyplace_signer_seed return DISABLED_MSG, and prepared_quotes_for_test plus tinyplace_solana_rpc_endpoints return empty collections. Include the relevant Solana cluster behavior if needed to exercise the facade’s public contract, while keeping tests focused on these stub functions.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/openhuman/x402/mod.rs`:
- Around line 34-60: Add feature-off regression tests at
src/openhuman/x402/mod.rs lines 34-60 covering the disabled facade’s callable
no-op APIs and empty registration results; add a sibling test at
src/openhuman/tools/impl/network/polymarket.rs lines 1373-1381 verifying
wallet-dependent write operations return the expected disabled error. Keep the
tests gated for builds without the web3 feature and use the existing facade and
write-operation symbols.
---
Nitpick comments:
In `@src/openhuman/wallet/stub.rs`:
- Around line 93-165: Add grep-friendly diagnostics to the disabled error paths
in secret_material, prepare_transfer, execute_prepared, and
tinyplace_signer_seed, matching the existing logging approach used by status().
Log the function entry or disabled-branch reason before returning DISABLED_MSG,
while preserving each function’s current return behavior and avoiding changes to
prepared_quotes_for_test.
- Around line 1-256: Add an inline #[cfg(test)] mod tests to the stub module
covering its disabled behavior: verify status returns an empty account list,
prepare_transfer, execute_prepared, secret_material, and tinyplace_signer_seed
return DISABLED_MSG, and prepared_quotes_for_test plus
tinyplace_solana_rpc_endpoints return empty collections. Include the relevant
Solana cluster behavior if needed to exercise the facade’s public contract,
while keeping tests focused on these stub functions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1498bbf1-5352-49d9-9ac9-a884468a11c7
📒 Files selected for processing (13)
AGENTS.mdCargo.tomlsrc/core/all_tests.rssrc/openhuman/tools/impl/network/http_request.rssrc/openhuman/tools/impl/network/polymarket.rssrc/openhuman/tools/mod.rssrc/openhuman/tools/ops.rssrc/openhuman/wallet/mod.rssrc/openhuman/wallet/stub.rssrc/openhuman/web3/mod.rssrc/openhuman/web3/stub.rssrc/openhuman/x402/mod.rssrc/openhuman/x402/stub.rs
The Tauri host consumes `openhuman_core` with `default-features = false`, so gating the wallet/web3/x402 domains behind the default-ON `web3` feature would drop them + their agent tools from the shipped desktop app. Forward `features = ["web3"]` to keep the desktop build byte-identical. Safe — web3 is default-ON; this only restores the pre-gate desktop surface.
…tub (tinyhumansai#4802) Log entry on each disabled error path (secret_material, prepare_transfer, execute_prepared, tinyplace_signer_seed) so a slim build's degraded tinyplace/Polymarket flows are grep-visible, matching status(). Add a #[cfg(test)] module (compiled only when web3 is off) pinning the degraded contract: empty status, disabled errors, empty quote/endpoint lists, and empty controller registration.
…inyhumansai#4802) Pin the disabled facades' contract: empty controller/schema registration (and empty web3 agent-tool list) plus x402 init_ledger as a callable no-op, so a slim build's empty surface is locked in against drift.
…ff (tinyhumansai#4802) The signing happy-path tests require a real wallet and stay web3-gated; add a feature-off counterpart proving wallet-signed writes surface the wallet-stub disabled error (via secret_material) instead of panicking or proceeding without a signer.
|
Addressed the CodeRabbit nitpicks (both on
One deviation from the suggested diff: |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/openhuman/tools/impl/network/polymarket.rs`:
- Around line 1420-1422: Update the assertion in the disabled-wallet test to
require the stable marker “web3/wallet feature disabled at compile time”
exclusively, removing the broader “wallet secret material” alternative. Keep the
assertion’s failure message and surrounding test flow unchanged so it verifies
the intended stub path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c672ca58-2720-49fc-bd40-98cdfe8fc663
📒 Files selected for processing (5)
app/src-tauri/Cargo.tomlsrc/openhuman/tools/impl/network/polymarket.rssrc/openhuman/wallet/stub.rssrc/openhuman/web3/stub.rssrc/openhuman/x402/stub.rs
🚧 Files skipped from review as they are similar to previous changes (3)
- src/openhuman/x402/stub.rs
- src/openhuman/web3/stub.rs
- src/openhuman/wallet/stub.rs
…humansai#4802) The disabled-wallet test matched `"wallet secret material"` (from the `.context()` wrapper, present regardless of failure cause) OR the loose `"feature disabled"`. Require the stable stub marker `"web3/wallet feature disabled at compile time"` exclusively so the test proves the disabled-stub path specifically. Per CodeRabbit review.
|
Re @chatgpt-codex-connector's P1 "Forward web3 into the Tauri core dependency" — already addressed in current HEAD. openhuman_core = { path = "../..", package = "openhuman", default-features = false, features = ["web3"] }so the shipped desktop in-process core keeps the wallet/web3/x402 controllers (registered over Separate observation for a maintainer (out of scope for this PR, no change made here): that same Tauri dep forwards only |
|
To use Codex here, create a Codex account and connect to github. |
max_iteration_checkpoint_uses_deterministic_fallback_and_hooks fed the wrap-up call a non-empty response (tool-call XML text) plus a streamed delta, so summarize_turn_wrapup returned that text as the checkpoint and the deterministic fallback the test is named for never ran — the (1 steps) assertion failed under the FULL instrumented suite. Make the wrap-up yield nothing (empty text, no deltas) so build_deterministic_checkpoint is the answer, and assert no iteration-2 wrap-up delta is streamed. Pre-existing drift (checkpoint-selection predates tinyhumansai#4386); surfaced here because tinyhumansai#4802's Cargo.toml change forces the full coverage suite.
|
Maintainer fix pass (pushed CI — Fix ( Review feedback: none outstanding — |
🤖 Council Merge Gate — APPROVE (merge blocked by branch protection)The model council review gate returned APPROVE (session However, Action needed (human): resolve the failing required checks / obtain the required review, then merge. A maintainer with admin rights may also merge explicitly. The PR is left OPEN. Posted automatically by the |
🤖 Council Merge Gate — APPROVE (merge blocked by branch protection)The model council review gate returned APPROVE (session However, Action needed (human): resolve the failing required checks / obtain the required review, then merge. A maintainer with admin rights may also merge explicitly. The PR is left OPEN. Posted automatically by the |
…inyhumansai#4802) group_mapping_smoke asserted group_for_namespace("wallet") == Some(Web3) unconditionally. group_for_namespace resolves against the live controller registry, so with the web3 gate off the wallet controllers are unregistered and the lookup returns None, failing the test in the disabled config. The CI feature-gate-smoke lane only runs `cargo check`, which never compiles test code, so this could not surface there. Verified: `cargo test --lib --no-default-features --features tokenjuice-treesitter core::all::tests` no longer fails on the wallet assertion. The two remaining failures in that config assert the voice namespace and pre-date this branch (tinyhumansai#4803's gate); they are out of scope here.
Summary
web3feature (default-ON) that gates theopenhuman::wallet+openhuman::web3+openhuman::x402domains, composing with the runtimeDomainSet::Web3flag from feat(core): DomainSet on CoreBuilder + DomainRegistration filter seam (feature-gate prerequisite) #4796.--no-default-featureswithoutweb3) drops all three domains and their exclusive crypto depsbitcoin+curve25519-dalek.pub mod wallet/web3/x402stay always-compiled, real submodules are#[cfg(feature = "web3")], and each domain'sstub.rsre-exposes the always-on caller surface with disabled-error / empty bodies.Problem
#4795 wants one compile-time feature gate per subsystem family so slim harness builds drop code + deps; #4796 shipped the runtime
DomainSetaxis. This PR adds the compile-time half for the crypto/web3 family. Two scope realities the issue over-stated, confirmed by a full dependency + call-graph sweep:tokenjuiceunder web3 on the word "token", but it is the LLM-context compression engine (adapter over the vendoredtinyjuicecrate — detection / compressors / CCR cache / token estimates), already classifiedDomainGroup::Platform(always-on) insrc/core/all.rs. Itstokenjuice-treesitterCargo feature is a separate, unrelated default. Gating it under web3 would break LLM compression in every slim non-crypto build. Left untouched.ethers-core/ethers-signers/coins-bip39/bs58/ed25519-dalek/ripemdare shared with the Polymarket trading tools (tools/impl/network/polymarket*,clob_auth), tinyplace on-chain payments, and orchestration — so they stay always-on. Onlybitcoin(BTC P2WPKH PSBT) andcurve25519-dalek(Solana off-curve ATA) are exclusive to the gated modules and are dropped.The central constraint (from the issue owner): toggling the gate on or off must not break the core or the app. Always-on callers hard-depend on the wallet —
tinyplace/payment.rsuses the wallet's Solana signing (prepare_transfer,execute_prepared,tinyplace_signer_seed,SolanaCluster, …) andpolymarket.rsimportswallet::{secret_material, status, WalletChain}. Deleting the modules would break their compile; the stub facade is what keeps both builds compiling and degrades those paths to graceful "wallet disabled" errors at runtime.Solution
Cargo.toml: newweb3 = ["dep:bitcoin", "dep:curve25519-dalek"]feature added todefault; those two crates madeoptional(verified exclusive towallet/+x402/by call-graph grep).wallet/,web3/,x402/): real submodules + re-exports move behind#[cfg(feature = "web3")]; a#[cfg(not(feature = "web3"))] mod stub;mirrors the exact always-on caller surface with disabled-error /None/ empty-Vecbodies. Aggregator entry points (all_*_registered_controllers/all_*_controller_schemas/all_web3_agent_tools) return empty, socore/all.rs+tools/ops.rsneed no call-sitecfg.Wallet*Tool+X402RequestToolregistrations (tools/ops.rs) + thewallet::tools::*glob (tools/mod.rs), and the x402 402-retry path (tools/impl/network/http_request.rs) — with web3 off, a 402 passes through unpaid. Mirrors how the voice gate cfg's its concrete podcast tools.src/core/all_tests.rs):wallet_web3_x402_controllers_registered_when_feature_on(default) andwallet_web3_x402_controllers_absent_when_feature_off(disabled) assert the on/off registration behavior — the compile-time stub-facade correctness gate.rust-feature-gate-smokelane already builds--no-default-features --features tokenjuice-treesitter(every default gate off), so it now also compiles the web3-off path — no new step needed.AGENTS.mdgains aweb3gate-table row + a facade note.When off:
wallet/web3_*/x402RPCs become unknown-method (absent from/schema); the wallet + swap/bridge/dapp + x402 agent tools are absent; tinyplace on-chain payments + Polymarket writes return a graceful "wallet disabled" error (tinyplace comms + the core boot/serve path are unaffected);bitcoin+curve25519-dalekleave the build.Submission Checklist
#[cfg]attrs, aweb3feature, stub facades, docs).diff-coverreports no lines; the two registration tests cover the on/off behavior. CI coverage-gate authoritative. — Diff coverage ≥ 80%N/A: compile-time build-config change, no user-facing feature row## Related—N/A: no matrix rows affectedGGML_NATIVE=OFF cargo check(default, web3 ON) and--no-default-features --features tokenjuice-treesitter(web3 OFF) compile exit 0; both gate tests pass in their configs;cargo fmt --check+cargo clippy --libclean (0 new warnings, both configs).Closes #NNNin the## RelatedsectionImpact
web3on and is byte-identical.--no-default-features(withoutweb3) drops the wallet/web3/x402 domains + thebitcoin+curve25519-dalekdeps. tinyplace payments + Polymarket writes degrade to a graceful "wallet disabled" error; comms + core boot +/rpcare unaffected.Related
DomainSetseam. Follows the feat(core): feature gate — voice #4803 voice pathfinder (PR feat(core): compile-time voice feature gate (voice + audio_toolkit) (#4803) #4833) + the feat(core): feature gate — media generation #4804 media leaf gate (PR feat(core): compile-time media feature gate (media_generation + image) (#4804) #4840); this is the first gate that sheds real deps. Per-Tool/controller gating convergence follow-up: feat(core): converge tool gating with controller gating via per-Tool DomainGroup metadata #4821.AI Authored PR Metadata (required for Codex/Linear PRs)
Linear Issue
Commit & Branch
feat/4802-web3-feature-gate7a9cddc1ee2ba065b0eed49ae2d46d530a0ecd74Validation Run
pnpm --filter openhuman-app format:checkpnpm typecheckcore::all::tests::wallet_web3_x402_controllers_registered_when_feature_on(default, passed) +..::wallet_web3_x402_controllers_absent_when_feature_off(disabled build, passed)cargo fmt --checkclean · defaultGGML_NATIVE=OFF cargo checkexit 0 · disabledcargo check --no-default-features --features tokenjuice-treesitterexit 0 ·cargo clippy --lib0 new warnings in changed files (both configs)pnpm rust:checkon the shell passed)Validation Blocked
command:cargo test --lib(full)error:OOM on local machine (known)impact:full matrix runs in CI; locally scoped to the two web3 gate tests + default/disabledcargo check— all green in both feature configsBehavior Changes
web3compile-time gate; default unchangedbitcoin+curve25519-dalekdepsSummary by CodeRabbit
web3feature gate covering wallet support, Web3 controller/tool registration, and x402 capabilities.web3, and made related crypto dependencies load only whenweb3is enabled.web3is disabled.AGENTS.md.