feat: CEP-22 - transport integration, outbound split, inbound reassembly, accept handshake#91
Merged
ContextVM-org merged 1 commit intoJun 10, 2026
Conversation
…bly, accept handshake
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 #87
Third PR of CEP-22. Wires the framing engine (PR 1) and config (PR 2) into the actual transport layer. This is the big one - sender and receiver land together since they're co-dependent.
Lets MCP messages too large for a single Nostr event - big tool results, resources - travel over Nostr transparently.
Outbound fragmentation - client request path and server response path both check whether the final published (post-encryption, gift-wrapped) event would exceed the threshold, then split into start/chunk/end frames via send_oversized_transfer. The decision uses the real on-wire size, not the raw payload. Chunk size is resolved per-send via binary search (resolve_safe_chunk_size) so each frame stays under the threshold regardless of encryption overhead.
Inbound reassembly - both event loops intercept oversized frames ahead of the 1 MB single-message validation (so a reassembled payload can exceed 1 MB) and feed them to an OversizedTransferReceiver. On end, the receiver validates byte-length + SHA-256 + JSON-RPC parse before delivering the reassembled message.
Accept handshake - client registers a oneshot waiter keyed by progressToken before publishing start, then awaits it with a 30s timeout. The server emits an accept frame on first contact when peer support is unknown, using a pre-learning snapshot to get the decision right.
Correlation - client registers pending against the end-frame event id. Server dispatches a synthetic IncomingRequest on end keyed by the end frame's carrying event id so responses route back correctly.
Also adds resolve_safe_chunk_size + measure_published_event_size (sizing.rs), a touch() method on ClientCorrelationStore to keep pending entries alive during long transfers, and per-peer reassembly store on the server. Builds on the MockRelayPool filter-fidelity fix (#90), which makes EncryptionMode::Disabled e2e tests sound.
14 new integration tests covering request/response roundtrips, accept handshake, out-of-order delivery, digest mismatch, abort, per-frame size, >1 MB reassembly, all 3 encryption modes, gate-off, and the inflation-aware decision. 522 tests passing, clippy clean, fmt clean.
Known open item: per-transfer watchdog timer (transfer_timeout_ms default 300s) - deferred to next PR (4th).