server: relay a test device's adb endpoint, because mDNS does not cross subnets
The beacon this replaces was a separate service wildcard-bound to 0.0.0.0:443 - it silently occupied port 443 on the reserved measurement addresses, voiding the IPv4 interception proof for as long as it ran, and it accepted a port report from anyone who could reach it. So this lives where the repo's own post-mortem said it belongs: POST on the control plane authenticated by the device credential, GET on the admin UI behind the existing apiAdmin helper. No new listener, no new port, no wildcard. Entries expire after 24h (ECHOLOT_ADB_ENDPOINT_RETENTION_H) on both write and read - a LAN address is a breadcrumb for driving a test device, not measurement data worth keeping. Also records the BLE peer-comparison design: the case for it is that BLE is out-of-band, which is what makes client isolation measurable at all - silence over IP cannot distinguish an isolating AP from an absent peer, and a peer confirming out-of-band that it was listening turns that silence into proof. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ab6e278272
commit
ae63bd7c7f
@@ -1379,6 +1379,60 @@ poisons `/releases/latest` for the string-comparing updater the moment anyone ta
|
||||
The stale `server-v0.9.2` release (same code lineage, wrong number, created during the confusion)
|
||||
remains in Gitea but is harmless now that v0.11.3 outranks it as latest.
|
||||
|
||||
## Design note: what BLE between two devices is actually for (2026-08-02, not built)
|
||||
|
||||
Two or more phones running Echolot, talking over Bluetooth LE. The schema already anticipates
|
||||
this — `Trigger.PEER` and the whole `peer.*` test family (`peer.reachability`, `peer.isolation`,
|
||||
`peer.multicast`, `peer.lan_train`, `peer.lease_diff`) are in the registry, unused — and the
|
||||
prober measured `peer.ble_advertise` **SUPPORTED on both known devices**, so the mechanism is
|
||||
proven; what has been missing is a reason that beats "use the server".
|
||||
|
||||
**The reason is that BLE is out-of-band.** Everything else this app does depends on the network
|
||||
under test being at least partly functional. A second device reachable over a radio that shares
|
||||
nothing with the wifi turns several measurements from ambiguous into conclusive:
|
||||
|
||||
1. **Client isolation becomes measurable at all.** Today, "I sent a packet to the peer and heard
|
||||
nothing" cannot distinguish AP client isolation from the peer being asleep, gone, or on a
|
||||
different VLAN — the failure mode is silence, and silence has too many parents. With BLE the
|
||||
peer confirms out-of-band that it was listening on address X at time T, so silence over IP
|
||||
becomes *proof* of isolation rather than a guess. This is the single strongest argument for
|
||||
the feature, and it mirrors the rule this project keeps rediscovering: a measurement that
|
||||
cannot separate "nothing happened" from "nothing was tried" is not a measurement.
|
||||
2. **Differential diagnosis: the network or this phone?** Two devices on the same SSID, one
|
||||
resolving DNS and one not, settles in seconds what a single device cannot settle at all —
|
||||
and it is the same distinction `system_verdict` exists to draw, only with a second opinion
|
||||
instead of Android's. Natural finding: *this device fails where a peer on the same link
|
||||
succeeds* → look at the device (private DNS, ad blocker, per-client router rule, MAC
|
||||
randomization), not the router.
|
||||
3. **Two DHCP servers on one L2**, the classic invisible fault: peers compare lease source,
|
||||
subnet and gateway (`peer.lease_diff`). Disagreement is conclusive and needs no server.
|
||||
4. **Coverage and roaming**, later: several devices sampling RSSI in different rooms, exchanging
|
||||
summaries over BLE, gives a picture no single device standing in one place can produce.
|
||||
|
||||
**What crosses the link is a summary, never the document.** A measurement document describes
|
||||
someone's home network in detail; broadcasting it to whoever is nearby would betray the whole
|
||||
posture of §8. The peer payload should be: a *hashed* network identity (so two devices can agree
|
||||
they are on the same L2 without either putting the SSID/BSSID on the air in the clear), the §7.3
|
||||
category verdicts, the finding codes, and an IP endpoint plus a one-shot nonce for the LAN tests.
|
||||
Findings and verdicts are already the interpretation layer — exactly the right granularity to
|
||||
share.
|
||||
|
||||
**Privacy constraints, which are not optional here.** A BLE advertiser is a tracking beacon: it
|
||||
must be user-initiated, time-boxed to the run, carry no identifier that is stable across runs
|
||||
(the resolvable-private-address default plus a per-session ephemeral id), and pair by a code the
|
||||
two humans can see. "Discoverable by default" would make this app a worse citizen than the
|
||||
networks it audits.
|
||||
|
||||
**Deliberately not doing:** clock synchronisation over BLE. GATT latency is jitter measured in
|
||||
tens of milliseconds, which is the same order as the one-way delays worth measuring; peers should
|
||||
sync against the server's `time.server_offset` and use BLE only to correlate run ids. Nor should
|
||||
BLE become a transport for uploads — it is a *comparison* channel.
|
||||
|
||||
Staging when it happens: `peer.isolation` first (highest value, needs only advertise + connect +
|
||||
a nonce exchange), then `peer.lease_diff` (pure summary comparison, no extra plumbing), then the
|
||||
rest. Needs `BLUETOOTH_ADVERTISE/CONNECT/SCAN` in the manifest, which the app does not yet
|
||||
request.
|
||||
|
||||
## v0.11.3 live on fmr; trains validated end to end (2026-08-02)
|
||||
|
||||
Deployed via `--self-update` (the pre-signing v0.11.2 updater accepted the first signed release,
|
||||
|
||||
Reference in New Issue
Block a user