Skip to content

feat(payments): negotiate CEP-8 payment interaction on the server transport - #107

Merged
ContextVM-org merged 1 commit into
ContextVM:mainfrom
harsh04044:feat/cep8-server-negotiation
Aug 4, 2026
Merged

feat(payments): negotiate CEP-8 payment interaction on the server transport#107
ContextVM-org merged 1 commit into
ContextVM:mainfrom
harsh04044:feat/cep8-server-negotiation

Conversation

@harsh04044

Copy link
Copy Markdown

Part of #100

Fourth piece of CEP-8, after the authorization store in #104. First one that touches the live server transport rather than adding a self-contained module.

The server now speaks the payment-interaction handshake: parse the client's pmi and payment_interaction tags, negotiate an effective mode for the session, reject explicit_gating with -32602 when the server can't offer it, disclose the negotiated mode on the first response, and hang cap pricing tags off capability-list responses. The negotiated mode lands in InboundContext, which is what the payment middlewares will read.

No middleware and no payment flow yet. A server that never calls set_supported_payment_interaction and gets no payment tags behaves exactly as it does today.

What's here

  • extract_pmis / extract_payment_interaction in discovery_tags.rs
  • Three payment fields on ClientSession, mirrored onto SessionSnapshot and both mappers
  • The negotiation state machine in server/mod.rs, hooked into the inbound loop after the capability OR-learn, plus the -32602 emit on the drop path
  • set_supported_payment_interaction, frozen into the event loop at start()
  • First-response disclosure and the cap-on-list append in send_response, and the same composition on the CEP-41 deferred path
  • 38 unit tests, 14 more in a new pure tests/conformance_cep8_wire_format.rs pinning the tag tuples and -32602 bytes, 9 integration tests over MockRelayPool

No new dependency, no Cargo.toml change, no FFI change. The reasoning for each design call is in rustdoc on the item itself, including the odd-looking one where -32602 correlates on the inner request id instead of the event id.

CEP-41 fix

A deferred final response, held back while a stream is still open, went out with routing tags only. ts re-enters route() on flush and sends the full first-response set; our deferred publish is static and built its own bare tag list.

The fix covers the CEP-35 tags as well as the disclosure, because fixing one alone is worse than fixing neither. A client that negotiated gating and whose first call streams needs the disclosure or it concludes negotiation failed. But a response carrying the disclosure and nothing else un-gates the client's baseline capture, and it then latches that thin baseline and reports no server identity for the rest of the session.

So the deferred path now composes what the normal path composes: discovery and disclosure behind the same one-shot latches, then cap on a list result. Both flush orderings go through it. The test for it drives the real path end to end through start(), not the composer directly.

Heads up

Breaking. ClientSession and SessionSnapshot are now #[non_exhaustive]. This PR adds three fields to each, so downstream struct literals and exhaustive destructures break on cargo update either way; marking them now makes future additions free. InboundContext already had it. Next release is 0.3.0.

Pre-existing bug, not fixed here. The deferred publish never fragments. send_response measures an oversized response and splits it into CEP-22 frames; the deferred path calls send_mcp_message once with no size check, so a streaming tool returning a large final result fails and the flush only logs it. The client sees the stream complete, then waits for a response that never arrives.

Not in scope: the announcement availability tags. They need the processors and priced capabilities from the server payments options, so they belong with with_server_payments, same as ts.

@ContextVM-org
ContextVM-org merged commit 7fbaf2e into ContextVM:main Aug 4, 2026
9 of 10 checks passed
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