fix(router): qualify BCK.ROUTER.0006 in the windsurf rules, and correct how the asset symbol is resolved - #305
Conversation
…ct how the asset symbol is resolved Two independent corrections, both true against nvm-monorepo main today — deliberately carrying no reference to any unreleased error code, so this can land on its own. 1. `.windsurf/rules/nevermined-router.md` wrote the retryable pair as bare `0006`/`0007` where its four sibling IDE rule files write `BCK.ROUTER.0006`. nvm-monorepo's `check-skill-error-drift` guard matches on the qualified form, so it has been reporting the code as undocumented — the ONLY drift between the published skill and `api-errors.ts` today, and it turns that check red on every nvm PR touching the error catalogue. 2. `products/router/rails-x402.mdx` said the asset symbol "is read from the entry's `extra.name` field". That is the pre-#2768 behaviour and has been false since nevermined-io/nvm-monorepo#2775: the symbol comes from the `asset` ADDRESS, matched against the canonical token addresses. The old text sends a reader debugging in exactly the wrong direction. Adds a short section on what `extra.name` actually is — the token's own EIP-712 domain, "USD Coin" on Base mainnet and "USDC" on Base Sepolia — since mistaking it for a ticker is what produced that bug. Split out of #304, which documents two error codes that do not exist until nvm-monorepo#2959 merges and therefore has to wait for it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
The two EIP-712 signing-domain refusals introduced by nevermined-io/nvm-monorepo#2959. Two codes rather than one because the same check fails for opposite owners: 0012 (400) is the seller advertising a domain its own settlement token does not sign under; 0013 (500) is a gap in Nevermined's canonical token table. Coding ours as the seller's told an agent to report OUR defect to an innocent counterparty, and buried the only signal that the table has drifted. Added to all 10 surfaces the drift guard holds to api-errors.ts, plus the rails-x402 page. Skill 0.1.2 -> 0.1.3.⚠️ MERGE AFTER nvm-monorepo#2959. The drift guard is bidirectional — diffErrorTable (scripts/lib/skill-error-table.ts:232) flags a code documented here that api-errors.ts does not define. Landing this first produces 4 stale drifts on nvm main, and publishes a skill telling autonomous buyers to branch on codes the API cannot return. Stacked on #305, which carries the two corrections that are independent of #2959. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
👀 Reviewing |
eruizgar91
left a comment
There was a problem hiding this comment.
Code review
Both corrections were verified against nevermined-io/nvm-monorepo at main, not taken from the PR description. One low-severity note is posted inline; nothing else survived.
Verified true
BCK.ROUTER.0006/0007facts.api-errors.tshas0006= 500,retryable: true("Error getting router payments summary") and0007= 429Too many concurrent routed requests,retryable: true. The bullet's claim that these are the only two retryable codes matches the registry.- The drift check actually goes green. Ran
pnpm exec tsx scripts/check-skill-error-drift.tsagainst a detached worktree atfe396ee:✓ published skill matches api-errors.ts — 11 BCK.ROUTER codes across 2 table(s), exit 0. Reproduces the PR body's claim exactly. - Leaving
0007bare is correct, not a half-finished edit..windsurf/rules/nevermined-router.mdis aPROSE_SURFACESentry whose omit list isCONDENSED_IDE_RULES = [0004, 0005, 0007](scripts/check-skill-error-drift.ts:63-72), and the presence rule is a literaltext.includes(code)(:190-202). Only0006was required and missing. The three sibling IDE rule files write the same asymmetric form at base —.cursor/rules/nevermined-router.mdc:129,.clinerules/nevermined-router.md:133,.amazonq/rules/nevermined-router.md:124— so this restores parity rather than creating divergence. Blame confirms the bare form was a regression introduced by #299 (this PR's own base), not the original wording. - The
extra.namecorrection.assetSymbol()resolves the symbol fromentry.assetagainstKNOWN_ASSETS_BY_CHAINIDand returnsundefinedfor anything unrecognised, which is then treated as not fundable (apps/api/src/router/x402/x402-exact.ts:52-110).extra.name/extra.versionare consumed only as the EIP-712 signing domain and are hard-required (:210-211,:233-234). The"USD Coin"(Base mainnet) vs"USDC"(Base Sepolia) split is stated in that file's own comment block. Every sentence added on lines 59-65 holds. - Merge order. The diff contains no reference to
BCK.ROUTER.0012or0013; neither code exists inapi-errors.tstoday, so nothing here depends on nvm-monorepo#2959 and the bidirectional guard cannot go stale on this branch. - Completeness of the fix.
extra.nameappears exactly once in the whole docs tree — the line this PR corrects. No sibling surface (skills/nevermined-router/, the four IDE rule files,AGENTS.md,.github/copilot-instructions.md) ever carried the wrong claim, so no companion edit is missing.
Considered and discarded
- "a signature the token cannot recover" (line 65) — loose phrasing; ecrecover yields a different signer rather than failing to recover. The operative claim (the payment cannot settle) is right, and the precision is not worth a reader's attention.
- The new section omits the security half of the rationale —
x402-exact.ts:66-69also notesextra.nameis merchant-controlled and therefore untrustworthy for "is this USDC?". Absent, but not contradicted, and the page is seller-facing. - No
docs.jsonentry for the new###heading — it is an in-page subheading under the existing##, not a route; nav is unaffected. - No
SKILL.mdversion bump — history shows the version tracks edits toSKILL.md's own content; neither touched file is mirrored there. - Commit title uses
fix(router):rather than thedocs:prefixCLAUDE.mdlists — the repo's own merged history (#269, #289, #291, #299) consistently does the same.
Coverage note. Four of the five analysis lenses completed: repo-convention compliance, git history/blame, prior-PR review feedback, and in-file/consumer guidance. The shallow-bug lens and the automated PR-summary pass did not complete (infrastructure interruption); their scope — factual accuracy of every added sentence, MDX structure, and the 0012/0013 forward-reference check — was covered directly against the monorepo source and the rendered file at fe396ee, as itemised above.
🤖 Generated with Claude Code
eruizgar91
left a comment
There was a problem hiding this comment.
🟡 Approved with comments — no blockers; 0 should-fix, 1 nit(s) left inline.
Inline review: #305 (review)
This PR's edit to `.windsurf/rules/nevermined-router.md` grew it by 11 characters, so the figure CLAUDE.md pins was wrong the moment it landed. Re-measured with the exact command CLAUDE.md prescribes (characters, not bytes — `wc -c` reads 6,063 here because the file is full of `—` and `⚠️ `): base 237a9b5 = 5,980, head = 5,991. The payments sibling is unchanged at 3,759, verified the same way. The number is maintained precisely because the failure is silent: Windsurf drops the END of the file, where the guardrails live. Nine characters of headroom now remain, so the next edit to this file has to displace something rather than absorb it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The two EIP-712 signing-domain refusals introduced by nevermined-io/nvm-monorepo#2959. Two codes rather than one because the same check fails for opposite owners: 0012 (400) is the seller advertising a domain its own settlement token does not sign under; 0013 (500) is a gap in Nevermined's canonical token table. Coding ours as the seller's told an agent to report OUR defect to an innocent counterparty, and buried the only signal that the table has drifted. Added to all 10 surfaces the drift guard holds to api-errors.ts, plus the rails-x402 page. Skill 0.1.2 -> 0.1.3.⚠️ MERGE AFTER nvm-monorepo#2959. The drift guard is bidirectional — diffErrorTable (scripts/lib/skill-error-table.ts:232) flags a code documented here that api-errors.ts does not define. Landing this first produces 4 stale drifts on nvm main, and publishes a skill telling autonomous buyers to branch on codes the API cannot return. Stacked on #305, which carries the two corrections that are independent of #2959. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(router): document BCK.ROUTER.0012 and 0013 The two EIP-712 signing-domain refusals introduced by nevermined-io/nvm-monorepo#2959. Two codes rather than one because the same check fails for opposite owners: 0012 (400) is the seller advertising a domain its own settlement token does not sign under; 0013 (500) is a gap in Nevermined's canonical token table. Coding ours as the seller's told an agent to report OUR defect to an innocent counterparty, and buried the only signal that the table has drifted. Added to all 10 surfaces the drift guard holds to api-errors.ts, plus the rails-x402 page. Skill 0.1.2 -> 0.1.3.⚠️ MERGE AFTER nvm-monorepo#2959. The drift guard is bidirectional — diffErrorTable (scripts/lib/skill-error-table.ts:232) flags a code documented here that api-errors.ts does not define. Landing this first produces 4 stale drifts on nvm main, and publishes a skill telling autonomous buyers to branch on codes the API cannot return. Stacked on #305, which carries the two corrections that are independent of #2959. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs(router): fit the windsurf copy under its cap by omitting 0012 there Documenting BCK.ROUTER.0012 and 0013 pushed `.windsurf/rules/nevermined-router.md` to 6,469 characters — 469 over Windsurf's 6,000 cap, which truncates silently and drops the END of the file, exactly where the guardrails live. The overflow would have shipped unnoticed: nothing errors, the rules just stop. The file could not absorb both codes. Measured, not estimated: at the tersest honest wording, and after displacing every pure example the file still had, two codes came to 6,054 — still over. So one had to go. `0012` is the one omitted, and only from Windsurf: - It is a **400**, and the file already states the rule that decides it — "only 0006 and 0007 are retryable". Nothing is lost that the reader cannot act on. - `0013` is a **500**, the one shape an agent retries by default. That is the same reason this copy keeps `0010` while omitting `0007`. - Cursor, Cline, Amazon Q, Copilot, AGENTS.md and both table surfaces all carry BOTH codes. Only the capped file diverges. Displaced to make room, all presentation rather than rules, per CLAUDE.md ("what it trades away is presentation, never a rule"): the `category` enum example, the spelled-out `payment.fee` column list, and the gloss on `0007` — itself a declared omission on this surface. Also updates the headroom figure to 5,994 (6 characters left) and records the omission on the install page, so the promise the page makes to readers stays true. Needs the matching nvm-monorepo change to PROSE_SURFACES before the drift check accepts it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Split out of #304 so it can land immediately: this PR references no unreleased error code, so it is independent of nevermined-io/nvm-monorepo#2959 and unblocks nvm-monorepo#2956 now.
Why now
check-skill-error-driftin nvm-monorepo compares this repo's skill againstapi-errors.tsand runs on every nvm PR touching the error catalogue. Against nvmmaintoday it reports exactly one drift, and it is fix (1) below:With this branch:
nvm-monorepo#2956 is otherwise ready and blocked only on that check being red.
The two changes
1.
.windsurf/rules/nevermined-router.md— qualifyBCK.ROUTER.0006. It wrote the retryable pair as bare`0006`/`0007`where its four sibling IDE rule files write the qualified form. The guard matchesBCK\.ROUTER\.\d{4}, so it could not see the code there and reported it as undocumented. One token; no wording change.2.
products/router/rails-x402.mdx— the asset symbol does not come fromextra.name. The page said:That is the pre-#2768 behaviour and has been false since nvm-monorepo#2775. The symbol is resolved from the
assetaddress, matched against the canonical token addresses for the chain. As written the page tells a seller the opposite of what is true and sends a reader debugging in exactly the wrong direction.Corrected, plus a short section on what
extra.nameactually is — the settlement token's own EIP-712 domain,"USD Coin"on Base mainnet and"USDC"on Base Sepolia — since mistaking it for a ticker is precisely what produced that bug. Both facts hold against nvmmaintoday.Scope discipline
Deliberately not included, because they document behaviour that does not exist until nvm-monorepo#2959 merges: the byte-for-byte domain check,
BCK.ROUTER.0012, andBCK.ROUTER.0013. Those stay in #304.That ordering is not a preference — the drift guard is bidirectional.
diffErrorTable(scripts/lib/skill-error-table.ts:232) flags a code this skill documents thatapi-errors.tslacks, verified by running the docs-first scenario: 4staledrifts, exit 1. So #304 must land after #2959; this PR must not.Verification
main: green, exit 0 (output above).mintlify broken-links: no broken links found, whole site.SKILL.mdis untouched here.🤖 Generated with Claude Code