Skip to content

Retire this repo's tower search UI, now the service serves it - #389

Merged
Babissimo merged 1 commit into
mainfrom
worktree-retire-tower-ui
Sep 15, 2026
Merged

Babissimo merged 1 commit into
mainfrom
worktree-retire-tower-ui

Conversation

@Babissimo

@Babissimo Babissimo commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Ticket: https://app.clickup.com/t/123zgec2zw1

Split out of 86capx9mv, which covered the API dedup and is separately verified and ready to close.

Scope narrowed on review. This PR was originally the UI removal and the ${HOST_LEGACY_REDIRECT} vhost removal. The vhost half has been split into a child PR because it carries a risk this one does not (see below). This PR now changes no nginx config at all.

Why now

The Cloudflare origin rules moved towers.retina.fm, staging-towers, test-towers and the fleet's tower-finder.retina.fm onto port 8443 on 2026-09-14. All four names now reach tower-finder-service's own edge, which serves its own SPA. None of them reach this repo.

Why the copy here was dead, not merely redundant

frontend/dist is served on HOST_MAIN, HOST_MAP and HOST_TESTMAP only. Dash and admin serve dashboard/dist, a different app. isMapDomain already hid the tower tab on map and testmap, so once HOST_MAIN flipped away the tab was reachable on no live surface.

The service's copy had also moved well ahead of ours (SearchForm.tsx 356 lines there against 212 here), gaining address geocoding, rank tiers, expected-area ranking and a working frequencies parameter. Keeping ours invited exactly the split-brain 86capx9mv was raised to end.

What goes

  • The three components and their CSS, plus the ~145 lines of App.css that styled only them.
  • fetchTowers / fetchElevation and the three tower types.
  • The towers tab. Every surface this bundle still serves is a live map, so the hostname-dependent header goes too and App renders one surface unconditionally. That settles by deletion the "Tower Finder" display label left open during the rename.

What does not change

No nginx, deploy or compose changes. Every vhost keeps forwarding /api/towers, /api/elevation and /api/config to the service exactly as before, and the ${HOST_LEGACY_REDIRECT} vhost carrying the fleet's name stays. While it stays, deleting the Cloudflare origin rule remains a working rollback for the fleet.

That removal is the child PR, which should merge only once the flip is trusted enough to give that rollback up. The template declares no default_server on 443, so with that vhost gone an unmatched tower-finder.retina.fm would fall through to the first 443 block, the towers SPA, and answer a node with HTML and a 200 rather than JSON.

Verification

  • pre-commit run --all-files passes (ruff, ruff format, vulture, both shared-config checks).
  • tsc --noEmit clean on src and e2e; eslint reports only the 5 pre-existing LiveAircraftMap warnings.
  • 278 frontend tests pass across 21 files; vite build succeeds.
  • test_towers_vhost_coverage.py and test_nginx_rewrite_ordering.py pass (8 tests), unchanged by this PR.
  • deploy/check-env-parity.py passes.
  • Entry chunks every map surface loads: JS 56.66 to 43.84 kB (gzip 18.04 to 14.08), CSS 26.45 to 19.23 kB (gzip 5.67 to 4.13).

🤖 Generated with Claude Code

@claude

This comment has been minimized.

@Babissimo
Babissimo force-pushed the worktree-retire-tower-ui branch from 14de7a9 to eeb47e3 Compare September 15, 2026 12:43
@claude

This comment has been minimized.

@Babissimo
Babissimo force-pushed the worktree-retire-tower-ui branch from eeb47e3 to d9cf738 Compare September 15, 2026 13:59
@claude

This comment has been minimized.

@Babissimo Babissimo changed the title Retire this repo's tower search, now the service serves it directly Retire this repo's tower search UI, now the service serves it Sep 15, 2026
@Babissimo
Babissimo force-pushed the worktree-retire-tower-ui branch from d9cf738 to b9b8ecb Compare September 15, 2026 14:12
@claude

This comment has been minimized.

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>
@Babissimo
Babissimo force-pushed the worktree-retire-tower-ui branch from b9b8ecb to a20362f Compare September 15, 2026 15:36
@claude

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown

Claude finished @Babissimo's task in 1m 17s —— View job


Reviewing PR #389

Todo list

  • Gather context (PR description, changed files, CLAUDE.md)
  • Run /code-review on this PR per custom instructions
  • Post final review

Review

