Fix all critical/high/medium/low audit items

Critical – money integrity:
- server.ts: restrict Socket.IO CORS to NEXT_PUBLIC_SITE_URL (remove origin:"*")
- server.ts: validate userId against DB on join_room before any debit/credit
- server.ts: atomic coin-flip joiner claim via updateMany(where:{status:WAITING,joinerId:null})
- server.ts: await pong game_over payout+room update before emitting result; log errors
- prediction/route.ts: wrap market resolve + all payouts in one Prisma transaction;
  concurrent PATCH returns 409; dust remainder credited to first winner

High – data truth:
- raised/page.tsx, leaderboard/route.ts, cards/route.ts: add status:"succeeded"
  filter to all donation aggregations
- polls/next-president/route.ts: replace full in-memory row scan with DB-side
  groupBy + bounded 14-day window for daily activity chart

Medium – ops:
- faq-board/page.tsx: add admin approve/reject tab (visible to ADMIN role)

Low – UX/consistency:
- faq-board, billboard, spotlight, cards: replace hardcoded "BWT" with creditTicker()
- faq-board: read submitCost/voteCost from API response instead of hardcoded values
- WalletActions.tsx: make refreshBalance stable with useCallback; remove
  eslint-disable exhaustive-deps suppression

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
root
2026-05-16 00:56:13 +00:00
parent 391d90a754
commit c6a7b2e08d
11 changed files with 313 additions and 133 deletions

View File

@@ -11,7 +11,7 @@ export async function GET(req: NextRequest) {
// Aggregate total donated per user
const rows = await prisma.donation.groupBy({
by: ["userId"],
where: { userId: { not: null } },
where: { userId: { not: null }, status: "succeeded" },
_sum: { amountUsdCents: true },
_count: { id: true },
orderBy: { _sum: { amountUsdCents: "desc" } },