Conversation
tower-finder-service has owned the tower API since the monolith's copy was
deleted, and it now owns the UI too: it builds its own SPA and serves it from
its own edge. On 2026-09-14 the Cloudflare origin rules moved towers.retina.fm,
its staging and test counterparts and the fleet's tower-finder.retina.fm onto
port 8443, so all four names reach the service and none of them reach us.
That leaves the copy here dead rather than merely redundant. frontend/dist is
served on HOST_MAIN, HOST_MAP and HOST_TESTMAP only, and isMapDomain already
hid the tower tab on the latter two, so with HOST_MAIN flipped away the tab was
reachable on no live surface. The service's copy had also moved well ahead of
it, gaining address geocoding, rank tiers and a working frequencies parameter,
so keeping ours invited exactly the split-brain that 86capx9mv was raised to
end.
Every surface this bundle still serves is a live map, so the hostname-dependent
header goes with it and App renders one surface unconditionally. That also
settles, by deletion, the "Tower Finder" display label left open during the
rename: it named a surface that no longer ships from here. Because .map-surface
is now always set, the dark physics-tab background it used to override was dead
too, and collapses into the light rule.
Nothing about nginx changes here. Every vhost keeps forwarding /api/towers,
/api/elevation and /api/config to the service exactly as before, including the
${HOST_LEGACY_REDIRECT} vhost that carries the fleet's name. Retiring that vhost
is a separate change, deliberately held back: while it exists, deleting the
Cloudflare origin rule is still a working rollback for the fleet.
The entry chunks every map surface loads drop from 56.66 to 43.84 kB of JS
(gzip 18.04 to 14.08) and 26.45 to 19.23 kB of CSS (gzip 5.67 to 4.13).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
${HOST_LEGACY_REDIRECT} existed to proxy tower-finder.retina.fm, the name the
fleet calls, to tower-finder-service. Since the origin flip of 2026-09-14
Cloudflare sends that name to the service's own edge on 8443, so nothing
reaches this vhost and it is dead weight.
Held back from the UI removal it was originally part of, because it carries a
risk that change does not. Until this merges, deleting the Cloudflare origin
rule is a working rollback: the name lands here and this vhost proxies it on.
Afterwards it is not, and worse than merely absent. The template declares no
default_server on 443, so nginx falls back to the FIRST 443 block, which is the
towers SPA. A node calling /api/towers would then be answered with an HTML page
and a 200, and fail on decode rather than on a status it can branch on.
Merge this only once the flip is trusted enough to give that rollback up. A
catch-all default_server that refused unmatched hostnames outright would turn
the failure loud, and is worth doing, but it changes behaviour for every
unmatched name rather than this one and belongs in its own change.
EXPECTED_TLS_VHOSTS drops 8 to 7 alongside the removed vhost; it is hardcoded
and fails all three environments at once if left behind.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Claude finished @Babissimo's task in 1m 55s —— View job Review: Retire the fleet's legacy vhostTodo list
SummaryScoped and clean. This diff (against Checked:
No bugs, no dangling references, no inconsistency between the template, the two Python scripts, the four compose overlays, and the test fixtures. Not verifiedI could not execute anything in this sandboxed environment — no Process note (not a code issue)The PR is explicit that merging is gated on the Cloudflare flip being trusted, not on code review — worth a human confirming that gate before merging, since nothing in CI enforces it. |
b9b8ecb to
a20362f
Compare
Ticket: https://app.clickup.com/t/123zgec2zw1
Stacked on #389. Base is
worktree-retire-tower-ui, so review that first; this diff is only the vhost removal. Needs agit rebase --ontoonce #389 squash-merges.What this does
${HOST_LEGACY_REDIRECT}proxiedtower-finder.retina.fm, the name the fleet calls, to tower-finder-service. Since the origin flip of 2026-09-14 Cloudflare sends that name straight to the service's own edge on 8443, so nothing reaches this vhost. It goes, along with the variable in all four compose overlays, the substitution allowlist, the test fixtures, and theHOST_LEGACY_REDIRECTexemption intest_towers_vhost_coverage.py.EXPECTED_TLS_VHOSTSdrops 8 to 7. It is hardcoded, and left behind it fails parity on all three environments at once.Why this is split out, and what merging it costs
It was part of #389 until review. It carries a risk that the UI removal does not.
Today, deleting the Cloudflare origin rule is a working rollback:
tower-finder.retina.fmlands on this repo's nginx on 443 and this vhost proxies it to the service. After this merges, that rollback is not merely unavailable, it is harmful. The template declares nodefault_serveron 443 (the_catch-all is only in the port-80 redirect list), so nginx falls back to the first 443 server block, which is the towers SPA. A node calling/api/towerswould get an HTML page with a 200 and fail on decode, rather than on a status it can branch on.So: merge this only once the flip is trusted enough to give that rollback up. Nothing else gates it, and the flip has been live and verified since 2026-09-14.
Worth doing separately
A catch-all
default_serveron 443 that refuses unmatched hostnames outright would turn that failure loud rather than silent, and would be worth having regardless of this PR. It is not included here because it changes behaviour for every unmatched name, not just this one, and I could not establish what currently relies on the fallthrough.Verification
pre-commit run --all-filespasses.test_towers_vhost_coverage.pyandtest_nginx_rewrite_ordering.pypass (8 tests) against the sharednginx_helpersfixture with the variable removed.deploy/check-env-parity.pypasses; staging and test in parity with production.nginx -t("syntax is ok") and renders 7 TLS vhosts.HOST_LEGACY_REDIRECTreturns nothing.🤖 Generated with Claude Code