Skip to content

docs: add the Nevermined Router section - #264

Merged
r-marques merged 3 commits into
mainfrom
docs/router-section
Jul 31, 2026
Merged

docs: add the Nevermined Router section#264
r-marques merged 3 commits into
mainfrom
docs/router-section

Conversation

@r-marques

Copy link
Copy Markdown
Member

What

Adds a top-level Nevermined Router group to the Guides tab, sibling to Payments — the buyer
side of Nevermined, documented on the site for the first time.

Before this PR the docs site had no Router page at all: not for MPP, and not even for x402. The
only user-facing guide was the in-repo apps/api/src/router/README.md, which covers MPP only.

Pages

Page Covers
overview What the Router is, buyer side vs the x402 Facilitator (seller side), which services are payable, environments, prerequisites
how-it-works The five-beat payment flow, mode A vs mode B (+ the streaming /proxy variant), where custody sits, how settlement is recorded
quickstart API key → Delegation → fund the wallet → first paid call → check the ledger. curl / TypeScript / Python
rails-x402 The exact scheme, Base + Base-Sepolia, USDC/EURC, v1 vs v2 negotiation, the cents rounding, operator config
rails-mpp Tempo charge, the fail-closed asset allowlist, receipts, why split-bearing challenges are refused, the flag-gated card rail
guardrails Cap and expiry, the wallet balance check, recipient scope, idempotency, SSRF, relay limits, and every BCK.ROUTER.* code
ledger GET /payments with filters and CSV export, the aggregate summary, record statuses, closing a mode-A record, reconciliation

Grounding

Every claim is taken from the merged Router code — the controller's OpenAPI annotations, the DTOs,
api-errors.ts, x402-exact.ts, mpp/, and the in-repo MPP guide — rather than restated from a
roadmap. Specifics that came out of reading the source rather than assuming:

  • Sub-cent payments still reserve a whole cent of Delegation budget (amounts round up).
  • A mixed-chain 402 is not fatal — an unparseable entry (e.g. Solana) is skipped as long as a
    fundable one remains.
  • The asset symbol filter reads accepts[].extra.name, so a service that omits it won't match.
  • Issued is a success state, not an error — the Router deliberately won't fail an already-paid
    hop over a missing or malformed receipt.
  • The settlement reference is merchant-controlled and stored unverified, and a non-0x value is
    legitimate. Documented as an anchor to verify, not as proof of payment.
  • BCK.ROUTER.0003 (cap) and 0009 (wallet balance) are genuinely different failures — a cap is
    permission, not funds.

Scope — two pages deliberately deferred

discover-services and agent-autonomy are not in this PR. They overlap
#241 (Agents Catalog), and the agreed seam is:

  • Agents Catalog owns discovery — what is listed, the read API, the ARD feed.
  • Nevermined Router owns the payment product end to end.

Anything payment-related in the catalog section should become a link into this one, so there is only
ever one description of how to call through the Router. Happy to do that trim here or leave it to
#241 — whichever the author prefers.

Related

  • Error codes: the BCK.ROUTER.* namespace is still absent from the published catalogue on this
    site. #248 already contains all 9 codes and just
    needs a rebase onto the current path layout.
  • Tracking issue: nevermined-io/nvm-monorepo#2593

