Skip to content

feat: add Server Redirect CEP draft - #47

Open
ContextVM-org wants to merge 4 commits into
masterfrom
cep-42-server-redirect
Open

feat: add Server Redirect CEP draft#47
ContextVM-org wants to merge 4 commits into
masterfrom
cep-42-server-redirect

Conversation

@ContextVM-org

@ContextVM-org ContextVM-org commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

CEP-47: Server Redirect

Summary

Adds a draft Standards Track CEP defining a request redirection mechanism for ContextVM. A server can instruct a client to re-issue a request to a different address (a public key, with optional relay hints) by returning a JSON-RPC error response (-32044 "Redirect").

Motivation

There is currently no way for a ContextVM server to hand a client a different address mid-exchange. This blocks two common patterns, both reducible to "use this address instead":

  • Load distribution: a well-known entry point points clients at a backend instead of proxying traffic.
  • Privacy: a server rotates clients onto a different (possibly unannounced) address so its announced identity carries no subsequent traffic.

The reason for a redirect is a server-side concern; the protocol carries only the address hand-off and never represents intent on the wire. Full motivation, rationale, and security discussion live in the tracking issue.

What this PR contains

Per the CEP guidelines, this PR holds the specification-side document only:

  • src/content/docs/reference/ceps/cep-47.md — abstract, specification, security considerations, backward compatibility, dependencies, reference implementation
  • astro.config.mjs — sidebar registration

The tracking issue carries the comprehensive proposal (motivation, rationale, security implications); its Specification section should link back to this PR to keep the spec in a single place.

Design

  • One JSON-RPC error: -32044 "Redirect" in a kind-25910 response, e-tag correlated to the original request.
  • error.data: target (required pubkey), relays (optional inline hints; absent ⇒ CEP-17 lookup), instructions (optional, agent-readable).
  • Server emits it unconditionally per its own policy — no capability negotiation, no branching on client support.
  • Client re-issues the same request (method/params) to target; caps redirect chains (≤5) to prevent loops; surfaces unknown codes as ordinary errors (safe degradation, not silent failure).
  • Session state is established directly with target on re-issue, so no state transfer is needed and redirect works at any point in an exchange.
  • Follows the same "intercept special error → extract retry directive → re-issue" pattern as CEP-8's -32042 payment-gating error, but is independent of it.

Backward compatibility

Additive. No new event kind is introduced (redirects are normal kind-25910 responses); servers that do not redirect are unaffected; clients that do not recognize -32044 surface it as a normal error and are no worse off than with any other server refusal.

Dependencies

  • CEP-6 (target identity verification)
  • CEP-17 (relay discovery fallback when relays is absent)

CEP-4 (channel security) and CEP-8 (error-pattern sibling) are referenced inline only, not listed as dependencies.

@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
contextvm-docs Ready Ready Preview, Comment Jul 22, 2026 3:09pm

@abhayguptas

Copy link
Copy Markdown

Pulled the branch and went through the spec. Core design is solid, follows the same intercept-error-reissue pattern as CEP-8 which makes the SDK implementation straightforward. A few things that would be worth tightening before merge:

target format

The spec says target is "the public key of the server" but doesn't specify the format. Hex, npub, nprofile? If nprofile is allowed it carries relay hints inline, which overlaps with the relays field. Worth pinning this down explicitly, something like "64-character lowercase hex public key."

Relay fallback order when relays is provided

The spec covers the case where relays is absent (fall back to CEP-17). But when relays IS provided and the target is unreachable on those relays, should the client fall back to CEP-17 discovery or treat it as a failure? A sentence covering the priority would help implementers.

Redirect arriving during an in-flight CEP-8 payment

Security considerations mention that the target becomes the payment processor on redirect. But what about the case where a redirect arrives after a payment_required notification was already received in transparent mode (invoice displayed, waiting for settlement)? Should the client abandon the in-flight payment with the original server? Probably worth a note saying redirect cancels any pending payment state for that request.

Hop counter scope

"At most 5 hops" but is this per original request or per session? If a client sends 10 different tool calls and each gets one redirect, that's 10 total hops but only 1 per request. I'd suggest clarifying as "at most 5 consecutive redirects for the same original request."

Self-redirect

A server redirecting to its own pubkey creates a trivial 1-hop loop. The hop cap catches it eventually but burns through retries. A "servers SHOULD NOT redirect to their own public key" would be a cheap guard.

Unreachable target

No guidance on what to do if the target is simply offline or can't be reached. Should the client surface the redirect as an error to the caller, or retry the original server? Probably the former to avoid silent fallback confusion.

Minor: branch name is still cep-42-server-redirect but the spec content is CEP-47.

@1amKhush

1amKhush commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Some additional findings

+1 on all of Abhay's points. A few things not yet covered:

  1. Add _meta to error.data — CEP-8's error responses include _meta as an extension namespace. CEP-47 omits it. Adding it now avoids a breaking change if future extensions are needed (redirect reason hints, TTL, capability equivalence hashes via CEP-15).

  2. Redirect during CEP-41 open streams — if a redirect arrives for a request with an active open-ended stream, the client would need to abort and restart with target. Worth a note: "A redirect MUST NOT be emitted for a request with an active open-ended stream (CEP-41); the server SHOULD complete or abort the stream first."

  3. instructions example value — agents should treat -32044 as the actionable signal, not parse instructions for routing logic. An example like "Re-issue your request to the target address." would help implementers.

  4. Structured field table for error.data — for parity with CEP-8, a quick table (field / required / type) would improve scannability over the current prose-after-JSON-block format.

@ContextVM-org

Copy link
Copy Markdown
Contributor Author

Thanks @abhayguptas and @1amKhush . Attached your feedback in my latest commit. Please share your thoughts

@abhayguptas

Copy link
Copy Markdown

All points addressed cleanly. The field table, _meta namespace, hop scope clarification, CEP-41 interaction rule, and relay fallback order are all solid. One remaining gap I noticed:

Client behavior when server violates the CEP-41 MUST NOT

Line 75 says the server MUST NOT emit a redirect for a request with an active open-ended stream. That's the right constraint. But the spec doesn't say what a client should do if a buggy server does it anyway. The client receives a -32044 while the stream is still open (no close or abort frame), which leaves ambiguous state: does it follow the redirect with the stream still active? Does it ignore the redirect because it violates the spec?

Suggesting something like: "If a client receives a -32044 during an active CEP-41 stream, it SHOULD treat the stream as failed, release local stream state, and follow the redirect normally." That gives clients a clear defensive rule without over-specifying.

Everything else looks ready.

…rationale

- Client Behavior: define recovery when a server emits -32044 without
  first terminating an active CEP-41 stream (treat as failed, release
  state, follow redirect; stricter client MAY refuse).
- Server Behavior: correct the MUST NOT rationale — the stream needs its
  terminal close/abort frame before the single final JSON-RPC response;
  a mid-stream redirect strands it, rather than a double-final collision.
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.

3 participants