Skip to content

20260827 - Ship no location by default - #34

Merged
Purple10101 merged 1 commit into
mainfrom
20260827-null-default-location
Aug 27, 2026
Merged

Purple10101 merged 1 commit into
mainfrom
20260827-null-default-location

Conversation

@Purple10101

Copy link
Copy Markdown
Collaborator

The change that actually stops nodes telling the server a location nobody chose. (86cba5qt4)

Warning

Release this last. Everything that reads the config has to tolerate a null first:

retina-gui#74 is not ordering-critical; current main already copes.

Why

default.yml shipped a complete, plausible geometry: Greenwich Observatory as the receiver, Crystal Palace as the illuminator. config-merger writes it on first boot, so from power-on every consumer saw a populated location and none could tell an unconfigured node from a configured one. Nodes registered with the server claiming to sit in south-east London, poisoning the fleet's position data with values nobody chose.

What

Keys stay, with null values, rather than being removed. Consumers need to tell "unset" from "absent because this config is malformed", and retina-gui's config form renders from these keys.

The merger was substituting 0 for a missing coordinate, which is not a neutral value: it is Null Island, a real place the node then claimed to be. Worse, ADSBLOL_ENABLED stayed true, so the adsb.lol query asked for aircraft within ADSBLOL_RADIUS of 0,0 and fed them to blah2 as ground truth. The receiver block is now omitted when unset, and adsb.lol is forced off whatever adsblol_fallback says — the query is a radius around the receiver, so with no receiver there is no query to make, only a wrong one.

Omitting the vars does not fully undo the zero on its own, because tar1090-node's compose uses ${RECEIVER_LAT:-0} and its proxy does parseFloat(... || '0'). Disabling adsb.lol is what actually prevents false truth; the omission stops us asserting a position we do not have.

Coordinates are tested against None rather than for truthiness, so an owner who genuinely sets 0,0 keeps it.

Release note

config/default.yml and config-merger/script/merge_config.py both bake into the same retina-config-merger image, so they cannot be separated. But that image is pinned by CONFIG_MERGER_V in this repo's own compose, so the pin has to be bumped to the new build or the release looks clean while the old default.yml keeps shipping. That pin has sat frozen before — it was stuck at v0.3.17 across six releases.

Testing

4 new merger tests. test_actual_config_files pinned default.yml's real coordinates and correctly failed on this change — it now asserts the new intent, and still checks the sited case when a location is present.

Verified end to end on owl-ded9 with the full stack running unsited, via the real merger image and the real retina-node.service (node fully restored afterwards; user.yml and config.yml checksums confirmed identical to baseline):

Result
blah2 (C++ radar) Started and ran normally — it reads only capture, network, process, save
/api/detection HTTP 200 — radar data path unaffected
/api/adsb2dd HTTP 400 — ADS-B truth correctly refused
tar1090 Up and healthy with RECEIVER_* absent
retina-telemetry Held registration, explained why, zero requests
Re-siting Picked up within 40s, no restart

Also confirmed the coupling is real: running the new default.yml against the old merger script produced RECEIVER_LAT=None and ADSBLOL_ENABLED=true, which is worse than today. Same image, so it cannot happen in practice, but it is why the merger fix is in this PR rather than a separate one.

Not verified: ran from a mounted script and defaults dir, not from a built image via Mender.

🤖 Generated with Claude Code

default.yml shipped a complete, plausible geometry: Greenwich Observatory
as the receiver, Crystal Palace as the illuminator. The merger writes it on
first boot, so from power-on every consumer saw a populated location and
none could tell an unconfigured node from a configured one. Nodes
registered with the server claiming to sit in south-east London.

Keys stay, with null values, rather than being removed. Consumers need to
tell "unset" from "absent because this config is malformed", and
retina-gui's config form renders from these keys.

The merger was substituting 0 for a missing coordinate, which is not a
neutral value: it is Null Island, a real place the node then claimed to be.
Worse, ADSBLOL_ENABLED stayed true, so the adsb.lol query asked for
aircraft within ADSBLOL_RADIUS of 0,0 and fed them to blah2 as ground
truth. The receiver block is now omitted when unset, and adsb.lol is forced
off whatever adsblol_fallback says.

Omitting the vars does not fully undo the zero on its own, because
tar1090-node's compose uses ${RECEIVER_LAT:-0} and its proxy does
parseFloat(... || '0'). Disabling adsb.lol is what actually prevents false
truth; the omission stops us asserting a position we do not have.

Coordinates are tested against None rather than for truthiness, so an owner
who genuinely sets 0,0 keeps it.

DEPLOY LAST. Everything that reads this config has to tolerate a null
first: retina-telemetry's _require raised, blah2-api dereferenced it
unguarded, and retina-gui's schema rejected it. All three are fixed on
their own branches; this is the change that makes the null real.

test_actual_config_files pinned default.yml's real coordinates and caught
this, which is what it is for. It now asserts the new intent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Purple10101
Purple10101 merged commit ff235e6 into main Aug 27, 2026
1 check passed
@Purple10101
Purple10101 deleted the 20260827-null-default-location branch September 6, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant