fix(feedback-site): keep every link and redirect under the /feedback/ prefix #592

Merged
claude-bot merged 1 commit from fix/feedback-mockup-links into main 2026-09-10 22:35:37 +00:00
Contributor

Follow-up to #590, part of #363. Reported on first real use: the round-two mockup links sent people to the Quest Board login page.

Cause. The site is served at /feedback/ behind Caddy's handle_path, which strips the prefix before the request reaches the app. The landing page linked its designs as /mockups/a and /mockups/b, so a click left the site and landed in the Quest Board app, which sends a signed-out reader to its login page. The page's script already derived the correct prefix for saving answers; it just never applied it to the two links.

A second route to the same place. Starlette's redirect_slashes builds its Location from the path it sees, which has already lost /feedback, so /feedback/mockups/ was redirected to /mockups. Anyone whose chat app or browser appended a slash would have hit the same login page.

Fix.

  • The landing page applies its derived prefix to both design links, and the static hrefs are relative fallbacks. The index page's three card links get relative fallbacks too; its script was already rescuing them.
  • redirect_slashes is off, and a trailing slash on a GET or HEAD is answered with a relative Location (/mockups/a/../a), which the browser resolves against the URL it actually requested. The share key survives the redirect.

Why the tests missed it, and what closes that. Every route test passed throughout, because a test client requests known paths directly and never follows a link a person clicks. tests/test_static_links.py asserts that no page carries a root-relative href, src or action, and that trailing slashes redirect relatively with the query intact. Both sets failed against the broken code (2 and 6 failures) before passing; the suite is 34 of 34.

Already deployed to dev and verified through the public URL: every trailing-slash variant now resolves inside /feedback/, and the three round-one responses are untouched.

🤖 Generated with Claude Code

Follow-up to #590, part of #363. Reported on first real use: the round-two mockup links sent people to the Quest Board login page. **Cause.** The site is served at `/feedback/` behind Caddy's `handle_path`, which strips the prefix before the request reaches the app. The landing page linked its designs as `/mockups/a` and `/mockups/b`, so a click left the site and landed in the Quest Board app, which sends a signed-out reader to its login page. The page's script already derived the correct prefix for saving answers; it just never applied it to the two links. **A second route to the same place.** Starlette's `redirect_slashes` builds its `Location` from the path it sees, which has already lost `/feedback`, so `/feedback/mockups/` was redirected to `/mockups`. Anyone whose chat app or browser appended a slash would have hit the same login page. **Fix.** - The landing page applies its derived prefix to both design links, and the static `href`s are relative fallbacks. The index page's three card links get relative fallbacks too; its script was already rescuing them. - `redirect_slashes` is off, and a trailing slash on a GET or HEAD is answered with a **relative** `Location` (`/mockups/a/` → `../a`), which the browser resolves against the URL it actually requested. The share key survives the redirect. **Why the tests missed it, and what closes that.** Every route test passed throughout, because a test client requests known paths directly and never follows a link a person clicks. `tests/test_static_links.py` asserts that no page carries a root-relative `href`, `src` or `action`, and that trailing slashes redirect relatively with the query intact. Both sets failed against the broken code (2 and 6 failures) before passing; the suite is 34 of 34. **Already deployed to dev and verified through the public URL**: every trailing-slash variant now resolves inside `/feedback/`, and the three round-one responses are untouched. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(feedback-site): keep every link and redirect under the /feedback/ prefix
All checks were successful
CI / Docker image build (pull_request) Successful in 22s
CI / Bot/backend version sync (pull_request) Successful in 45s
CI / Backend lint (ruff) (pull_request) Successful in 46s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m26s
CI / Bot tests and audit (pull_request) Successful in 2m25s
CI / Frontend tests, audit, and build (pull_request) Successful in 2m47s
CI / Backend migration, tests, and audit (pull_request) Successful in 8m9s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 21m10s
6ab4ac4f39
The round-two landing page linked its two designs as /mockups/a and
/mockups/b. Behind the proxy the site lives at /feedback/, so a click left
the site and landed in the Quest Board app, which sends a signed-out reader
to its login page. The page's script already derived the right prefix for
saving answers; it now applies it to the two links too, and the static
hrefs become relative fallbacks. The index page's three card links get the
same relative fallbacks, although its script was already rescuing them.

A trailing slash did the same thing by another route: Starlette's slash
redirect builds its Location from the proxy-stripped path, so
/feedback/mockups/ was sent to /mockups. That redirect is now off, and a
trailing slash is answered with a relative Location, which the browser
resolves against the URL it actually requested. The share key survives it.

Every route test passed throughout, because a test client requests paths
directly and never follows a link a person clicks. tests/test_static_links.py
closes that gap: no page may carry a root-relative href, src or action, and a
trailing slash must redirect relatively. Both sets failed against the broken
code before they passed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
claude-bot scheduled this pull request to auto merge when all checks succeed 2026-09-10 22:16:50 +00:00
claude-bot deleted branch fix/feedback-mockup-links 2026-09-10 22:35:38 +00:00
Sign in to join this conversation.
No description provided.