Files
democratic-money/redmeFIXSES.md
2026-05-16 00:47:44 +00:00

104 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# redmeFIXSES — systematic issue & follow-up list
This document is a **repo-wide audit** of the Democratic Fundraising Platform (`/root/fundraising-platform`): things that need a **solution, decision, wiring, or hardening** before calling the product complete for real-world use. Items are grouped for triage; paths are relative to the project root.
---
## 1. Security & authentication (high priority)
| # | Issue | Where / notes |
|---|--------|----------------|
| 1.1 | **Socket.IO trusts `userId` from the browser** — anyone can emit another users id and trigger **debits, refunds, or payouts** against the wrong wallet. There is no session cookie / JWT handshake binding the socket to `auth()`. | `server.ts` (`join_room`, `paddle_move` for Pong); `src/components/casino/CoinFlipRoom.tsx` passes `userId` into `io(...).emit("join_room", { roomId, userId })`. **Fix:** authenticate on connection (e.g. pass a short-lived signed token or upgrade request with session), ignore client-supplied `userId`, use server-derived id. |
| 1.2 | **CORS is `origin: "*"`** on the Socket.IO server — combined with 1.1, third-party sites could script abuse if a victim is logged in (and even without, id spoofing is already possible). | `server.ts``new SocketIOServer(..., { cors: { origin: "*" } })`. **Fix:** restrict to `siteUrl()` / env allowlist. |
| 1.3 | **Registration endpoint is unthrottled** — email enumeration, credential stuffing, mass fake accounts. | `src/app/api/register/route.ts`. **Fix:** rate limit (IP + email), CAPTCHA or proof-of-work for production, optional email verification before wallet use. |
| 1.4 | **No automated password reset** — acceptable as a placeholder only; increases support load and lockout risk. | `src/app/forgot-password/page.tsx` (static copy). **Fix:** SMTP or auth provider + `VerificationToken` flow. |
| 1.5 | **Admin role** can only be granted out-of-band (DB/seed). There is **no secure admin bootstrap or audit log** for privileged actions. | `src/lib/admin.ts`, usage in FAQ/billboard/etc. **Fix:** documented procedure, optional separate admin app, logging. |
| 1.6 | **Public FAQ API leaks pending community submissions** (display names + text) to anyone. | `src/app/api/faq/route.ts` `GET` returns `pending` without auth. **Fix:** require auth for pending, or admin-only pending list. |
---
## 2. Data integrity, races, and consistency
| # | Issue | Where / notes |
|---|--------|----------------|
| 2.1 | **`/api/public/stats` vs treasury** — donation aggregates use **no `status: "succeeded"` filter**, while `getTreasuryTotalUsdCents()` filters `succeeded`. Today most rows are succeeded-only, but the two can **diverge** if statuses are ever used. | `src/app/api/public/stats/route.ts` vs `src/lib/treasury.ts`. **Fix:** align queries on the same predicate. |
| 2.2 | **Prediction bets: debit and row insert are not one transaction** — edge cases under concurrency could desync balance vs bets. | `src/app/api/games/prediction/route.ts` (`debitForBet` then `predictionBet.create`). **Fix:** single `prisma.$transaction`. |
| 2.3 | **Movement meter milestone bonuses** — crossing `METER_TARGET` can race under concurrent `POST`s; bonus grants are not idempotent keys. | `src/app/api/boost/route.ts`. **Fix:** row lock / serializable transaction, or separate “epoch_closed” record before paying bonuses. |
| 2.4 | **Ledger vs `GameSession`**`DEBIT_GAME_BET` / `CREDIT_GAME_WIN` ledger lines are **not FK-linked** to `GameSession`/`GameRoom`, making reconciliation and support harder. | `src/lib/game-ledger.ts`, `prisma/schema.prisma`. **Fix:** optional `gameSessionId` / `gameRoomId` on `LedgerEntry`. |
| 2.5 | **Pong server state**`setInterval` runs in process memory; **multi-instance deploy** would break. **Process crash** mid-game loses state (partial debits may already have happened). | `server.ts`. **Fix:** document single-instance requirement, or Redis-backed rooms + recovery. |
---
## 3. Features implemented in API only (no UI wiring)
Grep shows **no** `fetch("/api/…")` usage from the React app for these routes; they are **dead from an end-user perspective** unless hit manually or by a future screen.
| Route area | Files | Needed solution |
|------------|--------|-----------------|
| Community FAQ board | `src/app/api/faq/route.ts` | Add a page or embed: list approved, submit/vote when signed in, admin approve/reject UI (or drop the API). |
| Democracy billboard | `src/app/api/billboard/route.ts` | Wire ticker/post UI; or remove until product wants it. |
| Issue spotlight auction | `src/app/api/spotlight/route.ts` | Wire homepage “issue of the week” UI to real bids; or remove. |
| Movement meter (BWT sink + milestone) | `src/app/api/boost/route.ts` | The homepage **“Grassroots meter”** (`ProgressSection`) is **Stripe USD goal**, not this BWT meter — product copy vs implementation are **misaligned**. Either wire `/api/boost` into the UI + clarify copy, or retire the feature. |
| Supporter trading cards | `src/app/api/cards/route.ts` | Add profile/wallet cards UI; or remove. |
Static marketing FAQ (`src/components/FaqSection.tsx`) and the dynamic FAQ API are **two parallel systems** — decide which is source of truth.
---
## 4. Product / compliance / copy
| # | Issue | Notes |
|---|--------|--------|
| 4.1 | **Committee & legal placeholders** | README and env still assume `NEXT_PUBLIC_COMMITTEE_LEGAL_NAME_PLACEHOLDER`, disclaimers, counsel review before live fundraising. |
| 4.2 | **Casino / prediction / games** | Server-side games exist; **jurisdiction, gambling, and campaign-finance** implications need counsel. Disclosure copy may be insufficient sitewide. |
| 4.3 | **Prediction markets** | Creator resolves outcome (`PATCH` in `src/app/api/games/prediction/route.ts`) — no independent oracle; reputational and fairness risk. |
| 4.4 | **User-generated initiatives** | `src/app/api/initiatives/route.ts` — public text up to 8k chars with **no moderator queue** in code. |
| 4.5 | **Email verification** | `User.emailVerified` exists in Prisma but credentials flow does not set or enforce it. |
---
## 5. Configuration, dev/prod parity, and tooling
| # | Issue | Where / notes |
|---|--------|----------------|
| 5.1 | **`NEXT_PUBLIC_SITE_URL` missing from `.env.example`** | Defaults in `src/lib/public-env.ts` to `https://democracyrising.org` — local/staging can silently emit **wrong canonical URLs** in metadata/sitemap. |
| 5.2 | **`npm run dev` uses `server.ts`** | Socket games depend on this. **`npm run dev:next`** skips custom server — **coin flip / pong break** if a developer uses the wrong script. Document clearly or unify. |
| 5.3 | **`npm run lint` is only `tsc --noEmit`** | `eslint` is in `devDependencies` but not wired as a script — style and Next lint rules are unused in CI script form. |
| 5.4 | **Strict-Transport-Security with preload** | `next.config.ts` applies globally. **Local HTTP dev** is usually fine, but misconfigured hosts + HSTS have bitten teams before — confirm intended behavior for each environment. |
| 5.5 | **Sitemap is incomplete** | `src/app/sitemap.ts` omits major routes (`/missions`, `/initiatives`, `/casino`, etc.) vs actual app surface. **SEO** gap or intentional — decide. |
---
## 6. UX / polish still called out historically
From the workspace plan `platform_bug_hunt_&_polish_30ad9fd4.plan.md` (many items marked done), the following **may still be desirable**:
| Item | Notes |
|------|--------|
| **Active nav state** | `src/components/SiteNav.tsx` — no “current page” styling for non-anchor routes. |
| **Loading shimmer coverage** | Plan mentioned skeletons beyond what `MockExchangeTicker` already does for errors. |
| **DonationCheckout** | Mentions `.env` in user-visible copy — consider production-friendly wording (`src/components/DonationCheckout.tsx`). |
---
## 7. Testing & observability
| # | Gap |
|---|-----|
| 7.1 | No unit test suite — only `scripts/smoke-integration.ts`, `scripts/http-smoke.sh`, and `scripts/full-site-test.ts` (manual against a running server). |
| 7.2 | No structured logging / APM hooks for Stripe webhooks or game transactions. |
| 7.3 | Webhook path returns 500 on processing errors — need **alerting** and **Stripe retry** monitoring in production. |
---
## 8. Quick reference — files that most often need attention
- **Auth & gatekeeping:** `src/middleware.ts` (only protects `/wallet`), `src/auth.ts`, `src/auth.config.ts`
- **Money:** `src/app/api/webhooks/stripe/route.ts`, `src/app/api/stripe/create-payment-intent/route.ts`
- **Realtime games:** `server.ts`, `src/app/api/games/rooms/route.ts`, `src/components/casino/CoinFlipRoom.tsx`
- **Public truth vs internals:** `src/app/api/public/stats/route.ts`, `src/lib/treasury.ts`
---
*Generated by a full-tree pass of source, Prisma schema, config, and README; re-run this audit after large feature merges.*