feat: peer protocol compatibility check between jack instances#23
Merged
Conversation
- Add version module (SERVER_VERSION, MIN_PEER_PROTOCOL_VERSION, compareVersions)
- Add authenticated /handshake endpoint returning { name, version }
- Gate PeerConnector init on handshake version check
- Surface peer version in /servers output
- Old/incompatible peers fail init with clear IncompatiblePeerError
Closes #8
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
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.
Summary
Closes #8.
Versions jack at
0.1.0and makes peer-protocol mismatches fail loudly instead of silently returning empty results. The version doubles as the peer-protocol version, and a new authenticated/handshakeendpoint lets peers negotiate compatibility at connect time.Changes
lib/version.ts):SERVER_VERSION+MIN_PEER_PROTOCOL_VERSION(both0.1.0) and a dependency-freex.y.zcomparator (compareVersions,isPeerVersionCompatible).GET /handshake: returns{ name: 'jack', version }. Mounted behindrequireApiKey(the unauthenticated/pingDocker health check is untouched), so a wrong API key still fails loudly at connect time.PeerConnectorcompatibility gate: init now pings/handshake, reads the response defensively, and throws a clearIncompatiblePeerError(Peer "<name>" runs an incompatible peer-protocol version: expected >= 0.1.0, got <X>) when the peer's version is too low, missing/malformed, or the endpoint 404s (old pre-handshake peers). Connectivity/auth errors (network, timeout, 401) propagate unchanged. The failure surfaces in/serversvia the existinginitialized/initializationErrorfields./serversversion field: each peer's reported version is stored (peerVersiongetter) and exposed in the/serversoutput.Behavior for older peers
Older jacks have no
/handshakeroute, so they 404 → treated as an incompatible protocol version and rejected with the clear mismatch error, exactly as required.Tests
New:
version.test.ts,handshake.test.ts,peer-handshake.test.ts(compatible peer, low version, missing/null version, 404 old peer, 401 auth-not-misreported, and the/serversversion contract). Full suite: 193 passing, lint + typecheck clean.Greptile Summary
This PR introduces a peer-protocol compatibility gate between jack instances: a new authenticated
GET /handshakeendpoint reports{ name, version }, andPeerConnector.runInit()now calls it, rejects peers belowMIN_PEER_PROTOCOL_VERSION(0.1.0) with a clearIncompatiblePeerError, and surfaces the negotiated version in/servers.lib/version.ts: AddsSERVER_VERSION,MIN_PEER_PROTOCOL_VERSION, and a dependency-free semver comparator (compareVersions,isPeerVersionCompatible).GET /handshake: Authenticated endpoint (behindrequireApiKey) returning the server's identity and version; mounted only whenconfig.jackis present, leaving the unauthenticated/pinghealth check untouched.PeerConnectorhandshake gate: Replaces the old/peer/searchping; 404s from pre-0.1.0 peers are converted toIncompatiblePeerError; the negotiated version is stored aspeerVersionand exposed in/serversviastringifyPeer.Confidence Score: 4/5
Safe to merge after addressing the stale peerVersion in /servers after a failed retry.
The handshake gate, version comparator, and error handling are all correct. The one concrete defect is that _peerVersion is never cleared at the start of runInit(): if a peer successfully handshakes, later goes offline, and a retry fails, /servers keeps reporting the old version alongside initialized: false, surfacing inaccurate state to callers.
apps/backend/src/lib/servers/peer.ts — the stale peerVersion reset.
Important Files Changed
Sequence Diagram
sequenceDiagram participant PC as PeerConnector (local) participant PE as Peer Jack (remote) participant SC as ServersController PC->>PE: GET /handshake (X-Api-Key) alt 404 (pre-0.1.0 peer) PE-->>PC: 404 Not Found PC->>PC: throw IncompatiblePeerError(got none) else 401 (bad API key) PE-->>PC: 401 Unauthorized PC->>PC: throw FetchError (propagated as-is) else 200 OK PE-->>PC: "{ name: jack, version: 0.1.0 }" PC->>PC: isPeerVersionCompatible(version)? alt version below minimum or missing PC->>PC: "throw IncompatiblePeerError(expected >= 0.1.0)" else version compatible PC->>PC: "_peerVersion = version, isInitialized = true" end end SC->>PC: listServers() PC-->>SC: "{ initialized, initializationError, peerVersion }" SC-->>SC: "stringifyPeer → { version: peerVersion }"Reviews (2): Last reviewed commit: "fix: compare versions via OR instead of ..." | Re-trigger Greptile