The app-scan and EOL pollers had two branches — running, or finished — so every answer that was not a readable status object fell into "finished". The empty result then rendered as "0 assets, 0 findings (0 new)" and the button went idle while the backend scan carried on and logged the real numbers. The tester hit this after ~15-30 minutes with several tabs open, which is when the access token expires mid-scan: the poll 401s, the interceptor refreshes and replays it, and anything that comes back other than a clean status object — a login-page body from a redirect, a second 401 — landed in the finished branch. The 401/refresh/200 sequence in the log is the healthy path, not the bug; the poller's reading of it was. Now only status "completed" or "failed" stops the poll. Anything else keeps polling, with a ~2 min counter of unusable answers so a backend restart mid-scan (the job lives in process memory) ends it with a clear message instead of spinning forever. Same counter on the catch branch, which could poll a dead backend indefinitely. Also surfaces fp_suppressed in the result line, now that suppression runs inside the scan.
TrueVuln Frontend
Next.js 16 (App Router) UI for TrueVuln. See the root README for setup, deployment, and configuration — this app is deployed via Docker Compose alongside the backend, not standalone or on Vercel.
Local dev (without Docker)
npm install
npm run dev
Open http://localhost:3000. The dev server proxies API calls to the backend — see ../README.DEV.md for the full local (non-Docker) setup.