Repository navigation
fix(gps): coarse live broadcast precision by default, full is opt-in - #16
Merged
Merged
Conversation
Split stored from broadcast geotag precision at the gps.py emission seam. Stored captures keep gps_precision (default full, operator's own files); gps_status, emitted capture geolocations and ISM-contact receiver locations now cross to all sockets at gps_broadcast_precision (default ~1km, fail-closed on unknown), full only on explicit opt-in. Existing gps_precision choices are untouched; existing installs get coarse broadcast until they opt in.
This was referenced Oct 18, 2026
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.
With GPS on, the live map/GPS pill and any location in socket payloads now show ~1 km coarse position by default, not your exact position. Captures on disk are not degraded (see below). To restore exact live position, set Diagnostics → "Live broadcast precision" → "Full — shares exact location live". That full setting shares your exact location with everyone who can connect (any local process on loopback with no token, or any token holder).
Addresses parked SECURITY question #4 only. #5 (capture routes / absolute paths) is untouched — no path exposure changed here.
Evidence (stored vs broadcast — they were already two paths)
backend/gps.py— local gpsd (127.0.0.1:2947,AETHERSCOPE_GPSD_HOST/PORT), opt-ingps_enabled(default off,AETHERSCOPE_GPS=0hard-off). No config-file lat/lon receiver position in the GPS path (ADS-B/scanrx_lat/rx_loninputs are separate, operator-typed).gps.py,_PRECISION_DECIMALS):full= exact,100m= round 3dp (~0.001°),1km= round 2dp (~0.01°). (Note: task brief saidconfig.py:125; in this tree the default lives inapp.pyget_setting("gps_precision", "full")—config.pyholds only the demod vocabulary.)_receiver_geotag()(app.py, IQ captures + ISM-contact receiver location) and audio-record start both appliedcoarsen_geolocation(geo, gps_precision default "full")into sidecar/SigMF (sigmf.pycore:geolocation) and the contacts DB. Per-capture redaction already exists.gps_statuswas emitted raw full precision from three sites —GpsClient(on_status=…)on every TPV/SKY,_emit_gps_status(), and the connect snapshot — to all connected sockets (socketio.emit, no room scoping). Frontend used it for the ADS-B map receiver pin (aether-adsb.js), GPS-pill hover coords (aether-core.js, toFixed(6)), and "Use GPS location". The captures list also emitted the stored geolocation, and ISM contacts emitted receiver lat/lon; ADS-B contacts/aircraft carry the aircraft's position, not the receiver's.<select id="gps-precision">viaset_setting(allowlisted), persisted instore.pysettings; its label honestly said stored-only ("The live map shows full precision") — that live full precision is exactly Publish one current job with a required status label #4.Decision
gps.pyis the deep module;broadcast_position/broadcast_geolocationare its interface, unknown values fail closed to coarse):gps_status, emitted capturegeolocation, ISM-contact receiver lat/lon): newgps_broadcast_precision, default1km(the coarsest existing level),100m/fullexplicit opt-ins. All threegps_statussites unified through_broadcast_gps_position().gps_precisiondefaultfull, operator's configured choice preserved. Recordings are not silently degraded.gps_precisionvalues keep their exact stored meaning. Existing installs have nogps_broadcast_precision, so they get coarse broadcast (the security fix) until they explicitly opt into full; new installs same default.Tests (TDD, failing-first)
tests/test_geotag_broadcast.py(7 tests, written first — ImportError red): default emitted payload rounds 38.723298→38.72 and ≠ raw, storedcoarsen…("full")unchanged, explicitfullopt-in emits exact,100mrounds 3dp, unknown value fails closed, no-fix passes through, and a source guard that no rawgps_statusemission remains + allowlist contains the new key._broadcast_precisionto"full"→ 4/7 red; restored → 7/7.tests/test_waterfall_split.pyintentional drift noted inline (newgps-broadcast-precisionDOM id, socket.emit sites 47→48 for the new control; event-name sets unchanged).Verification (CI-way, local snapshot)
tests/test_*.pypass (incl. gps 13/13, broadcast 7/7, waterfall 7/7 after guard note, auth 12/12).check_html_templates0 untagged,check_architecture_namespass,node --checkall frontend JS pass.Self-review (pocock-code-review, Standards/Spec separately): Standards — emission logic in one place in
gps.py, callers only name the setting, no new module (architecture-names intact, architecture.md updated), frontend is one select + restore wiring. Spec — #4 only, stored preserved, no #5/path changes, absolute-path fields untouched.