Repository navigation
wallet receive --token-file/stdin; document trade CLI build by manifest path - #1127
Merged
Merged
Conversation
…est path
- maxplayer wallet receive accepts --token-file <path>, or the token on stdin
('-' or no argument); the positional token still works. Argument+file is
refused, input is trimmed, errors never contain the token.
- maxplayer-mint docs use --token-file instead of "$(cat ...)" on argv.
- maxplayer-trade README/skill: cargo build -p maxplayer-trade fails from the
root (own workspace); give the --manifest-path release build and note protoc
is only needed for tests/examples.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…very defers
- report.rs renders every send (id, mint, amount, fee, state, reclaimed,
reclaim fee/state); non-terminal and manual-recovery sends are UNRESOLVED
and counted in the summary (a stuck prepared send printed 'UNRESOLVED: none').
- receive/send/money/coordinator recovery: 'recovery deferred (<reason>)' with
'timeout after Ns' or the {:#} error chain, tokens and 32+ hex runs redacted.
- tests: status send rendering vs status --json counts; recover receive deferral
reason is secret-free; redact_reason unit test. commands.md status wording.
…ile token reads; broader redaction wallet receive (maxplayer): - M1: no token -> USAGE_ERROR naming `--token-file <path>` and `-`; stdin only for explicit `-` (an open, never-closed stdin pipe can no longer hang the command). Usage line updated. - N1: `-` on a terminal prints "paste the token, then press Ctrl-D" and reads. - L1: token-file/stdin reads capped at 1 MiB (take(MAX+1)), refused without quoting content; non-regular --token-file (FIFO/device/dir) refused before open; non-UTF-8 refused. - L2: wallet errors redact the exact token, then cashuA/cashuB runs (any case, %-encoded) and 32+ hex runs (same logic as maxplayer_trade::redact_reason, duplicated minimally). - Test seam (cmd_receive_with) so receive_wallet_error_never_contains_the_token injects a token-echoing wallet error and bites when the redact call is removed. maxplayer-trade: - L3: case-insensitive cashuA/cashuB prefix, runs continue past `%`; byte scan (N4 alloc). Base64url-run redaction skipped (would eat npubs, mint URL paths and long ids). - L5: summary reads "N unresolved (M of them need manual recovery)"; exit codes unchanged. - send_line table test over every SendState; redact_reason unit cases (+/ alphabet, upper/mixed hex, token at end, %-encoding, truncation at 600). N4: tests below use super::*.
maxie-agent
marked this pull request as ready for review
October 12, 2026 18:01
maxie-agent
added a commit
that referenced
this pull request
Oct 12, 2026
# Conflicts: # crates/maxplayer-trade/tests/nostr.rs
maxie-agent
added a commit
that referenced
this pull request
Oct 12, 2026
# Conflicts: # crates/maxplayer-trade/src/dryrun.rs # crates/maxplayer-trade/src/money.rs
maxie-agent
added a commit
that referenced
this pull request
Oct 12, 2026
# Conflicts: # crates/maxplayer-trade/src/coordinator.rs # crates/maxplayer-trade/tests/nostr.rs
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two papercuts from the live trade test, plus two trade fixes from the live nostr:// test (items 3–4). Bob approved this on 2026-10-11 at 03:55 UTC.
1. Trade CLI build docs (docs only)
crates/maxplayer-tradeis its own Cargo workspace, socargo build -p maxplayer-tradefrom the repo root fails with exit 101:package ID specification `maxplayer-trade` did not match any packages. The README "Build and automated tests" section and the skill'sreferences/commands.mdnow give the build that works:Verified locally on this branch with
PROTOCunset:cargo install --locked --pathexits 0.--examplesfails in thecdk-signatorybuild script (Could not find protoc).PROTOCset.The docs now say protoc is needed only for tests and examples. No workspace restructuring. No website or docs page mentions building the trade CLI;
web/app/README.mdonly references its parser.2.
maxplayer wallet receive --token-file/ stdinmaxplayer wallet receive --token-file <path>, ormaxplayer wallet receive -to read the token from stdin. If you give no token at all, the command exitsUSAGE_ERRORwith a message naming--token-file <path>and-, the same as before this PR. Stdin is read only when-is given explicitly (review r1 M1). With-on a terminal, it printspaste the token, then press Ctrl-Dto stderr and then reads. The positional<token>still works for compatibility.-) together with--token-fileis refused as a usage error before the home is touched.--token-filethat is not a regular file (FIFO, device, directory) is refused before it is opened. Input is trimmed.redact_token. That removes the exact token, then anycashuA/cashuBrun (any case,%-encoded too) and any hex run of 32 or more characters.crates/maxplayer-mint/README.mdande2e/README.mdnow use--token-fileinstead of"$(cat …token)"on argv. No other docs or skills passed the token on argv.Scope notes (not widened): MCP has no receive tool;
wallet_receiveonly returns a "moved to the CLI" pointer. I did not audit the daemon or other CLI paths for token-on-argv.maxplayer-trade receivealready uses--token-fileor stdin.3.
maxplayer-trade statusnow lists sends (visibility bug)report.rs(#1125) never rendered send records (#1123), so a nostr send stuck inpreparedwith all 650 sats of inputs reserved printed "UNRESOLVED: none" and "0 unresolved"; onlystatus --jsonshowed it. Each send now gets one line: id, mint, state, amount, fee, reclaimed, reclaim fee and reclaim state (in flight/done/available until redeemed/manual recovery/ …).prepared/submitted/swapped/reclaiming) go under UNRESOLVED.inputs_spent,quarantined,reclaim_quarantined,reclaim_unresolved) are flaggedMANUAL RECOVERY, listed as unresolved, and counted like quarantined swaps and receives.commands.mdnow lists send among thestatusrecord kinds.Test
readable_status_lists_unresolved_and_settled_sends_with_json_matching_counts(tests/send.rs):prepared,submitted,reclaimingandinputs_spentsends appear under UNRESOLVED;sentandreclaimedappear as settled.status --json:4 unresolved (1 of them need manual recovery).Mutation check: deleting the send-rendering loop fails this test (exit 101).
4.
recoversays why an item was deferredThe receive, send, funding, withdrawal and swap recovery loops now print
recovery deferred (<reason>), where the reason is eithertimeout after Nsor the{:#}error chain. The outer "money recovery deferred" line now uses{:#}too.Every reason goes through
redact_reason, which replacescashuA…/cashuB…tokens and hex runs of 32+ characters (secrets, preimages, proofC, blinded messages, signatures) and caps the length at 600 characters. Short hex such as keyset ids and NUT codes stays readable.Tests:
recover_prints_redacted_deferral_reason_for_receive(tests/receive.rs): a submitted receive against a dead mint runs the realrecoverbinary, exits 3, prints a concrete reason, and stderr/stdout contain no token, proof secret or proofC.deferral_reason_names_timeout_and_redacts_secrets.Local gates
cargo test -p maxplayer --features acp,wallet --locked --bin maxplayer wallet_cli: 31 passed, 0 failed (7 new).cargo check -p maxplayer --no-default-features: ok.cargo fmt --check: clean.skill_commands_and_flags_match_binary_help: 1 passed.wallet_cli.rsas a whole isn't rustfmt-clean on main, so I didn't reformat the rest of the file.cargo clippy -p maxplayer --all-targets --no-deps -D warnings: 56 errors, none in new code. The onlywallet_cli.rshit is the existingcollapsible_ifincmd_balance. CI runs no clippy for this crate.cargo fmt --checkclean; clippy-D warningswith the CI allow-list exits 0 for both default andlab; default tests and--features lab(TRADE_LAB_SECONDS=1) tests all pass with--test-threads=1, 0 failures.Review round 1 (cashu-rust-dev, at fd954d6)
Changes are in
e722658cand405b2f71.wallet receivewith no token blocks on an open stdin pipeUSAGE_ERRORagain, and the message names--token-file <path>and`-`. Stdin is read only for an explicit-. Usage line:maxplayer wallet receive (--token-file <path> | -) …. Mint README wording updated to match.-on a TTY refusedpaste the token, then press Ctrl-Don stderr, then reads.take(1 MiB + 1). Over the cap gives… is larger than 1048576 bytes, without quoting content. A--token-filethat is not a regular file is refused before open. Non-UTF-8 input is refused without echoing bytes.redact_tokenreplaces the exact token first. It then removescashuA/cashuBruns (any case,%-encoded too) and hex runs of 32 or more characters. This duplicates the smallredact_reasonscan locally, becausemaxplayerdoes not depend onmaxplayer-tradeand I did not want to grow core for it.%/ base64url secrets%, so nothing after it leaks. Skipped: redacting 40+ char base64url runs. That rule would also eat npubs (63 chars),nostr://npub…mint URLs, URL path segments and other long ids that operators need to read. Non-hex NUT-00 secrets therefore stay uncovered (theoretical; no path quotes them). The mnemonic stays out of scope (no path). New unit cases:+/alphabet, uppercase and mixed-case hex, token at end of string, glued token,%-encoding, and 600-character truncation applied after redaction.sentsend with no token filerewrittenis#[serde(skip)](it is set only for this command), so no journaled field records whether the file was written. Fixing this needs a new field.N unresolved (M of them need manual recovery). Exit codes are unchanged.--token-file -/--token-file=PATHUSAGE_ERRORStringallocuse super::*;is back at the top ofmod tests. Both redactors scan bytes.Tests
receive_wallet_error_never_contains_the_tokennow injects a wallet error through a test seam (cmd_receive_with). The error echoes the whole token, a 20-character prefix of it and a 64-hex secret. The test asserts that all three are redacted on stderr. The old real-wallet path stays covered asreceive_real_wallet_error_for_a_malformed_token_omits_the_token.receive_without_a_token_is_a_usage_error_and_never_reads_stdin: TTY and pipe; stdin panics if anyone reads it; no home is created.receive_dash_on_a_terminal_hints_then_reads_and_refuses_empty_inputreceive_token_reads_are_capped_at_one_mib_without_quoting_content: over the cap, exactly at the cap, and non-UTF-8.receive_token_file_must_be_a_regular_file: a directory and/dev/null.redact_secret_runs_catches_token_and_secret_shapes_and_keeps_identifiersreport::tests::send_line_flags_every_state: a table over all 12SendStates giving the expected(unresolved, manual)flags. The expected values are written out in the table, not derived fromterminal()/manual_recovery(), and an exhaustivematchmakes a new state fail to compile until it is added.redact_reason_covers_prefix_variants_alphabets_case_and_truncation.Mutation checks (each mutant applied alone and then reverted; every one failed its named test):
([], None) => TokenSource::Stdin)receive_without_a_token…, at the stdin panicreceive_token_reads_are_capped…receive_token_file_must_be_a_regular_fileredact_tokencall removed)receive_wallet_error_never_contains_the_tokenreceive_dash_on_a_terminal…send_linerule!terminal() || manual→!terminal()send_line_flags_every_statecashuAprefixredact_reason_covers…%removed from the token runredact_reason_covers…Local gates at e722658 (
--test-threads=1, PROTOC set):cargo test -p maxplayer --locked: 218 passed, 0 failed (11 suites).--features labwithTRADE_LAB_SECONDS=1: 255 passed, 0 failed.cargo fmt --checkfor maxplayer-trade: clean. The touchedwallet_cli.rsregions are rustfmt-clean; the rest of the file was left unformatted, as before.-D warningswith the CI allow-list exits 0 for both default and lab.cargo clippy -p maxplayer --all-targets --no-deps -D warnings: 46 errors, all pre-existing and none inwallet_cli.rs. The root crate has nolabfeature; the--no-default-featuresvariant does not compile its test targets on this base either (checks/seller_nodegated). CI runs no clippy for the root crate.