Repository navigation
feat(cli): add --debug request tracing with credential redaction - #668
Conversation
`--debug`, or `NANSEN_DEBUG=1`, prints one line per HTTP request to stderr: method, URL, response status, latency in ms, retry decisions (attempt, reason, delay) and the server request id when the response carries one. stdout still carries only the JSON/CSV payload, so piped output stays machine-parseable. The trace never prints a credential. src/debug.js owns the single switch and a redact() pass that blanks values under any key naming a key, token, secret, signature, password or auth; strips inline Bearer/Payment credentials; blanks private-key, mnemonic, JWT and long opaque shapes wherever they appear; drops URL userinfo; and truncates long values. Header values are never traced at all and bodies are never traced. Request ids and public identifiers (addresses, chains) stay readable so the trace is worth having. The two x402 wallet-lookup notes that were keyed on a bare DEBUG env var now route through the same helper, so there is one switch, one output stream and one redaction pass instead of a parallel mechanism; DEBUG keeps working as an alias. Covers the shared API client: the main request loop (including cache hits, which report that no request was made) and the x402 paid retry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
pr-reviewer Summary for #f7db304📝 2 findings Review completed. Please address the findings below. Findings by Severity
Review effort: 4/5 (Complex) SummaryThis is a solid, well-considered feature. The Findings
|
`--debug` was documented as a global flag but was missing from VALUELESS_FLAGS, so `nansen --debug research token screener` consumed `research` as the flag's value: tracing stayed off and a different command was dispatched. Placing a global flag first is the natural way to type it, so this made the documented usage silently wrong. Also narrow the inline-credential pattern to `Bearer`/`Basic` and require the credential to be at least 8 characters. `Payment` and `Signature` are ordinary English words in traced text, and a real payment signature is already covered by header-name matching and the value-shape rules, so including them only garbled prose. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Both findings addressed in 8fba5e7.
|
|
Merge position: 8 of 9. Merge after #661, #662 and #666. Shares One live conflict to expect: #651 edits the same retry branch this PR's retry trace hooks into. The trace reports whatever that PR decides, so it is a context conflict rather than a behavioural one. |
# Conflicts: # src/api.js
|
@codex review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
|
@nansen-pr-reviewer re-review |
… review/pr-668-fixes
# Conflicts: # src/api.js
|
@nansen-pr-reviewer re-review |
Summary
Adds an opt-in request trace so auth, response timing, retry, and response-shape failures can be diagnosed without mixing diagnostics into command output.
--debug(a global flag) orNANSEN_DEBUG=1emits HTTP trace events to stderr. Events include method, sanitized URL, response status, time-to-response-headers (TTFB) in milliseconds, retry decisions (attempt, reason, delay), and the server request id when present. stdout remains JSON/CSV-only and safe to pipe:(All values above are examples.)
For
http.response,duration_msmeasures from the start of an attempt until response headers arrive (TTFB); it deliberately excludes downloading and parsing the response body. Forhttp.error, it measures elapsed time until the transport failed before headers arrived.Migration:
DEBUG=1no longer enables Nansen diagnostics. UseNANSEN_DEBUG=1(or--debug) instead.Redaction and output guarantees
apikey,Authorization, andPayment-Signature.[redacted].Coverage
The shared API client is traced end to end: every main request attempt, response, network failure, retry decision, x402 paid retry, and local cache hit. The AI-agent SSE stream, trading/bridge/limit-order transports, direct RPC calls, telemetry, and the background update check remain outside this PR because each uses a separate transport and error flow.
Changes
src/debug.js— opt-in switch (--debug/NANSEN_DEBUG), stderr writer, recursive redaction and bounding, URL/header sanitizers, andhttp.*helpers.src/api.js— request/response/error/retry/cache tracing for the shared API loop and x402 paid retry.src/cli.js— global--debugparsing and early trace activation, merged with currentmain's argument validation and--yessupport.src/privy.js,src/api.js— wallet-lookup diagnostics now use the shared trace helper.src/schema.json,README.md— global option and usage documentation..changeset/debug-request-tracing.md— minor release note.src/__tests__/debug.test.js,src/__tests__/api-debug-trace.test.js— redaction, bounding, switch, transport, retry, x402, cache, and CLI flag coverage.The branch includes a merge of current
main, including #669's CLI/help coverage and #667's trade/bridge--dry-runand--yesbehavior. The only merge conflict was the valueless-flag registry; the resolution retains both--debugand--yes.Validation
The previous full CI matrix passed on head
b1237de; the matrix will rerun for the timing-documentation commit. Local full-suite execution in the review sandbox is not reported as passing: the existing subprocess smoke test attempts the real API and times out under restricted networking, while the wallet/keychain guard does not terminate under the isolated temporary HOME. Focused tests covering this PR and the timing semantics pass as shown above.Checklist
npm run lintpassessrc/schema.jsondocuments the new global option