Skip to content

Frontend bug sweep — 2026-05-25

Motivation

After completing the blast-execution-validation skill workflow, a follow-up browser-smoke pass found that every page navigation emitted two React Router v7-migration warnings to the console, and that ESLint (run with --max-warnings 0) failed on five react-hooks/exhaustive-deps warnings concentrated in the cluster-provisioning card. None of these were new regressions; they had accumulated quietly because the dev loop normally runs npm run test, not npx eslint --max-warnings 0. This change closes them as pure bug fixes — no UI, route, contract, or behaviour change — so the console and the lint baseline stay clean.

User-facing change

None. The fixes are:

  • Console no longer prints "React Router will begin wrapping state updates in React.startTransition in v7..." or "Relative route resolution within Splat routes is changing in v7..." on every page load.
  • No other visible UI / network / data-plane changes.

Diff summary

  1. web/src/main.tsx — add future={{ v7_startTransition: true, v7_relativeSplatPath: true }} to the <Router> element. React Router v6.28 documents these as no-op opt-ins for the same behaviour that ships in v7. Silences the two startup warnings.
  2. web/src/components/cards/ClusterCard/ClusterCard.tsx — wrap const clusters = query.data?.clusters ?? [] in useMemo keyed off query.data?.clusters. The ?? [] literal created a fresh array reference every render, causing the downstream useMemo / useEffect blocks that key off clusters (stale-failure detection, provisioning auto-dismiss) to re-fire on every parent render.
  3. web/src/components/cards/ClusterCard/useClusterProvisioning.ts — three fixes in the same file:
  4. Preflight useEffect: the // eslint-disable-next-line react-hooks/exhaustive-deps directive was misplaced (inside the dep array literal, just above ]);). ESLint reports the warning at the line of the dep array opening, so the directive was a no-op ("unused directive" warning) and the original clusterName missing-dep warning was still firing. Moved the directive above the }, [ line so the intentional clusterName exclusion is properly silenced. Behaviour unchanged.
  5. Task-poller useEffect: added the four missing deps (clusterName, provisionRegion, provisionResourceGroup, subscriptionId) to the deps array. The poller's saveLastFailedProvision call captures these values; they are stable for the lifetime of a "creating" transition (the modal disables those inputs once the task is queued), so adding them is safe and silences the warning without re-creating the poll interval mid-provisioning.
  6. Preflight catch block: removed a dead // eslint-disable-next-line no-console directive — the no-console rule is not enabled for this file, so ESLint flagged it as an unused directive. The console.warn underneath is untouched.
  7. web/src/api/settings.tsgetAksObservabilityStatus no longer needs as unknown as Record<string, string>. Spreading the query object with { ...q } is enough for TS to widen it to Record<string, string> while keeping the same runtime behaviour.
  8. web/src/api/callerIp.ts — deleted. The getCallerIp export had no callers in the workspace; it was leftover dead code from an earlier storage-firewall iteration. The current local-debug flow (/api/storage/local-debug + scripts/dev/storage-public-access.sh) resolves the caller IP server-side.

No route prefix change, no Bicep change, no Celery task change, no Container App template change.

API/IaC diff summary

None.

Validation

  • npx tsc --noEmit (web): rc=0
  • npx eslint src --max-warnings 0 (web): rc=0 (was 5 warnings)
  • npm run -s test --run (web): 48 files / 331 tests passing in 3.31s
  • uv run ruff check api: All checks passed
  • uv run pytest -q api/tests: 1466 passed in 26.41s
  • Browser re-smoke on http://127.0.0.1:8090/: navigated Dashboard → New Search → Recent Searches → Terminal → API; console captured 15 messages, 0 of type warning, 0 of type error. The two React Router v7 warnings that used to fire on every page load are gone.