Validation

  • mintlify broken-linksno broken links.
  • All 7 pages carry title / description / icon frontmatter; component tags balance.
  • docs.json edited surgically (13-line diff, no reformat) and parses.
  • api-reference/** untouched — it is generated from the SDK repos.
  • Only sandbox / live environment names appear.

🤖 Generated with Claude Code

Adds a top-level "Nevermined Router" group to the Guides tab, sibling to
Payments — the buyer side of Nevermined, documented for the first time.
Neither rail had any docs-site coverage before this: not MPP, not even x402.

Pages: overview, how-it-works, quickstart, rails-x402, rails-mpp,
guardrails, ledger.

Everything is grounded in the merged Router code (apps/api/src/router/) —
the controller's OpenAPI annotations, the DTOs, the error catalogue, and
the in-repo MPP guide — rather than restated from the roadmap.

Two further pages (discover-services, agent-autonomy) are deliberately
deferred pending the seam with the Agents Catalog section in #241.

Refs nevermined-io/nvm-monorepo#2593

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mintlify

mintlify Bot commented Jul 31, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Nevermined 🟢 Ready View Preview Jul 31, 2026, 2:15 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

…ns unrestricted

Self-review caught an overstatement: the Router enforces recipient scope
only when the delegation actually carries a recipient list
(router.service.ts guards on `allowedRecipients.length > 0`). A delegation
without one can pay any reachable merchant, with the cap and expiry as its
only limits — the opposite of what the first draft implied.

Also corrects the MPP splits rationale: that refusal is unconditional, not
a consequence of recipient scope.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@r-marques
r-marques marked this pull request as ready for review July 31, 2026 14:15
@r-marques
r-marques requested a review from a team as a code owner July 31, 2026 14:15

@aaitor aaitor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve. This is an unusually well-grounded docs set — I cross-checked the concrete, falsifiable claims against the merged Router source and they hold up end to end. The writing earns its density: each page stands alone (deliberate repetition of the pull/custody model across rails is correct for docs, not debt), the agent-facing framing is genuinely useful, and the error/guardrail pages are precise rather than aspirational. One LOW inline nit; nothing gating.

Verification I ran (against apps/api/src/router/** + libs/helpers/src/lib/output/api-errors.ts on the local monorepo checkout)

  • Error table (guardrails): all 9 BCK.ROUTER.* codes match the catalogue — statuses 0001→400, 0002→409, 0003→402, 0004→404, 0005→409, 0006→500, 0007→429, 0008→403, 0009→402, and the retryable set is exactly {0006, 0007}. ✅
  • Endpoints: routes.ts maps /api/v1/router and /api/v1/delegation; controller routes resolve to POST /route, ALL /proxy, POST /payments, POST /payments/:id/settled, GET /payments, GET /payments/summary, and POST /delegation/create / GET /delegation/:id. Every path in the docs is correct. ✅
  • Delegation DTOs: provider enum includes erc4337, currency includes usdc/eurc, spendingLimitCents/durationSecs required; the step-3 JSON (providerPaymentMethodId, remainingBudgetCents, amountSpentCents, expiresAt, …) matches the response DTO. The {delegationId} step-2 shape is a fair simplification (delegationToken is the optional JWT, not needed for the HTTP flow). ✅
  • x402 rail: base=8453 / base-sepolia=84532, CAIP-2 form, USDC/EURC 6-dec, exact/EIP-3009, extra.name symbol filter, ceil-to-cent rounding ((atomic + 9999)/10000), settlement.approxCents, MAX_AUTH_TTL_SECS=3600 — all confirmed. ✅
  • MPP rail: Tempo 4217 / Moderato 42431 → tempo/tempo-moderato, fail-closed ROUTER_TEMPO_ASSETS_<chainId> allowlist, splits refused unconditionally (mppx expectedRecipients backstop + re-decode compare), Payment-ReceipttxHash, method=stripe card rail behind ROUTER_STRIPE_SPT_ENABLED (the code's own comment calls it "sandbox-only"). ✅
  • Env defaults: ROUTER_MAX_CONCURRENT_PER_USER=10, STREAM_IDLE_MS=30000, STREAM_MAX_MS=300000, MAX_RELAY_BYTES=100MB, FUNDED_NETWORKS=base,base-sepolia, FUNDED_SYMBOLS=USDC,EURC, PREFER_SYMBOL=USDC. All match. ✅
  • SSRF / relay (guardrails): loopback / RFC1918 / link-local / 169.254.169.254 metadata blocked at literal-IP + name layer, DNS-rebinding caught by resolve-then-pin, redirects manual with location stripped, X-Router-* control headers stripped both directions, proxy header names all correct. ✅
  • Ledger: list-response fields, format=csv, from/to, and the summary (total + series[{date,value}], normalizeGranularity day/week/month → day fallback) match the DTOs. ✅
  • Leanness (/ponytail-review): nothing to cut. Cross-page repetition of the custody/0009 model is intentional standalone-page design for docs, not over-engineering. Lean already.
  • Nav / links: docs.json group is well-formed and correctly placed (sibling to Payments); cross-link /products/x402-facilitator/overview resolves on the branch; heading anchors (#3-fund-your-wallet, #how-settlement-gets-recorded, …) are correct. Only sandbox/live env names appear.
  • CI: 2/2 green; Mintlify preview 🟢.

Nice catch on the seam with #241 (catalog owns discovery, Router owns payment) — worth pinning that in one of the two PRs before both merge so the boundary doesn't drift.

Comment thread products/router/rails-x402.mdx Outdated
…cent)

aaitor review, LOW. The page states 10,000 atomic units = 1 cent, so the
4,500 example was 0.45 cent, not half a cent. The rounding point was
unaffected — both round up to 1 — but on the one page whose job is the
atomic-unit -> cent math, the example has to be exact.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@r-marques
r-marques merged commit 2b174be into main Jul 31, 2026
3 checks passed
@r-marques
r-marques deleted the docs/router-section branch July 31, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants