Repository navigation
Let paired machines reconnect after address changes - #55
Merged
Merged
Conversation
…ming A paired machine can change networks while its member record retains only the old LAN endpoint. Learn a bounded, expiring set of endpoints from pinned roster connections and each authenticated peer’s self-report, retain the pairing-time fallback, and budget unproven dials across concurrent reconciles and restarts. Every application connection still verifies the exact pin and refuses redirects. Keep address hints local to members.json rather than extending the JSON-RPC projection. Serialize learning with admission removal, ignore discovery and third-party address claims, and update cluster-derived manual-node entries without changing saved entries. Add unit regressions and an isolated real-worker roaming/restart/removal test for CI. Bump cluster-manager for the additive roster field and manual-nodes for the endpoint-refresh fix. Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
Scanner starts before node-info has necessarily opened its listener. Give only the first local enrichment read a bounded fifteen-second readiness budget using the existing telemetry backoff. Normal startup stays quiet; exhaustion still warns and subsequent outages retain immediate transition reporting. Cover delayed readiness and a sustained outage, and bump the scanner patch version. Signed-off-by: Jared Ping <13906915+JaredP94@users.noreply.github.com>
Owner
Author
|
CI note before merge: on run 42202311657, five of six jobs passed, including both cross-process jobs (Linux: 123 passed, 0 skipped; macOS passed on re-run). The "Go modules (macos-15)" job was cancelled twice without acquiring a runner (GitHub macOS arm64 capacity). It never started. That job's exact steps were run instead on macOS arm64 at bfb09d9 with the CI toolchain (Go 1.26.7): |
7 tasks done
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.
Description
Let a paired machine recover when its peer moves away from the LAN address recorded at pairing. Learn a bounded, durable set of address hints from pinned cluster mTLS roster traffic, without treating an address or name as identity. Also give the scanner's first local node-info read a bounded readiness grace so normal startup does not report an outage.
Scope
9213215c: cluster-manager alone owns learned hints incluster/members.json(atomic writes, 0600), keyed to the member/admission. Sources are the authenticated inbound connection's source host, the pinned sender's own additiveselfAddressesHTTP roster field, and successful pinned outbound roster responses. Discovery, public previews, and third-party relayed addresses cannot teach this set.bfb09d9b(separate commit): first local node-info enrichment retries using existing 2/4/8-second telemetry backoff under one 15-second budget. A sustained outage still warns; subsequent outages are reported immediately.Validation
Isolated worktree
/tmp/pair-work/peer-roaming, branchfix/peer-address-roamingfromorigin/mainat9d3c71e2(0.9.0). Implementation written directly, not delegated. Rebased before push; no changes to engine-manager or shared/jsonrpc.go test -race -count=1 ./...passed in cluster-manager, manual-nodes and scanner. Full cluster-manager non-race suite passed too. Native/Linux/Windowsgo vet ./...passed in all three modules and the cross-process test module.gofmt -lclean;git diff --checkpassed.node scripts/spdx-headers.mjs: 1423 checked, zero missing.npm ci --no-audit --no-fund; desktop typecheck, lint with--max-warnings=0, 936 tests across 94 files, dead-code check, service-contracts:write and service-contracts:check passed. No desktop source changes.TestRoamingSelfReportsBelongOnlyToPinnedSender,TestRoamingCandidatesBoundedOrderedPersistedAndExpired,TestRoamingIgnoresDiscoveryAndRelayedAddresses,TestRoamingInboundSourceSurvivesRestart,TestRoamingPinnedPeerCannotRedirectCandidateDials,TestRoamingSuccessfulPairingFallbackBecomesMostRecent, thecluster_seedsubtest ofTestClusterSeedFollowsRoamingAddressWithoutOverwritingSavedEntry,TestLocalNodeInfoStartupWaitsBeforeWarning, andTestLocalNodeInfoRealStartupOutageEventuallyWarnsall failed on missing behavior (not compile errors). Restored implementation passes. The hostile-certificate guard already passed on origin/main and is retained, not claimed as a newly failing regression.TestRoamingCandidateValidationAndIPv6Zones,TestRoamingNewCandidateDialBudgetSurvivesClaimChurnAndReload,TestRoamingInFlightRequestCannotRestoreRemovedMember,TestRoamingLearnsSelfReportFromPinnedResponseOnly,TestRoamingSuccessfulPairingFallbackBecomesMostRecent, andTestRoamingNewCandidateNeedsDurableDialBudget. The durable-write regression failed before withholding the new dial, then passed with the fix.TestPeerRoamingLearnsInboundAndDialsAfterRestart: real isolated workers, stale recorded address, pinned inbound repair, persisted pairing fallback, restart, then successful authenticated removal delivery at the learned endpoint. No cross-process tests were run locally; CI supplies that evidence.Latest-head CI: run 42202311657, head bfb09d9. Four of six jobs passed: SPDX, desktop checks (including contracts/licenses), Linux Go modules, and Linux cross-process. Both macos-15 jobs never acquired runners (
runner_nameempty, zero steps) and were cancelled after about 15 minutes. In particular, Go modules (macos-15) never acquired a runner. The run concludes failure; all-six-job success is not confirmed, and macOS cross-process remains untested in CI.Downloaded
cross-process-ubuntu-latestusinggh run downloadinto the new empty directory/tmp/pair-review/peer-roaming-linux-42202311657-EOGsoW. Ran exactlypython3 -I /tmp/pair-review/scripts/noskip.py /tmp/pair-review/peer-roaming-linux-42202311657-EOGsoW/cross-process.jsonl: 123 passing cases, zero failures, ZERO skips.TestPeerRoamingLearnsInboundAndDialsAfterRestartpassed in 5.14 s. Artifact contents were parsed, not executed. No cross-process suite was run locally.Risk
Address hints are not identity authority: wrong/hostile endpoints fail the exact pin check. At least one authenticated rendezvous path must remain; if both machines lose every known address, explicit reachable configuration is still needed. Old peers may omit
selfAddresses; inbound source learning and the pairing fallback still work. Certificate endorsements continue to establish transitive membership, but a relayed third-party address is no longer an address-learning source. The scanner can take up to 15 seconds to finish its first local inventory enrichment during a real outage; its control reader remains independent.Unit/CI evidence is not live two-Mac, Windows runtime, packaged-asset, signing or notarization certification.
Checklist
git commit -s), certifying the Developer Certificate of Origin.services/versions.json, and described user-visible changes above so they reach the release notes.