feat(api): XIP-83 Subscribe — tag deliveries with wave mutate_id and enforce ordering guarantees#2035
Conversation
Summary by OctaneNew ContractsNo new contracts were added. Updated Contracts
🔗 Commit Hash: 574d699 |
ApprovabilityVerdict: Needs human review This PR implements XIP-83 Subscribe ordering guarantees - a protocol-level feature with significant runtime behavior changes including new wave tagging, merged keyset scanning, and ordering enforcement. The scope and complexity of these changes, plus the fact that all files are owned by xmtp/backend, warrants review by the designated owners. You can customize Macroscope's approvability policy. Learn more. |
574d699 to
8495f6e
Compare
Overview
Detailed findings
|
1e7a53a to
75f7bc5
Compare
|
Octane scan triage. The scan ran against Hardened in response — finding 1 (T×N floor materialization / per-wave ceilings): the adds-count cap ( Fixed before the scan posted — finding 4 (ceilings built only from cached originators): the current head builds the ceiling set from the originator cache ∪ every cursor-named originator ( Bounded by existing guards — findings 2, 3: concurrent waves are capped per stream ( By design per XIP-83 — findings 5, 6: the nonzero Not reproducible — findings 7–10 and the warning:
|
75f7bc5 to
64a3342
Compare
64a3342 to
7dffb62
Compare
…enforce ordering guarantees Replace per-topic catch-up with a merged keyset scan over per-(topic, originator) floors bounded by per-originator ceilings pinned at wave start; gate live delivery for a wave's topics and fold gated arrivals into the wave at completion (tagged, sorted per originator, deduped); stamp every Envelopes frame with its wave's mutate_id (0 = live); require nonzero mutate_id on adds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7dffb62 to
095b0b1
Compare
Implements XIP-83 server-tagged deliveries on the d14n
QueryApi.Subscribehandler. Spec revision: xmtp/XIPs#139; protos: xmtp/proto#340.Protocol behavior
Envelopesframe is stamped with the wave that produced it (mutate_id,0= live); a frame never mixes lanes or waves.originator_sequence_id, stream-wide; a wave's replay does the same across the wave's topics.CatchupComplete; live for other topics keeps flowing; envelopes are delivered exactly once across the seam.Mutatewith adds must carry a nonzeromutate_id(INVALID_ARGUMENTotherwise); everyMutateis acked by exactly oneCatchupComplete.Implementation
SelectGatewayEnvelopesWaveScan: per-(topic, originator) floors, row-value(originator, sequence)keyset progression, per-originator ceilings from the newSelectOriginatorCeilingspinned at wave start).TopicsLive, thenCatchupComplete, then the gates open.Testing
White-box pins for the fold (tag/order/seam frame sequence, scan-vs-pending dedup, ceiling-less new originator, remove-mid-wave pending disposal, DB or send error → no
CatchupComplete), plus end-to-end: overlapping waves, per-originator order on both lanes, the seam with a live sentinel topic, reset mid-wave across scan pages, keyset pagination across a mid-originator page boundary, duplicate adds, and the empty-Mutateack. Internal tests run green under-race.Depends on xmtp/proto#340 — the vendored generated code here matches that branch and regenerates identically from proto@main once it lands.
🤖 Generated with Claude Code
Note
Tag subscribe delivery frames with wave
mutate_idand enforce per-wave ordering guaranteesmutate_id; live frames carrymutate_id=0, giving clients a reliable way to distinguish replay from live delivery.(originator, sequence), and emitted under the wave'smutate_idbeforeTopicsLiveandCatchupCompleteare sent, enforcing per-originator ordering at the seam.(originator, sequence)ordered stream bounded by per-originator ceilings captured at wave start, replacing per-topic chunking; new SQL queriesSelectGatewayEnvelopesWaveScanandSelectOriginatorCeilingssupport this.handleMutatenow requires a non-zeromutate_idfor adds, rejects reuse of an in-flightmutate_id, and enforces caps on raw add count (maxMutateAdds=100,000) and total cursor entries (maxMutateCursorEntries=1,000,000).Macroscope summarized 095b0b1.