fix(mcp-x402): API Market review blockers — ids comma bug + fabricated-200-on-failure - #164
Merged
Merged
Conversation
…d-200-on-failure
API Market's TESTER-plan review (8th rejection) flagged two real bugs on
/x402/crypto-price:
1. ids=bitcoin,ethereum silently merged into the single invalid id
"bitcoinethereum" -- cleanTerm() strips any non-[a-zA-Z0-9 .-] character,
including the comma delimiter, and ran on the raw string before it was
split. Fixed by splitting first, then sanitizing each id individually.
2. On full upstream failure it returned 200 with a fabricated stub value
and kept the payment ("payment kept" was literally in the code comment)
-- API Market only bills on 2xx, and this repo's own
AGENT_STANDARDS/SOVEREIGN_DATA_POLICY.md section 4 explicitly prohibits
fabricated fallback data and requires 502 on upstream error. Fixed to
return 502 and refund the sovereign-rail payment (matching the pattern
already used by every other endpoint in this file).
Audited the rest of the file for the same two bug classes since the
reviewer asked for all 82 endpoints to be clean before the next
submission:
- Found and fixed the identical fabricated-200-on-failure pattern on
/x402/crypto-trending, /x402/llm-chat, and /x402/chat/completions (the
latter two fabricated a fake assistant reply -- e.g. "ACK: <prompt>" --
and returned it as a real chat.completion object).
- Verified no other endpoint misuses cleanTerm() on a comma/list parameter
(18 other cleanTerm() call sites checked, all single free-text fields).
- Verified every endpoint declaring required input fields enforces them at
runtime before calling upstream (125 routes scanned).
- The /x402/firms 503 (SAM_API_KEY) is a genuine missing env var on the
Render deployment, not a code bug -- operator needs to set it.
Regression test: tests/unit/crypto-price-ids-parsing.test.ts, including a
marker test proving the old implementation actually produced
"bitcoinethereum" from "bitcoin,ethereum" (the exact failure reported).
151/151 tests pass, tsc --noEmit clean on index.ts, eslint clean (0
errors), scripts/check-sovereign-data.sh passes.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Timwal78
marked this pull request as ready for review
August 3, 2026 20:58
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
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.
Summary
API Market's TESTER-plan review rejected the ScriptMasterLabs x402 Data API listing for the 8th time, flagging two specific bugs on
/x402/crypto-price:ids=bitcoin,ethereumsilently merged intobitcoinethereum(a single invalid id). Root cause:cleanTerm()strips any character outside[a-zA-Z0-9 .-]— including the comma delimiter — and ran on the rawidsstring before it was split. Fixed by splitting first, then sanitizing each id individually to[a-z0-9-](CoinGecko's real id character set, e.g.usd-coin,matic-network).AGENT_STANDARDS/SOVEREIGN_DATA_POLICY.mdsection 4 explicitly prohibits fabricated fallback data and requires 502 on upstream error, no exceptions. Fixed to return 502 and refund the sovereign-rail payment, matching the pattern already used by every other endpoint in this file.Reviewer also asked for all 82 endpoints to be clean before the 9th submission, so I audited the whole file for the same two bug classes rather than patching only what was flagged:
/x402/crypto-trending,/x402/llm-chat, and/x402/chat/completions— the latter two fabricated a fake assistant reply (e.g."ACK: <prompt>") and returned it as a realchat.completionobject, which is worse than the price stub since a caller could reasonably act on it as real model output.cleanTerm()on a comma/list parameter — checked all 18 other call sites, all single free-text fields (drug names, tickers, UEIs, etc.), no bug./x402/firms's 503 is a genuine missingSAM_API_KEYenv var on the Render deployment, not a code bug — needs to be set there (free key at sam.gov) separately from this PR.Not touched:
/x402/web-fetch,/x402/domain-enrich, and the CoinCap/Binance intermediate fallback branches in crypto-price/crypto-trending — these return real (if partial) data on degraded paths, not fabricated stubs, so they're a legitimately different and acceptable case.Test plan
tests/unit/crypto-price-ids-parsing.test.ts— 6 tests, including a marker test proving the old implementation actually producedbitcoinethereumfrombitcoin,ethereum(the exact failure reported).npx vitest run tests/unit— 151/151 pass (145 pre-existing + 6 new), zero regressions.npx tsc --noEmit— clean onindex.ts(pre-existing unrelated errors insacred/store.ts/security/zyla.tsuntouched by this PR).npx eslint src/server/index.ts— 0 errors (17 pre-existing warnings, none on changed lines).bash scripts/check-sovereign-data.sh— passes.🤖 Generated with Claude Code
Generated by Claude Code