Summary
The TinyWallet module migration is, as far as I can measure, already complete — signing runs in the module, and the heavy gates (key, tx, client, asset, x402) are shed from the shipped build. What is missing is not more migration but a guard: the crate was silently de-vendored and inlined once before (3ee5a3cad), nothing would catch it happening again, and tinydocs is in exactly that state right now.
Problem / Context
First, the part that is done, recorded so nobody re-opens it as if it were incomplete. On 90dabbb5b the host takes:
tinywallet = { path = "vendor/tinywallet", default-features = false,
features = ["btc","evm","solana","tron","keccak","net","wire","eip712","abi","tx-codec"], optional = true }
against a crate whose default is ["btc","evm","solana","tron","keccak","net","key","asset","client","tx","x402","wire","eip712","abi"]. So key, asset, client, tx and x402 are already dropped. tx-codec rather than tx is the load-bearing choice: tx is the only thing that pulls bitcoin and its native secp256k1 C build, while tx-codec gives the verification half (recompute_txid, verify_contract, digest, attach_signature) with only sha2. OpenHuman signs through the module over k256, so it never links bitcoin.
The web3 gate now sheds 5 crates, down from 25 — the whole secp256k1 / elliptic-curve / coins-bip cohort left when signing moved in-module. What remains (bech32, keccak, ripemd, sha3, tinywallet) is the deliberate residue: the wire contract, address validation, and transaction verification. Per AGENTS.md, the host is supposed to keep "RPC endpoint resolution, transaction assembly and broadcast, key custody". The three production tinywallet::key::derive call sites are all behind #[cfg(test)], annotated "Test-only: production derives inside the wallet module."
So the risk here is regression, not incompleteness. On 2026-08-12, commit 3ee5a3cad ("refactor: run tiny domains as TinyBus modules") removed the vendor/tinywallet submodule and inlined ~3,700 lines of crate source into src/openhuman/web3/wallet/primitives/, rewriting every crate:: path and collapsing the crate's granular chain gates onto OpenHuman's single web3 gate. That was collateral damage from a larger change, not a decision — the Cargo.toml comments and AGENTS.md were left describing the crate-based design, so code and docs contradicted each other for a day.
That is not a cosmetic problem. An inlined copy of a shared crate is a silent fork. Four real fixes accrued in OpenHuman's copy that no other host ever saw, including a key-derivation bug where a SLIP-10 path segment already carrying the hardening bit was OR-ed with it again, so m/44'/501'/2147483648' and m/44'/501'/0' derived the same key. It was restored in #5533 / tinywallet#16 / tinywallet#17.
Nothing prevents a recurrence, and the same failure is live elsewhere today: tinydocs has no vendor/tinydocs directory, no .gitmodules entry and no dependency declaration, while four separate Cargo.toml comment blocks still describe it as one — including # After cloning: git submodule update --init vendor/tinydocs, an instruction that cannot work. Its spec types are inlined at src/openhuman/tools/impl/document/{types.rs, format/spec, format/error}.
Scope
In scope
- A CI guard asserting that every crate the manifest comments describe as vendored is actually a
.gitmodules submodule with a matching path dependency. The check is cheap and would have caught 3ee5a3cad on the PR that introduced it.
- Restore
tinydocs to a vendored submodule + default-features = false path dependency, matching what the comments already claim, and diff the inlined copy against upstream first so any fixes that accrued locally go upstream rather than being discarded.
- Confirm and document that TinyWallet's remaining host-side surface is intentional, so the residue is not mistaken for unfinished work.
Not in scope
- Moving verification into the module.
digest / attach_signature / signature_hex are deliberately on the codec side — exactly what a host doing its own k256 signing over a returned digest needs.
tinymemory — tracked separately, and genuinely incomplete.
Implementation note
Prefer verify_contract over verify_transfer at any new call site: the latter is a substring scan over the hex that a decoy field or a substituted amount defeats.
Acceptance criteria
Related
Summary
The TinyWallet module migration is, as far as I can measure, already complete — signing runs in the module, and the heavy gates (
key,tx,client,asset,x402) are shed from the shipped build. What is missing is not more migration but a guard: the crate was silently de-vendored and inlined once before (3ee5a3cad), nothing would catch it happening again, andtinydocsis in exactly that state right now.Problem / Context
First, the part that is done, recorded so nobody re-opens it as if it were incomplete. On
90dabbb5bthe host takes:against a crate whose
defaultis["btc","evm","solana","tron","keccak","net","key","asset","client","tx","x402","wire","eip712","abi"]. Sokey,asset,client,txandx402are already dropped.tx-codecrather thantxis the load-bearing choice:txis the only thing that pullsbitcoinand its native secp256k1 C build, whiletx-codecgives the verification half (recompute_txid,verify_contract,digest,attach_signature) with onlysha2. OpenHuman signs through the module overk256, so it never linksbitcoin.The
web3gate now sheds 5 crates, down from 25 — the whole secp256k1 / elliptic-curve / coins-bip cohort left when signing moved in-module. What remains (bech32,keccak,ripemd,sha3,tinywallet) is the deliberate residue: the wire contract, address validation, and transaction verification. PerAGENTS.md, the host is supposed to keep "RPC endpoint resolution, transaction assembly and broadcast, key custody". The three productiontinywallet::key::derivecall sites are all behind#[cfg(test)], annotated "Test-only: production derives inside the wallet module."So the risk here is regression, not incompleteness. On 2026-08-12, commit
3ee5a3cad("refactor: run tiny domains as TinyBus modules") removed thevendor/tinywalletsubmodule and inlined ~3,700 lines of crate source intosrc/openhuman/web3/wallet/primitives/, rewriting everycrate::path and collapsing the crate's granular chain gates onto OpenHuman's singleweb3gate. That was collateral damage from a larger change, not a decision — theCargo.tomlcomments andAGENTS.mdwere left describing the crate-based design, so code and docs contradicted each other for a day.That is not a cosmetic problem. An inlined copy of a shared crate is a silent fork. Four real fixes accrued in OpenHuman's copy that no other host ever saw, including a key-derivation bug where a SLIP-10 path segment already carrying the hardening bit was OR-ed with it again, so
m/44'/501'/2147483648'andm/44'/501'/0'derived the same key. It was restored in #5533 / tinywallet#16 / tinywallet#17.Nothing prevents a recurrence, and the same failure is live elsewhere today:
tinydocshas novendor/tinydocsdirectory, no.gitmodulesentry and no dependency declaration, while four separateCargo.tomlcomment blocks still describe it as one — including# After cloning: git submodule update --init vendor/tinydocs, an instruction that cannot work. Its spec types are inlined atsrc/openhuman/tools/impl/document/{types.rs, format/spec, format/error}.Scope
In scope
.gitmodulessubmodule with a matchingpathdependency. The check is cheap and would have caught3ee5a3cadon the PR that introduced it.tinydocsto a vendored submodule +default-features = falsepath dependency, matching what the comments already claim, and diff the inlined copy against upstream first so any fixes that accrued locally go upstream rather than being discarded.Not in scope
digest/attach_signature/signature_hexare deliberately on the codec side — exactly what a host doing its own k256 signing over a returned digest needs.tinymemory— tracked separately, and genuinely incomplete.Implementation note
Prefer
verify_contractoververify_transferat any new call site: the latter is a substring scan over the hex that a decoy field or a substituted amount defeats.Acceptance criteria
.gitmodulesor from the dependency list. Guard is proven by a red run against3ee5a3cad's shape.tinydocsre-vendored — submodule restored, taken withdefault-features = falsefor the wire contract, inlined sources undersrc/openhuman/tools/impl/document/deleted.tinydocscopy is diffed against the crate and any local fixes are landed in thetinydocsrepo before deletion.scripts/kernel-floor.shandscripts/assert-shed.shconfirm re-vendoring does not re-adddocx-rs/ppt-rs/pdf-extractor their tails to the product graph.AGENTS.mdstates which host-side surface is deliberate (wire contract, address validation,tx-codecverification, RPC resolution / broadcast / custody) so it is not re-litigated.Related
3ee5a3cad.AGENTS.md"Extracted host-agnostic crates" and "Loadable native modules".