fix: actually strip stale SESSION_SECRET mentions from README

The gap-g-readme merge commit (57a8914) staged this fix but never
re-staged it after editing, so the merge landed with the pre-fix content —
the working tree had the correction but git didn't. No functional change,
just closing the gap between what was intended and what was committed.
This commit is contained in:
Indiana
2026-07-23 03:32:21 +00:00
parent 57a8914fdc
commit 761d6171b5
12 changed files with 143 additions and 4 deletions

View File

@@ -86,4 +86,17 @@ async def serve_spa(full_path: str):
status_code=503,
detail="Frontend not built. Run `npm run build` in frontend/ and restart.",
)
# Vite emits root-level static files (favicon.ico, favicon.svg,
# apple-touch-icon.png, og-image.png, …) straight into dist/ rather than
# dist/assets/ — the only mounted static dir. Without this, requests for
# them fall through to the SPA fallback below and get index.html back
# instead of the actual file (browsers silently ignore it; social-media
# link-preview crawlers fetching og:image get an HTML page).
if full_path:
dist_root = FRONTEND_DIST.resolve()
candidate = (dist_root / full_path).resolve()
if candidate.is_file() and dist_root in candidate.parents:
return FileResponse(candidate)
return FileResponse(index_file)

View File

@@ -24,3 +24,38 @@ async def test_missing_frontend_build_returns_clear_error(client, monkeypatch, t
response = await client.get("/some/route")
assert response.status_code == 503
assert "npm run build" in response.json()["detail"]
@pytest.mark.asyncio
async def test_root_level_static_file_is_served_directly(client, monkeypatch, tmp_path):
# Vite emits favicon.ico, og-image.png, etc. straight into dist/, not
# dist/assets/ (the only mounted static dir) — these must be served as
# themselves, not swallowed by the SPA fallback.
import app.main as main_module
monkeypatch.setattr(main_module, "FRONTEND_DIST", tmp_path)
(tmp_path / "index.html").write_text('<div id="root"></div>')
(tmp_path / "favicon.svg").write_text("<svg>fake favicon</svg>")
response = await client.get("/favicon.svg")
assert response.status_code == 200
assert response.text == "<svg>fake favicon</svg>"
assert "html" not in response.headers["content-type"]
@pytest.mark.asyncio
async def test_static_file_lookup_cannot_escape_dist_directory(monkeypatch, tmp_path):
# Bypasses the HTTP client, which normalizes ".." segments out of URLs
# before they're ever sent — this exercises the route function's own
# guard directly against a full_path value an unusual client could send.
import app.main as main_module
dist_dir = tmp_path / "dist"
dist_dir.mkdir()
(dist_dir / "index.html").write_text('<div id="root"></div>')
secret = tmp_path / "secret.txt"
secret.write_text("should never be served")
monkeypatch.setattr(main_module, "FRONTEND_DIST", dist_dir)
response = await main_module.serve_spa("../secret.txt")
assert response.path == dist_dir / "index.html"