Skip to content

Open the physics page and the sim config save to anyone - #508

Merged
jehanazad merged 2 commits into
mainfrom
feat/sim-physics-open
Sep 19, 2026
Merged

jehanazad merged 2 commits into
mainfrom
feat/sim-physics-open

Conversation

@jehanazad

Copy link
Copy Markdown
Contributor

Summary

test-app.retina.fm/sim/physics sent a visitor to the login card while every read behind the page (config, ground truth, solver stats, nodes) was already served to anyone; only the config PUT was admin-only. The console has no identity provider yet and the fleet the page reconfigures is synthetic, so this opens the save and lets the page follow it: no session needed to open /sim/physics or to apply a change.

Changes

Backend

  • PUT /api/simulation/config drops require_admin. The docstring says why. PUT /api/test/known-hold keeps its gate.

Dashboard

  • isPublicRoute admits the whole /sim subtree like the other open routes; the exact escape hatch is gone. PublicRoute.exact becomes end, a nav-only flag that stops /sim lighting up beside /sim/physics.
  • /sim/physics joins PUBLIC_ROUTES with needsFleet, so the signed-out nav advertises Physics Layer right after Simulation wherever there is a fleet.
  • AuthProvider folds the two fleet answers into one syntheticFleet: /api/auth/me for a session, /api/health for a visitor. App mounts the physics route on that flag and Sidebar builds both navs from it. utils/physics.ts (showsPhysics(user)) is deleted.

Docs

  • ONBOARDING's surface paragraph says both pages and the save are open.

Test coverage

  • New backend test switches the suite's anonymous-admin bypass off and checks an unsigned config PUT is accepted while the known-hold PUT still returns 401.
  • publicRoutes.test: physics and the rest of the /sim subtree now admitted; Physics Layer advertised directly after Simulation and only with a fleet; /sim carries end.
  • physicsRoute.test: sidebar entry and the route open for a visitor with no session; the "not current" check runs signed in and out; the showsPhysics block is gone with the helper.
  • signedOutChrome.test: the "never offers the physics page" case is replaced by offered-with-fleet / withheld-without.
  • Run locally: pytest tests/test_sim_ingest.py (43 passed), dashboard tsc --noEmit, vitest run (1090 passed), eslint (no errors), pre-commit on the changed files.

Review notes

  • This is a deliberate removal of the only server-side lock on the sim config. Anyone reaching test-app or staging-app can change spawn fractions, node count, and trigger a fleet restart. That is the intent for now; when an identity provider lands, the gate is a one-line Depends(require_admin) to put back.
  • Production is unaffected in practice: SYNTHETIC_FLEET_ENABLED is off there, the fleet routes are not mounted, and the physics route is not rendered.
  • For a visitor the route mounts once /api/health answers, so a direct load of /sim/physics may render blank for one round trip before the page appears. A session gets it on the first settled render.
  • Test deploys are workflow_dispatch only; redeploy the test droplet by hand after merge.

🤖 Generated with Claude Code

/sim/physics bounced a visitor to the login card while every read behind it
(config, ground truth, solver stats, nodes) was already public; only the PUT
was admin-only. The console has no identity provider yet and the fleet it
reconfigures is synthetic, so the save is open now and the page goes with
it: isPublicRoute admits the whole /sim subtree like the other open routes,
the route and both navs mount on AuthProvider's one syntheticFleet answer
(/me for a session, /api/health for a visitor), and the Physics Layer entry
is advertised beside Simulation wherever there is a fleet.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@claude

This comment has been minimized.

@claude

claude Bot commented Sep 19, 2026 •

Copy link
Copy Markdown

Claude finished @jehanazad's task in 1m 38s —— View job


Re-review after new commits

  • Gather context (PR description, previous review comment, changed files)
  • Check whether the production-exposure finding from the last review was addressed
  • Review the rest of the diff for new issues
  • Post findings

Review complete

The only commit added since the last review is a merge of origin/main into this branch (7b9ed9c); it pulls in unrelated upstream work (e.g. #507) and touches one unrelated test fixture (mapShell.test.tsx) via the merge. backend/routes/test.py, backend/tests/test_sim_ingest.py, and the dashboard files are unchanged from what was already reviewed.

Standing finding: PUT /api/simulation/config is still reachable unauthenticated in production, not just test/staging

backend/routes/test.py:442-443 still drops Depends(require_admin) from put_simulation_config, and it's unchanged since the prior review. The PR body's review notes still say:

Production is unaffected in practice: SYNTHETIC_FLEET_ENABLED is off there, the fleet routes are not mounted, and the physics route is not rendered.

That's true for sim_ingest_router — gated in backend/main.py:465-466 by synthetic_fleet_enabled(os.environ) — but put_simulation_config lives in test_router, which backend/main.py:442-445 mounts unconditionally in every environment, production included. So an anonymous caller can still PUT /api/simulation/config in production after this PR. The same file fails fast at import time (backend/routes/test.py:43-48) if RADAR_API_KEY is unset in production, specifically to avoid this exact class of unauthenticated-write exposure on /api/test/ground-truth/push / /api/sim/adsb/push — so the codebase already treats "anonymous writer in prod" as worth guarding against elsewhere, just not here.

In production today this still looks functionally inert: state.simulation_config is only read by get_simulation_config/put_simulation_config and periodically persisted/restored by services/state_snapshot.py (alongside real state like trust_scores/chain_entries), and nothing else in the backend consumes those fields — the fleet process that would act on n_nodes/dual_fraction isn't running in prod. But the route is still writable by any internet caller in prod, which doesn't match the "production is unaffected" framing, and it's one accidental future read of state.simulation_config away from mattering.

Still worth either: gating this route the same way sim_ingest_router is (skip mounting it, or check synthetic_fleet_enabled() inside the handler and 404/no-op in production), or updating the PR description to be accurate about the actual blast radius. Fix this →

Everything else — isPublicRoute/advertisedPublicRoutes, the exact→end rename, the AuthContext fold into syntheticFleet, and the test coverage across physicsRoute.test.tsx/publicRoutes.test.ts/signedOutChrome.test.tsx — remains solid and unchanged from the prior pass.

@jehanazad
jehanazad merged commit 1dd4d04 into main Sep 19, 2026
15 checks passed
@Babissimo
Babissimo deleted the feat/sim-physics-open branch September 21, 2026 08:42
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