feat: spam protection and input validation for reviews#42
Conversation
Server-side: - Validate rating is integer 1-5, reject floats and out-of-range - Truncate comments to 2000 chars, allowlist sources (web/mcp/cli) - Rate limit: max 5 reviews per IP per 10 minutes - Duplicate prevention: one review per shader per IP (permanent) - Track client_ip with migration for existing DBs Client-side: - 5-second cooldown after successful submit - Guard against double-click submission - Error messages styled in red, success in muted Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Findings
Open Questions
Verification Signed, |
- Tests now use a temp DATA_DIR per run (idempotent across reruns) - Duplicate prevention relaxed to 24-hour window to avoid blocking users on shared IPs (NAT, offices, mobile carriers) - Added rate-limit threshold test (6th review from same IP is rejected) - Fixed hard-coded IPs in tests that leaked across runs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
I would stop using IP as reviewer identity and keep it only as a coarse abuse signal. The cleanest anonymous approach is an anonymous reviewer token:
That fixes the shared-NAT problem without forcing accounts. Two users in the same office stop colliding, while one browser still cannot spam the same shader repeatedly unless they clear cookies. I would also split controls by purpose:
If you want this to be harder to evade without full auth, add a second layer:
Concretely, I would model it like this:
If cookies are missing or blocked, degrade gracefully:
Signed, |
Replace IP-based duplicate detection with an HttpOnly cookie token. The server mints a random token on first review, hashes it with SHA-256, and stores the hash. Duplicate check is now reviewer_token_hash + shader within 24 hours — different users on the same IP are no longer blocked. IP is retained only for burst rate limiting (5 reviews / 10 min). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
client_ipviagetRequestIP()with DB migration for existing tablesFiles changed
reviews-db.tsclient_ipcolumn + migration-reviews.tsaddReviewReviewsSection.tsxreviews-db.test.node.tsTest plan
bun run check— all tests pass🤖 Generated with Claude Code