104 lines
8.8 KiB
Markdown
104 lines
8.8 KiB
Markdown
# 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 user’s 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.*
|