feat: RFC 0002 Local Peer Discovery - #2
Open
gmaclennan wants to merge 2 commits into
Open
Conversation
gmaclennan
force-pushed
the
feat/RFC-0002-local-peer-discovery
branch
from
August 25, 2026 15:47
fe1a9fd to
4180b05
Compare
3 tasks
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.
Rendered: https://github.com/digidem/comapeo-rfcs/blob/feat/RFC-0002-local-peer-discovery/rfcs/0002-p2p-discovery.md
Stacked on #1: the broadcast hints derive from RFC 0001's project secret
S_P, and discovery hands off to its connection layer.Summary
Local discovery today is mDNS-only, lives in the host app, and fails in ways common in the field (multicast-blocking routers, no shared network, broken Android NSD). This RFC moves all discovery into
@comapeo/core-react-native, adds a BLE transport that works screen-off and network-free, and upgrades what discovery says: rotating, member-only hints that convey "a co-member with data you don't have is nearby, on this/another WiFi network" without broadcasting anything a bystander can use to track a device or confirm membership beyond the current day.Key points for reviewers
The 24 h epoch default (§8). All hints rotate on a floored UTC day, chosen for clock-skew tolerance on field devices over tighter unlinkability — within a day, hints are linkable by a repeat observer. The scan-side previous/current/next overlap is free, but the period itself is the privacy lever.
State-hash gossip (§7). Broadcasting a 4-byte epoch-salted digest of sync state lets a scanner see "our states differ, worth connecting" passively — a new, deliberate information disclosure. The namespace set (excluding
blob) and the epoch salt are what keep it from being a false-positive generator or a cross-day fingerprint.The 31-byte beacon (§9.1, §10). Manufacturer data with no service UUID (a 128-bit UUID would spend 18 of 31 bytes), 2-byte truncated project hashes with accepted false positives, and one project per beacon with weighted round-robin rotation for multi-project devices — latency for many-project devices is the cost.
iOS as a silent participant (§9.3). iOS cannot advertise manufacturer data or run BLE in the background, so it scans only and introduces itself over a GATT write to the Android advertiser. Consequences accepted: an idle iOS device is undiscoverable, and iOS↔iOS BLE does not exist (mDNS covers it on a shared network). The rejected alternative — foreground service-UUID advertising — is §17.4.
Checklist
Open questions
From §19, the ones that need answers during review rather than implementation:
S_P(stops bystanders confirming SSID guesses, but one token per project instead of one per device), and SSID vs BSSID granularity.auth/config/data/blobIndex(excludingblob) yields "equal ⟺ nothing to sync" in practice, including partial-download edge cases.