feat(feedback-site): tell answers from different links apart (#363) #597

Merged
claude-bot merged 1 commit from feat/feedback-response-source into main 2026-09-11 05:16:56 +00:00
Contributor

The owner wants to send round two to people outside their group without mixing those answers with the group's. They also asked to follow answers as they arrive, which turned up a gap from #594: the admin page never showed the new wiki ratings or the wiki answer.

What changes

  • Labelled share keys. SHARE_KEYS=external:<key>[,label:<key>…] sits beside SHARE_KEY.
    • The server records the label of the key that saved each response as source, overwriting anything the page sends, so nobody can relabel their own answers.
    • SHARE_KEY's link is group, and so is every response from before labels existed, when it was the only key.
    • Removing a labelled key switches off that one link without touching the others.
  • A malformed SHARE_KEYS entry stops the app at start-up rather than being skipped. A skipped entry would leave its link refusing everyone in a way that looks like the respondent's fault. The error message never repeats key material.
  • Readout:
    • a link filter that covers both rounds, with counts
    • a badge on each response
    • the round-two wiki ratings (a_wiki, b_wiki) and the "Wanted from the wiki" answer
  • CSV gains source as its last column, so anything reading columns by position is unaffected.
  • Docs: README and .env.example explain how to send a link to a different group.

Checked

  • Tests: 47 of 47 pass (9 new).
    • each key labels its own responses
    • a body claiming another source is overwritten
    • an unknown key is still refused
    • older responses read as group in the JSON and the CSV
    • five malformed settings each stop the app without echoing a key
  • Lint: ruff check is clean.
  • Admin page script: passes node --check.
  • Already deployed to dev:
    • the site's settings file was backed up, and only a SHARE_KEYS=external:… line was appended
    • both keys are accepted and a wrong key gets a 403, checked read-only against a response id that doesn't exist
    • the four existing responses all read as group

🤖 Generated with Claude Code

The owner wants to send round two to people outside their group without mixing those answers with the group's. They also asked to follow answers as they arrive, which turned up a gap from #594: the admin page never showed the new wiki ratings or the wiki answer. ## What changes - **Labelled share keys.** `SHARE_KEYS=external:<key>[,label:<key>…]` sits beside `SHARE_KEY`. - The server records the label of the key that saved each response as `source`, overwriting anything the page sends, so nobody can relabel their own answers. - `SHARE_KEY`'s link is `group`, and so is every response from before labels existed, when it was the only key. - Removing a labelled key switches off that one link without touching the others. - **A malformed `SHARE_KEYS` entry stops the app at start-up** rather than being skipped. A skipped entry would leave its link refusing everyone in a way that looks like the respondent's fault. The error message never repeats key material. - **Readout:** - a link filter that covers both rounds, with counts - a badge on each response - the round-two wiki ratings (`a_wiki`, `b_wiki`) and the "Wanted from the wiki" answer - **CSV** gains `source` as its last column, so anything reading columns by position is unaffected. - **Docs:** README and `.env.example` explain how to send a link to a different group. ## Checked - **Tests:** 47 of 47 pass (9 new). - each key labels its own responses - a body claiming another source is overwritten - an unknown key is still refused - older responses read as `group` in the JSON and the CSV - five malformed settings each stop the app without echoing a key - **Lint:** `ruff check` is clean. - **Admin page script:** passes `node --check`. - **Already deployed to dev:** - the site's settings file was backed up, and only a `SHARE_KEYS=external:…` line was appended - both keys are accepted and a wrong key gets a 403, checked read-only against a response id that doesn't exist - the four existing responses all read as `group` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(feedback-site): tell answers from different links apart (#363)
All checks were successful
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m23s
CI / Docker image build (pull_request) Successful in 20s
CI / Backend lint (ruff) (pull_request) Successful in 41s
CI / Bot/backend version sync (pull_request) Successful in 41s
CI / Bot tests and audit (pull_request) Successful in 2m28s
CI / Frontend tests, audit, and build (pull_request) Successful in 2m59s
CI / Backend migration, tests, and audit (pull_request) Successful in 8m15s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Successful in 19m9s
829bf3a381
The owner wants to send round two to people outside their group without
mixing those answers with the group's. SHARE_KEYS adds labelled share keys
(external:<key>, ...) beside SHARE_KEY. The server records which key saved
each response as `source`, overwriting anything the page sends, so nobody
can relabel their own answers. SHARE_KEY's link is "group", and so is every
response from before labels existed, when it was the only key.

A malformed SHARE_KEYS entry stops the app at start-up rather than being
skipped, since a skipped entry would leave its link refusing everyone in a
way that looks like the respondent's fault; the message never echoes key
material.

The readout gets a link filter across both rounds, a badge per response
and a `source` CSV column (appended last, so positional readers are
unaffected). It also now shows the round-two wiki ratings and wiki answer
that #594 added to the form but not to this page.

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-11 04:56:28 +00:00
claude-bot deleted branch feat/feedback-response-source 2026-09-11 05:16:57 +00:00
Sign in to join this conversation.
No description provided.