Skip to content

feat(surveys): anonymous mode, response delete, confirmation message - #1477

Open
leahpeker wants to merge 2 commits into
mainfrom
feat-survey-anon-delete-confirmation
Open

feat(surveys): anonymous mode, response delete, confirmation message#1477
leahpeker wants to merge 2 commits into
mainfrom
feat-survey-anon-delete-confirmation

Conversation

@leahpeker

Copy link
Copy Markdown
Collaborator

Summary

Closes #1466

  • Survey.anonymous: when true, submit_survey_response stores user=None even for authenticated submitters and skips the one-response-per-user upsert (nothing to key it on). get_survey_public / _survey_out no longer surface my_response_id / my_answers for anonymous surveys.
  • DELETE /surveys/{survey_id}/responses/{response_id}/, gated by manage_surveys (403 without it, 404 if the response isn't in that survey). New _surveys_responses.py module (list + delete admin response endpoints) split out of _surveys.py to stay under the repo's 500-line file limit. Frontend: a delete column on SurveyResponsesScreen using useConfirm, wired to a new useDeleteSurveyResponse hook that invalidates the responses query.
  • Survey.confirmation_message (optional, max 1000 chars): set via a new textarea in CreateSurveyDialog (alongside an "anonymous responses" checkbox), shown lowercased on SurveyScreen in place of the generic "saved ✓" after a successful submit.
  • Migration 0095_survey_anonymous_confirmation_message.py adds both fields to Survey. Migration-number collisions with concurrently-open sibling survey PRs are expected and get resolved at merge time.

Sibling PR #1461 is adding an anonymous-response token; once that lands it should take over identifying/deduping anonymous responses. This PR intentionally does not depend on it — anonymous mode here just means "store no user," per the issue's stated fallback ("otherwise is disabled").

Verification

Run manually this session (not as a final pre-push gate — see below):

  • Backend: ruff lint and ty typecheck clean; targeted pytest (tests/test_surveys_public.py + new tests/test_surveys_admin.py) — 13/13 passing, covering anonymous submit storing no user, one-per-user upsert being skipped for anonymous surveys, my_response_id/my_answers omitted for anonymous surveys, admin delete succeeding, 403 without manage_surveys, and 404 for a response belonging to another survey.
  • Frontend: tsc typecheck clean, eslint + prettier clean, full vitest suite green (1287 passed / 1 skipped across 159 files), including two new tests covering the response-delete confirm flow and the post-submit confirmation message render.
  • make frontend-types re-run to regenerate types.gen.ts / openapi_schema.json / validationCodes.gen.ts after the schema and router changes.

Not run as a final gate before opening this PR: the full make agent-ci umbrella and a full (non-scoped) make agent-test backend run. The last full backend run (done earlier, before the final router split) showed 7 pre-existing failures unrelated to this change — test_sse.py (needs pg_notify), test_poll_finalize_race.py and test_rsvp_capacity_race.py (need real Postgres row locking) — all documented in the Makefile as SQLite-vs-Postgres environmental gaps, not regressions from this branch. GitHub CI on this PR (which runs against Postgres) is the authoritative signal for final verification; please check it before merging.

Test plan

  • CI passes on this PR (Postgres-backed — covers the three tests that can't be verified locally on SQLite)
  • Create a survey with "anonymous responses" checked, submit as a logged-in member, confirm no user is attached to the stored response and the admin responses view doesn't show a name
  • Set a custom confirmation message on a survey, submit it, confirm the lowercased message renders in place of "saved ✓"
  • As an admin with manage_surveys, delete a single response from SurveyResponsesScreen via the confirm dialog and confirm it's removed

The anonymous flag stopped the user FK being written, but three paths
still carried the responder's identity:

- audit_log persisted actor + IP on every submit, so an anonymous
  response could be re-linked to its submitter by timestamp. Adds an
  anonymize_actor flag and uses it on survey_response_submitted.
- the admin response list returned user_id/user_name for responses
  collected before a survey was flipped to anonymous.
- poll tallies returned voter names/photos for the same pre-flip rows.

Also fixes the delete-response mutation swallowing errors silently, and
useUpdateSurvey dropping anonymous/confirmation_message from the PATCH
body.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add anonymous mode, per-response delete, and post-submit confirmation to surveys

1 participant