feat(payments): add the server payments registration entry point and gateway payment options - #113
Draft
harsh04044 wants to merge 7 commits into
Draft
Conversation
…authorization store
…am's drop-cleanup
… with payment-required errors
…ation entry point
…t both transport-construction sites
…registration entry point
This was referenced Aug 31, 2026
Draft
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.
Part of #100
Stacked on #112 (which is stacked on #111). Diff base
74e4d2e. I'll rebase onto main once the parents merge, same as the earlier PRs in this stack.This adds
with_server_payments, the call that actually turns the payment stack on. The middlewares from the last two PRs were only ever constructed by tests; nowcontextvm_sdk::payments::with_server_payments(&mut transport, options)wires everything up in one place, beforestart():pmiper processor, onecapper priced capability, and apayment_interaction=explicit_gatingtag when the policy isOptionalOptional) the explicit-gating one with a fresh authorization storeThe property that matters: one bool (
policy == Optional) decides the availability tag, the recorded policy, and whether the gating middleware gets registered. So a server can never negotiate a client onto explicit gating without having the middleware that answers it, and a transparent-only server never advertises a mode it rejects.The gateway gets a
payment_optionsfield onGatewayConfig(plus a builder), used in bothNostrMCPGateway::newandserve_handler.Client-side payments (auto-pay, retries) and the docs are the next PR.
The main thing to review: two deliberate divergences from ts
ts's
withServerPaymentsnever fails. Ours returnsResultand refuses two calls:start(). This works in ts because its middleware list is read on every dispatch. In rs the middlewares and the policy freeze into the event loop atstart(), so a late registration would update the announcement tags but register nothing: the server would advertise payments while executing every priced request for free. Hence the hard error.addInboundMiddlewareappends, so a second call registers a second middleware pair and every priced request gets two invoices. Not a guess; we ran the real ts function twice in a small spike and saw twocreatePaymentRequiredcalls for one request. The rs guard checks the recorded policy, which also means calling the entry point after hand-setting the policy is refused: the entry point owns the policy.Both checks run before anything is mutated, so a refused call leaves the transport untouched. The two error messages are part of the API now (the gateway and the next PR propagate them).
Also in here
pub(crate)accessors on the transport (started-ness, session timeout, recorded policy). Nothing new becomespub.payment_ttlas its snapshot TTL instead of the crate default, and apayment_ttlabove the session timeout logs a warning once at registration.[[test]]Cargo entry, a CHANGELOG bullet. No new dependencies, no FFI change.Known quirks (same as ts, documented in the rustdoc, not changed)
pmitags; only the last one is selectable.Note
The ts double-registration double charge should be reported to the ts-sdk, alongside the earlier findings (the wire id on gating errors, the
ttl: 0grant, the negotiation latch question).