Feat/cep8 explicit gating#75
Open
1amKhush wants to merge 5 commits into
Open
Conversation
Resolves ContextVM#74 by adding full support for the explicit gating payment lifecycle in the ContextVM TypeScript SDK. Includes server middleware for tracking authorization states, client support for auto-retrying intercepted -32042/-32043 errors, and transport modifications to negotiate payment modes.
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds CEP-8 “explicit_gating” payment interaction mode support across Nostr client/server transports, including negotiation tags, server-side authorization gating, and client-side auto-retry behavior for -32042/-32043.
Changes:
- Introduces explicit-gating server middleware with canonical invocation hashing + authorization store.
- Adds client negotiation/disclosure plumbing (
payment_interactiontags) and client auto-retry handling for-32042/-32043. - Refactors shared server payment utilities and adds unit + transport-level tests.
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/transport/payments-flow.test.ts | Adds a transport-level test for explicit-gating behavior and retry flow. |
| src/transport/nostr-server/session-store.ts | Stores requested/effective payment interaction on server sessions. |
| src/transport/nostr-server/outbound-response-router.ts | Discloses effective payment_interaction on first response (CEP-8). |
| src/transport/nostr-server/inbound-coordinator.ts | Parses client payment_interaction request and sets per-request context. |
| src/transport/nostr-server-transport.ts | Exposes API to configure supported payment interaction mode. |
| src/transport/nostr-client/server-metadata-store.ts | Persists server-disclosed effective payment interaction mode. |
| src/transport/nostr-client/outbound-sender.ts | Stores raw JSON-RPC request into correlation metadata for retries. |
| src/transport/nostr-client/inbound-coordinator.ts | Captures server-disclosed payment_interaction tag and passes event id to response handler. |
| src/transport/nostr-client/correlation-store.ts | Extends pending request state to include the raw JSON-RPC request. |
| src/transport/nostr-client-transport.ts | Exposes get/set API for payment interaction negotiation and forwards response context. |
| src/transport/middleware.ts | Extends inbound middleware context with paymentInteraction. |
| src/transport/capability-negotiator.ts | Advertises requested payment_interaction tag from the client. |
| src/payments/types.ts | Adds explicit-gating types: interaction mode, error data shapes, canonical identity. |
| src/payments/server-transport-payments.ts | Wires explicit-gating middleware + discovery tags into server transport. |
| src/payments/server-payments.ts | Refactors shared helpers into a new utils module; adds paymentInteraction option. |
| src/payments/server-payments-utils.ts | New module for timeout/capability matching and resolvePrice type guards. |
| src/payments/server-explicit-gating.ts | Implements explicit-gating server middleware returning -32042/-32043. |
| src/payments/server-explicit-gating.test.ts | Unit tests for explicit-gating server middleware. |
| src/payments/constants.ts | Adds explicit-gating error codes and negotiation error code constant. |
| src/payments/client-payments.ts | Adds client-side explicit-gating handling, auto-retry, and pending backoff. |
| src/payments/client-payments.test.ts | Adds tests for -32042/-32043 handling and retry behavior. |
| src/payments/canonical-identity.ts | Computes canonical invocation hash/identity using JSON canonicalization + SHA-256. |
| src/payments/canonical-identity.test.ts | Unit tests for canonical hashing determinism and identity composition. |
| src/payments/authorization-store.ts | Adds LRU+TTL store for pending/granted paid authorizations. |
| src/payments/authorization-store.test.ts | Unit tests for authorization store behavior (TTL, pending, eviction). |
| src/core/constants.ts | Adds PAYMENT_INTERACTION to Nostr tag constants. |
| package.json | Adds json-canonicalize dependency. |
| bun.lock | Locks json-canonicalize dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Feat: CEP-8 Explicit Gating Lifecycle
Resolves: #74
Reference Spec: ContextVM/contextvm-docs#44
Description
This PR introduces full support for the Explicit Gating payment lifecycle (
explicit_gatingmode) in the ContextVM TypeScript SDK, as mandated by the latest CEP-8 specification updates.Previously, the SDK only supported the default
transparentnotification-based payment flow. With this update, servers can now strictly gate priced capabilities by returning JSON-RPC error responses (-32042 Payment Requiredand-32043 Payment Pending), effectively blocking execution until a verifiable payment is made.Key Changes & Architecture
-32042and-32043.payment_interactionto negotiation tags.CanonicalInvocationIdentityutilizing RFC-8785 JSON canonicalization (JCS) and SHA-256 to ensure idempotent matching between paid authorizations and retried executions.createExplicitGatingMiddleware):AuthorizationStorewith strict check-and-set atomicity.-32043with a precise mathematically computedretry_afterif a request races against an active payment verification.ClientSessionto track bothrequestedPaymentInteractionandeffectivePaymentInteraction.payment_interactionmode and safely fallback totransparentmode to prevent injection of untyped interactions.withClientPayments):onPaymentRequiredhandler hook.-32043errors capped at 5MAX_RETRIES, alongside robust memory management (timer cancellation on transport termination).Testing
AuthorizationStoreconcurrency, JCS hashing, and edge cases. (Timings have been buffered to prevent CI flakiness).payments-flow.test.ts) that runs a client request → intercepts-32042→ delegates to user payment logic → auto-retries → consumes authorization → and successfully returns the result.Notes-
AuthorizationStore.trySetPendingrelies on in-memory Maps and is therefore strictly single-process. Extensive doc comments have been added noting that distributed environments should implement an external Redis Redlock using theCanonicalInvocationIdentity.transparentcapability.