This synchronize event carries the same single commit (a20362f) already reviewed in the prior pass — diff is unchanged (19 files, +49/-1233). I re-verified independently rather than trusting that:

  • App.tsx: SummaryStrip, the towers tab, handleSearch/fetchTowers, and liveEverOpened gating are all gone; MainApp now unconditionally renders .app map-surface and defaults to the "live" tab. LiveAircraftMap mounts unconditionally inside the Suspense/hidden-div wrapper, consistent with every remaining vhost (HOST_MAIN, HOST_MAP, HOST_TESTMAP) being a map surface.
  • Deleted components: SearchForm, ResultsTable, TowerMap (+ their CSS) are fully removed; api.ts's fetchTowers/fetchElevation and types.ts's tower types are gone with no leftover imports (checked via repo-wide grep for SearchForm, ResultsTable, TowerMap, fetchTowers, fetchElevation, SummaryStrip — no hits outside the e2e negative assertion and an unrelated external link in dashboard/src/components/Sidebar.tsx).
  • domains.ts: isMapDomain is no longer imported by App.tsx but is still live — used to derive isPublicDemo in the same file and covered by domains.test.ts. Not orphaned.
  • Tests: App.test.tsx and live-map.spec.ts updated to assert on the h1/.app-body.live-active instead of the removed title/search-form. index.html title updated from "Tower Finder" to "RETINA" to match.
  • Nginx (unchanged by this PR, confirmed no diff outside frontend/, ONBOARDING.md, README.md, docs/architecture.md): traced location /towers on the HOST_MAIN vhost (deploy/nginx/nginx.conf.template:78-82) — it still aliases this repo's SPA bundle at /towers. That's pre-existing, harmless (it now just serves the live map since the tab is gone), and matches the PR's explicit "no nginx changes" scope. The ${HOST_LEGACY_REDIRECT} vhost and /api/towers, /api/elevation, /api/config proxying are all untouched, as described.
  • Docs: README.md, ONBOARDING.md, docs/architecture.md consistently describe illuminator search as fully owned by tower-finder-service (API + UI). No stale "Tower Finder" surface references remain in the docs table/prose besides the deliberate "It started life as..." history note.

No issues found — this is a clean, purely subtractive change that matches its stated scope. Nothing new surfaced versus the prior review of this same commit.

As before, I could not run npm install/tsc/eslint/vitest in this sandbox (no node_modules, no network access), so I'm relying on the PR's stated verification numbers rather than re-running them.

@Babissimo
Babissimo merged commit 6d27bea into main Sep 15, 2026
26 of 27 checks passed
@Babissimo
Babissimo deleted the worktree-retire-tower-ui branch September 15, 2026 15:42
Babissimo added a commit that referenced this pull request Sep 15, 2026
test_interval_gate_holds_between_passes asserts that its first
maybe_run_pass runs, and under xdist that assertion fails now and then
with the attempt count still 0 (2026-09-06, 2026-09-15 on #389, and
twice in a row on #403, all diffs that never touched the backend).

conftest turns KNOWN_LANE_MODE off for the suite so the solver worker
daemons every TestClient lifespan leaks do not poll the pass, but
DARK_FOLLOW_MODE keeps its "shadow" default, lanes_armed() is true when
either lane is on, and maybe_run_pass returns early only when both are
off. So every leaked daemon takes the pass lock, stamps the pass clock
and runs an empty dark-follow pass every two seconds, and one landing
between the fixture's clock reset and the test's first call leaves that
call gated.

DARK_FOLLOW_MODE is now off for the suite the way KNOWN_LANE_MODE is,
and the known-lane fixture turns it off again per test for a daemon
armed while another file had a lane on, before the reset that drains
any pass in flight. Tests that exercise dark following already set the
mode themselves. The fixture's clock comment is trimmed to the reason
the reset stands; the ordering story it told was the first guess at
this.

ClickUp: 123zgec3130

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Babissimo added a commit that referenced this pull request Sep 15, 2026
test_interval_gate_holds_between_passes asserts that its first
maybe_run_pass runs, and under xdist that assertion fails now and then
with the attempt count still 0 (2026-09-06, 2026-09-15 on #389, and
twice in a row on #403, all diffs that never touched the backend).

conftest turns KNOWN_LANE_MODE off for the suite so the solver worker
daemons every TestClient lifespan leaks do not poll the pass, but
DARK_FOLLOW_MODE keeps its "shadow" default, lanes_armed() is true when
either lane is on, and maybe_run_pass returns early only when both are
off. So every leaked daemon takes the pass lock, stamps the pass clock
and runs an empty dark-follow pass every two seconds, and one landing
between the fixture's clock reset and the test's first call leaves that
call gated.

DARK_FOLLOW_MODE is now off for the suite the way KNOWN_LANE_MODE is,
and the known-lane fixture turns it off again per test for a daemon
armed while another file had a lane on, before the reset that drains
any pass in flight. Tests that exercise dark following already set the
mode themselves. The fixture's clock comment is trimmed to the reason
the reset stands; the ordering story it told was the first guess at
this.

ClickUp: 123zgec3130

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
jehanazad pushed a commit that referenced this pull request Sep 15, 2026
…406)

test_interval_gate_holds_between_passes asserts that its first
maybe_run_pass runs, and under xdist that assertion fails now and then
with the attempt count still 0 (2026-09-06, 2026-09-15 on #389, and
twice in a row on #403, all diffs that never touched the backend).

conftest turns KNOWN_LANE_MODE off for the suite so the solver worker
daemons every TestClient lifespan leaks do not poll the pass, but
DARK_FOLLOW_MODE keeps its "shadow" default, lanes_armed() is true when
either lane is on, and maybe_run_pass returns early only when both are
off. So every leaked daemon takes the pass lock, stamps the pass clock
and runs an empty dark-follow pass every two seconds, and one landing
between the fixture's clock reset and the test's first call leaves that
call gated.

DARK_FOLLOW_MODE is now off for the suite the way KNOWN_LANE_MODE is,
and the known-lane fixture turns it off again per test for a daemon
armed while another file had a lane on, before the reset that drains
any pass in flight. Tests that exercise dark following already set the
mode themselves. The fixture's clock comment is trimmed to the reason
the reset stands; the ordering story it told was the first guess at
this.

ClickUp: 123zgec3130

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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