Add checked-history guards to Streams sessions

Merged
VA
5d ago
+1520-4

Current signed head: c075800b48725176832ae3043f94b276169be504. Both existing constructors in harness/client/swarm.rs and stream/memory/recovery_model.rs now default the empty guard. Workspace-wide Rust/TS construction audit found no other omission requiring an edit; TS uses Buf initializer defaults. The Greptile compile-blocker thread is replied to and resolved.

Requested local Windows/MSVC checks passed at this head:

  • cargo check -p acyclic-harness --lib — 49.29 s.
  • cargo check -p acyclic-stream --features http,local --lib --tests — 16.14 s.

The following earlier protocol/property/fuzz results predate this constructor-only fix and main merge.

Main conflict resolved and pushed at signed merge 7c40c6a9417bd18aa8203bd52a46ad895949049d. The conflict was adjacent additions in wire_codec/session.rs; both helper sets and InvalidArgument classification are retained. GitHub reports MERGEABLE. Validation of this merge is deferred until bb1 returns, per user instruction.

File live queries already call StreamProvider::follow_checked, but hosted sessions cannot carry or confirm its atomic predecessor check. Adds two additive fields without renumbering anything:

  • SessionFollow.preceding_commit_id = 3: optional 32-byte predecessor at resume.next - 1, with ALL delivery and next > 0.
  • SessionOpened.preceding_commit_id = 2: confirms the provider enforced that exact guard before registering the follow.

A checked client must match the confirmation before granting channel data credit. An older peer's missing confirmation fails that logical channel with Unsupported, preserving healthy siblings and preventing an unchecked fallback. Moved/reconnect must check the commit immediately before the last yielded cursor, rather than a buffered record or the initial snapshot.

The contract and field assignments are also recorded in Q:/lanes/session-protocol.md, in stream-push's own sections. The Actors extension handoff is untouched. Rust codec helpers implement guard decoding and confirmation; generated TS bindings, the descriptor and compatibility digest are regenerated through the focused Buf path.

Validation

All Linux execution used Q:/lanes/bs.ps1.

  • Focused built Rust binary: three tests passed in 0.00 s. Two 128-case shrinking properties verify exact byte round trips, valid/invalid request guards and exact/mismatched confirmations. A legacy-peer regression verifies that absent confirmation cannot authorize a checked follow.
  • Checked-in cargo-fuzz target exercises the actual codec helpers, including untrusted request and Opened frames. Four seeds cover a checked subscription, confirmed/legacy Opened and truncation. Debug ASan/coverage run on nightly-2026-07-01 completed 256 inputs in <1 s with no failure (1,680 coverage edges).
  • Buf breaking comparison against main's descriptor passed. The protocol gate now checks session field numbers and bidirectional Session streaming as well as the existing StreamService contract.
  • Protocol and compatibility digest gates pass. LF/source-size/diff checks pass.

Decisions

This is a platform follow precondition needed by a file query's snapshot-plus-cursor boundary. A file cannot make a remote provider atomically validate history and register a follow without provider confirmation. There is no harness endpoint, application message, store, polling fallback or new service. The pure codec boundary adds no synchronization or concurrency mechanism.

Keep this contract separate from adapter implementation so cloud lanes can pin a stable schema revision. Existing unchecked follows and provider-owned child/fs opaque cursors keep their wire meaning. Full-fidelity checked follows use explicit commit fields, rather than overloading opaque cursors.

Live steps

Native/TS/browser adapters and platform session hosts must implement the check and confirmation before exposing checked follows. #579, #557 and #644 need constructor compatibility updates for the additive generated fields; the lane is updating those branches before this contract merges. Deployed service measurement and platform fs query binding remain outstanding.

Disclosure

  • Existing field numbers preserved; no new dependency versions.
  • Signed commit with DCO sign-off.
  • No README, credential or private data changed.

Summary by cubic

Adds atomic history guards to Streams sessions so hosted follows confirm the exact commit they resume from, matching local file queries via follow_checked.

  • SessionFollow.preceding_commit_id (field 3) carries the 32-byte commit at resume.next - 1 and requires ALL delivery with next > 0.
  • SessionOpened.preceding_commit_id (field 2) echoes that guard only after the provider enforced it atomically.
  • A checked client must match the confirmation before granting data credit; a missing confirmation from an older peer fails that logical channel with Unsupported instead of silently downgrading.
  • Malformed nonempty guards decode to InvalidArgument; the property test asserts the exact result for all generated inputs, and the fuzz corpus includes the reported 31-byte guard.
  • Rust codec helpers preceding_follow and confirm_follow implement guard decoding and confirmation; the proto descriptor, TS bindings, and protocol gate check are regenerated and extended.
  • Existing unchecked callers default the new guard, keeping prior wire behavior intact.
  • Existing field numbers are preserved; native, TS, and browser adapters must implement the check before exposing checked follows.

Review fix at signed head 142e402743a7e143526fe792eed9f999841b34e8: malformed nonempty guard decoding maps to InvalidArgument. The shrinking property now asserts the exact result for all generated inputs, and the fuzz target/corpus include the reported 31-byte ALL/next=1 guard. All three codec properties pass in 0.02 s from the built binary. The refreshed debug ASan fuzz run passed 256 inputs in under one second, loading all five seeds including the short guard (1,657 coverage edges). It explicitly selects x86_64-unknown-linux-gnu because the runner's musl default failed ASan/toolchain setup. The checked codec, property and fuzz source are unchanged in the #557 validation tree that ran the fuzz check. Required land order: #647 -> #557 -> #579 -> #650 -> #644.