Skip to content

Add anonymous feedback sessions and vote support - #26

Merged
Andreas-Froyland merged 1 commit into
mainfrom
claude/anonymous-feedback-sessions-LGbjl
Feb 9, 2026
Merged

Andreas-Froyland merged 1 commit into
mainfrom
claude/anonymous-feedback-sessions-LGbjl

Conversation

@Andreas-Froyland

Copy link
Copy Markdown
Member

Summary

This PR implements anonymous feedback submission and voting for unauthenticated users. Anonymous sessions are managed via HttpOnly cookies and can be merged into user accounts upon authentication.

Key Changes

Anonymous Session Management

  • Added server/utils/anonymous-session.ts to handle session lifecycle:
    • Sessions are created on first feedback action (submit or vote)
    • Stored in anonymous_session table with 90-day TTL
    • HttpOnly cookie (veerify_anon_session) persists across browser restarts
    • Sessions auto-refresh on activity

Feedback & Voting APIs

  • Vote endpoint (/api/feedback/[id]/vote.post.ts):

    • Changed from requireAuth to optionalAuth to allow anonymous voting
    • Tracks votes by voterSessionId for anonymous users, voterUserId for authenticated users
    • Supports vote toggle (upvote/downvote)
  • Feedback submission (/api/feedback/index.post.ts and public variant):

    • Added authorSessionId field to track anonymous submissions
    • Anonymous users can optionally provide email for notifications
  • Feedback listing (/api/feedback/index.get.ts and public variant):

    • Returns hasVoted status for both authenticated and anonymous users
    • Added isOwn flag to identify user's own submissions
    • Queries votes by session ID for anonymous viewers

Session Merge on Authentication

  • New endpoint /api/auth/merge-anonymous.post.ts:
    • Transfers anonymous feedback ownership to authenticated user
    • Merges votes, handling duplicates (removes if user already voted on same item)
    • Cleans up anonymous session and cookie after merge

UI Enhancements

  • Feedback cards now show "Your submission" badge with star icon for own submissions
  • Added visual ring highlight (ring-2 ring-primary/30) for own submissions
  • Added email helper text in submit dialog explaining notification benefits
  • Improved vote error handling with generic message

Testing

  • Added comprehensive e2e test suite (tests/e2e/anonymous-feedback.spec.ts):
    • Session creation and persistence
    • Anonymous submission and voting
    • Own submission highlighting
    • Session merge on login
    • Vote toggle functionality

Implementation Details

  • Anonymous sessions survive browser restarts via persistent HttpOnly cookies
  • Vote deduplication prevents double-voting when merging sessions
  • All anonymous data is properly cleaned up after merge
  • Sessions expire after 90 days of inactivity
  • IP address and user agent are captured for session tracking

https://claude.ai/code/session_01Wxa3T56cAhuTFJDx2qUrpQ

- Add anonymous session utility (server/utils/anonymous-session.ts) that
  manages HttpOnly cookie-based sessions with 90-day expiry
- Update feedback POST routes (internal + public) to associate anonymous
  sessions with feedback submissions via authorSessionId
- Update vote POST route to allow anonymous voting (was auth-only)
- Update feedback GET routes to track hasVoted and isOwn for anonymous users
- Add session merge API (POST /api/auth/merge-anonymous) that transfers
  feedback and votes to authenticated user on login, handling duplicates
- Update public feedback page to highlight own submissions with ring style
  and "Your submission" badge, enable anonymous voting, add email helper text
- Add Playwright e2e tests for anonymous feedback flows

https://claude.ai/code/session_01Wxa3T56cAhuTFJDx2qUrpQ
@vercel

vercel Bot commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
veerify Error Error Feb 9, 2026 5:59pm

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1d614fe53a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +40 to +42
const voteCondition = userId
? and(eq(vote.feedbackId, id), eq(vote.voterUserId, userId))
: and(eq(vote.feedbackId, id), eq(vote.voterSessionId, anonSessionId!))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Check session vote when authenticated before inserting vote

When session.user is present, voteCondition only looks at voterUserId, so an existing anonymous vote from the same browser (voterSessionId) is ignored. If a person votes anonymously and then authenticates before the merge step runs, this branch inserts a second vote row and increments feedback.voteCount again, allowing the same person to be counted twice for one feedback item.

Useful? React with 👍 / 👎.


export default defineEventHandler(async (event) => {
const session = await requireAuth(event)
const session = await optionalAuth(event)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate anonymous voting to public feedback items

This handler now uses optionalAuth, but it never checks whether the target feedback belongs to a public project before accepting an unauthenticated vote. As a result, any unauthenticated request with a known feedback ID from a private project can still mutate vote counts, which violates private-project access expectations.

Useful? React with 👍 / 👎.

@Andreas-Froyland
Andreas-Froyland merged commit 788231e into main Feb 9, 2026
8 of 11 checks passed
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.

2 participants