Skip to content

Phase 3: /id-sync/1 is used by both range and LogSync handshakes #179

Closed

Description

@dezren39

The range session starts after a Request/Answer on /id-sync/1, and LogSync sends Request first. Confirm one handshake covers both and that a responder answering a method it was not asked for is refused.

Activity

  1. dezren39 commented on Oct 24, 2026

    @dezren39
    MemberAuthor

    id train triage (2026-10-24): needs-decision — project owner: single /id-sync/1 handshake for range + LogSync (confirm one covers both, and unanswered methods are refused).

  2. added
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    on Oct 27, 2026
  3. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

    • Agent: queue worker (repo-worker-code), Lane B shift
    • Session / ID: queue task 2022 (triage)
    • Found via: queue claim
    • Task: Triage Phase 3: /id-sync/1 is used by both range and LogSync handshakes #179 — /id-sync/1 used by both range and LogSync handshakes
    • Expectation: Done — verdict: confirmed, half-built at HEAD. Follow-up fix packet enqueued as queue task 2970.
    • Links: Follow-up task 2970 · pkgs/id/src/log_sync.rs · pkgs/id/src/sync_method.rs · pkgs/id/src/event_sync.rs

    Verdict (fresh HEAD reads, this shift)

    What is already true:

    • One ALPN: log_sync.rs SYNC_ALPN and event_store/sync.rs ALPN are both b"/id-sync/1", and log_sync's module doc states the design intent — range sync joins as a method of the same session, first frame is the Request.
    • One handshake shape covers both methods in sync_method.rs / log_sync.rs: initiator sends Request { topic, method } (SyncMethod::{Log, Range}, chosen by choose()), responder answers Answer::Agree(method) or Answer::Refuse.
    • The refusal the issue asks about is implemented and tested: the initiator errors when an Answer names a different method than requested (dedicated SyncError variant), the responder sends Refuse for a method it does not support, and a test in log_sync.rs covers "peer answers Range when Log was asked — the initiator must refuse it."

    What is not yet true (the confirmed remainder):

    • run_agreed in log_sync.rs dispatches SyncMethod::Range to SyncError::NotWired, and LogSyncOnly refuses Range — so under the shared handshake, Range is a dead end today.
    • The /id-sync/1 acceptor serve actually registers (event_sync::EventSyncProtocol for the LocalEvents store, added for id phase-8/platform-completion: ProseMirror save revisions are signed and stored locally but never replicated to peers #792) runs range sessions with no Request/Answer first frame — a second, different session shape on the same ALPN. A peer opening with one shape can be misread by an acceptor expecting the other, instead of refused.

    Route: scoped small_fix follow-up enqueued as queue task 2970: wire Range dispatch under the handshake, and bring serve's range acceptor under the same first frame (or split it to a distinct ALPN, documented). Refusal semantics stay as-is.

  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

    • Agent: queue worker (repo-worker-code), lane A shift
    • Session / ID: queue task 2970
    • Found via: queue claim
    • Task: Fix Phase 3: /id-sync/1 is used by both range and LogSync handshakes #179 — wire SyncMethod::Range dispatch in log_sync run_agreed under the Request/Answer handshake and end the second session shape on /id-sync/1 (event_sync acceptor speaks the same first frame, or moves to a distinct ALPN with the split documented).
    • Expectation: branch + PR this shift (CI-first verification); refusal semantics unchanged and tested.
    • Links: triage verdict: task 2022 on this issue
  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 29, 2026
  6. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

    Progress — the two session shapes no longer share an ALPN in serve

    Done (PR #2214, commit a472fec): the serve-registered range acceptor moved to a distinct ALPN, /id-range-sync/1 — the option this issue's text explicitly allows ("or split it onto a distinct ALPN with the split documented in code"). The split is documented in event_store/sync.rs (module + ALPN docs), event_sync.rs, and log_sync.rs (SYNC_ALPN docs); dialer and acceptor both read event_store::sync::ALPN, so they move together; a peer on an older build fails the dial and serve retries next interval. A new event_sync test pins both ALPN values and asserts they differ. CI on the PR is the verification (fleet CI-first rule); the two-node event_sync tests exercise the new ALPN end to end.

    Remainder (why #179 stays open): wiring SyncMethod::Range in log_sync::run_agreed. Verified against current code, this is a design step, not a dispatch arm:

    • run_agreed(store: &SharedEventStore, topic, method, frames: &mut Frames) holds ONE already-open stream pair; range sync (event_store::sync::run) opens its own stream pair from a Connection and also uses the connection for the pull-gate peer check and cut/close handling. Range sync first needs a stream-level entry point (send/recv + peer id) that both call sites can use.
    • Range sync needs &mut EventStore for the whole session; SharedEventStore is Arc<RwLock<EventStore>> (std lock, short holds by design — its ingest path deliberately avoids session-length holds, which is why log_sync has an ingest worker). A session locking design is needed (e.g. a tokio-mutex session handle like LocalEvents uses, or a dedicated range_session method on SharedEventStore with documented starvation semantics).
    • Range sync's set is the whole store; the handshake's Request.topic has no range equivalent yet — the resumed work must say what topic means for an agreed Range session (store-wide, documented, is the honest current semantic).
    • SyncSupport: whoever registers SyncProtocol in production must then advertise Range; today LogSyncOnly refuses it, which stays correct until the dispatch exists.

    Refusal semantics are untouched by PR #2214 and remain tested (log_sync mismatch/refusal tests).

  7. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    and removed
    queue/claimedQueue worker lifecycle state
    on Oct 29, 2026
  8. 86 remaining items

  9. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    Lane D (queue task 2970) resumed from checkpoint merge_ready. Fresh revalidation 2026-10-29T23:25Z: PR #2214 OPEN/MERGEABLE at 7154a76; all checks SUCCESS except clippy-lint (the failure prior shifts attributed to the #2401 infra pattern; tests incl. test-unit and all shards pass); both Codex inline findings have disposition replies on their threads. Blocker #2403 still open, main still 5a34fa7. Attempting one fresh merge-queue enqueue this shift (another PR is currently queued, so queue health can be observed); if ejected per #2403, the task re-parks.

  10. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    Lane D (queue task 2970): merge-queue enqueue attempted — PR #2214 entered 23:26:29Z at position 2 behind #2447; by ~23:30Z the queue was empty, PR still OPEN, main still 5a34fa7. Fresh confirmation of blocker #2403 (evidence posted there). Task re-parked. Resume: MQ healthy / main advances → enqueue #2214 → merge → complete fixed_merged + close this issue.

  11. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Oct 29, 2026
  12. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up → parked

  13. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    Lane A (queue task 2970): verified terminal state fresh — PR #2214 MERGED 2026-10-30T01:00:10Z (merge commit 88636ed), blocker #2403 CLOSED, main advanced to 7d1b081. The parked resume condition was met and the merge landed under a prior shift; this issue closed 2026-10-30T01:16:04Z. Task 2970 completing as already_done; stale queue/status/work labels removed.
    🤖 Agent note · picked up → done (already_done)

  14. removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    work/assignedQueue worker lifecycle state
    on Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions