[Hardening] Proxy /public/ so the public analytics share page works #92
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
The analytics share page (
/analytics/share/:token) is the app's one unauthenticated feature. The frontend fetches/public/analytics/{shareToken}(webapp/frontend/src/api/campaigns.js:150-151), and the backend mounts the public router at that prefix (webapp/backend/app/main.py:94:app.include_router(public.router, prefix="/public", ...)).Current behavior
Neither frontend proxy layer forwards
/public/*to the backend:webapp/frontend/nginx.confproxies onlylocation /api/(line 22) andlocation /auth/(line 33)webapp/frontend/vite.config.jsdev proxy (block starting line 16) covers only/apiand the concrete/authbackend endpointsSo
/public/analytics/...falls through to the SPA catch-all and returnsindex.html;r.json()infetchPublicAnalyticsthen throws parsing HTML. Result: share links never load in dev, and in the prod compose build they only work if an external reverse proxy happens to route/publicto the backend itself.Fix / Spec
Least-invasive option (preferred):
location /public/ { proxy_pass ... }block towebapp/frontend/nginx.conf, mirroring the existing/api/block (same proxy_pass target and headers)."/public"entry to theserver.proxymap inwebapp/frontend/vite.config.js, mirroring the/apientry.(Alternative, only if preferred during implementation: move the backend route under
/api/publicand updatecampaigns.js— pick one approach, not both.)Take care that no SPA route begins with
/public(none does today) so the catch-all is unaffected.Acceptance criteria
/analytics/share/<valid-token>renders analytics data (network tab shows JSON from/public/analytics/..., not HTML).References
webapp/frontend/src/api/campaigns.js:150-151(fetchPublicAnalytics)webapp/backend/app/main.py:94(public router mount)webapp/frontend/nginx.conf:22(/api/),:33(/auth/) — no/public/webapp/frontend/vite.config.js:16+(dev proxy map)Filed from the July 2026 full-project review.
Picking this up as part of a v3.3.0 push. Landing on branch
hardening/infra-docstogether with #102 and #113 (grouped by component to keep the diffs reviewable). Taking the least-invasive option from the spec: add the/public/proxy to both nginx.conf and the Vite dev proxy, leaving the backend route where it is.Fixed on
main(commit5154b32, merged via9448593). Added alocation /public/block towebapp/frontend/nginx.confmirroring the existing/api/block, and a"/public"entry to the Vite dev proxy invite.config.js. Confirmed no SPA route begins with/public, so the catch-all is unaffected. Verifiednginx -tpasses on the final merged config. Backend route left where it is (least-invasive option). Frontend suite not run (no local Node — config-only change).