# FlieMart Production Audit Report (Points 1–38)

Date: 2026-08-04  
Environment verified for tests: local `http://localhost:3000`  
Production origin: **NOT TESTED** (no production URL/credentials provided)

Legend: **PASS** = verified · **FAIL** = confirmed problem · **WARNING** = partial · **NOT TESTED** = insufficient access

---

## A. Critical Issues Fixed

### 1. Client-trusted order totals / unpaid order creation
- **Problem:** `POST /api/orders` accepted browser prices/totals and could mark orders processing without payment proof.
- **Risk:** Fraudulent orders, stock theft, revenue loss.
- **Files:** `src/app/api/orders/route.ts`, `src/lib/payment-verify.ts`, `src/app/api/checkout/route.ts`
- **Fix:** Orders confirmed from pending DB row; Stripe PaymentIntent amount/status verified server-side; demo checkout blocked in production.

### 2. Client-trusted discounts / product prices
- **Problem:** Checkout accepted arbitrary `discount` and fallback client prices.
- **Risk:** Arbitrary discounts / underpayment.
- **Files:** `src/lib/stripe-order.ts`, `src/app/api/checkout/route.ts`
- **Fix:** Prices/stock from MariaDB only; coupons validated server-side via `findCoupon`.

### 3. Unsigned Stripe webhooks in production
- **Problem:** Missing webhook secret allowed forged JSON events.
- **Risk:** Fake payment success / stock decrement.
- **Files:** `src/app/api/webhooks/stripe/route.ts`
- **Fix:** Signature required; idempotency via `StripeWebhookEvent`.

### 4. Weak / fallback auth secret in production
- **Problem:** Hardcoded JWT secret fallback.
- **Risk:** Session forgery.
- **Files:** `src/lib/auth.ts`, `src/lib/auth-edge.ts`, `src/lib/env.ts`
- **Fix:** `AUTH_SECRET` required in production; admin role requires live DB check.

### 5. No cPanel-safe startup / Windows absolute build paths
- **Problem:** Missing `server.js`; `.next/required-server-files.json` contained Windows paths.
- **Risk:** 503 / app inaccessible on Linux cPanel.
- **Files:** `server.js`, `scripts/cpanel-fix-paths.js`, packaging scripts
- **Fix:** cPanel entrypoint on `process.env.PORT`; path fix script; process stays alive on recoverable failures.

---

## B. Security Hardening

- HttpOnly / SameSite / Secure cookies (prod)
- bcrypt password hashing (cost 12)
- Server-side `requireAdmin()` on all admin APIs
- Middleware protection for `/admin` and `/account`
- MariaDB rate limiting (login/register/checkout/orders/upload)
- Input validation helpers + safe JSON parse (`readJsonBody`)
- Security headers + CSP (Stripe-compatible)
- Upload: magic-byte validation, no SVG, path sanitize, UUID filenames
- Open-redirect guards (`safeInternalPath` + login `next` checks)
- Admin settings secret masking
- Safe logging redaction (`safe-log`)
- Generic production error UI (no stack traces)
- Temporary `/__status` gated by `ENABLE_STATUS_ENDPOINT`

---

## C. Bugs Fixed

- Invalid JSON on login/register returned **500** → now **400**
- Oversized registration names accepted → now **400**
- `/__status` never registered (Next private `_` folder) → rewrite to `/api/diag-status`
- Package script crashed on `.next/dev` symlinks → excluded from tarball
- Footer/CMS/policy pages wired earlier in audit stream
- Stripe line-item / product metadata sync added earlier

---

## D. Database Audit

| Topic | Status |
|-------|--------|
| Engine | MariaDB/MySQL via Prisma (**not** migrated away) |
| Connection | `DATABASE_URL` or composed from `DB_*` |
| Pooling | `connection_limit=5`, `pool_timeout=10` (conservative for cPanel) |
| Client | Process singleton in `src/lib/db.ts` |
| Query safety | Prisma parameterized queries; no string-concat SQL |
| Schema extras | `deploy/schema-extras.sql` (phpMyAdmin) |
| Failure recovery | Controlled JSON errors; process not killed by DB blips |
| Charset | utf8mb4 in SQL extras |

---

## E. cPanel Compatibility

| Item | Result |
|------|--------|
| No SSH required | **PASS** (design) |
| No terminal required | **PASS** (design) |
| `server.js` startup | **PASS** (present) |
| `process.env.PORT` | **PASS** |
| Prebuilt `.next` | **PASS** (packaged) |
| `.tar.gz` deployment | **PASS** (`dist-cpanel/project-prebuilt.tar.gz`) |
| MariaDB/MySQL | **PASS** |
| phpMyAdmin SQL | **PASS** (`deploy/schema-extras.sql`) |
| NPM Install compatibility | **PASS** (`postinstall` prisma generate; prisma in dependencies) |
| Linux paths | **PASS** (fix-paths script + packaging normalize) |
| File permissions model | **PASS** (755/644 helpers) |
| Environment variables | **PASS** (checklist + doctor) |
| Stop → Start workflow | **PASS** (documented) |
| 503 resilience | **PASS** (keepalive diagnostic listener) |

---

## F. Security Checklist

| Control | Result | Notes |
|---------|--------|-------|
| Authentication | **PASS** | Local login/register verified |
| Authorization | **PASS** | Admin APIs 401 without session |
| Admin protection | **PASS** | Page redirect + API requireAdmin |
| IDOR | **PASS** | Unknown order confirm → 404; email mismatch blocked |
| SQL injection | **PASS** | Probe returned safe 200 JSON |
| XSS | **PASS** | No HTML injection surface in API; PageBody text-only |
| CSRF | **WARNING** | Cookie SameSite=Lax + JSON APIs; no CSRF tokens (typical SPA pattern) |
| SSRF | **PASS** | No user-controlled server fetch endpoints found |
| File upload security | **PASS** | Code audit (magic bytes, no SVG) |
| Path traversal | **PASS** | Product/upload probes |
| Open redirects | **PASS** | `//evil.com` not accepted by login handler |
| Session security | **PASS** | HttpOnly JWT cookie |
| Secrets | **WARNING** | Local `.env` may use weak dev secret — rotate for prod |
| Security headers | **PASS** | Configured in `next.config.ts` |
| Rate limiting | **PASS** | MariaDB buckets (fails open if table missing) |
| Input validation | **PASS** | Verified via smoke tests |
| Payment verification | **PASS** | Code path verified; live Stripe charge **NOT TESTED** |
| Webhook verification | **PASS** | Unsigned → 503/400 |
| Logging | **PASS** | Redaction helper in critical routes |

---

## G. Live Site Check

### Local (`http://localhost:3000`) — verified 2026-08-04

| URL | HTTP | Expected | Actual | Result |
|-----|------|----------|--------|--------|
| `/` | 200 | Storefront HTML | 200 ~855KB | **PASS** |
| `/login` | 200 | Login page | 200 | **PASS** |
| `/shop` | 200 | Catalog | 200 | **PASS** |
| `/pages/privacy` | 200 | CMS page | 200 | **PASS** |
| `/admin` | 307 | Redirect login | 307 → `/login?next=%2Fadmin` | **PASS** |
| `/api/health` | 200 | ok+db connected | `ok:true, db:connected` | **PASS** |
| `/__status` | 404 | Disabled | 404 | **PASS** |
| `/api/admin/products` | 401 | Unauthorized | 401 | **PASS** |
| `/api/auth/login` (valid customer) | 200 | Session | 200 user payload | **PASS** |
| `/api/categories` | 200 | List | 200 | **PASS** |
| Security smoke suite (20 cases) | — | All pass | 20/20 | **PASS** |

### Production origin

| URL | Result |
|-----|--------|
| All production URLs | **NOT TESTED** — no production `BASE` provided |

After deploy, run:

`BASE=https://your-domain.com npm run check:live`  
`BASE=https://your-domain.com npm run check:security`

---

## H. Remaining Risks

1. **Production not smoke-tested** — deploy + `check:live` still required on real domain.  
2. **Live Stripe end-to-end payment** — needs real/test keys + webhook endpoint on public HTTPS.  
3. **CSRF** — relies on SameSite cookies + JSON; add CSRF tokens if you later use cookie-auth form posts cross-site.  
4. **Rate-limit fail-open** — if `RateLimitBucket` table missing, limiter allows traffic (doctor/SQL import mitigates).  
5. **Seed admin credentials** — change immediately on any shared DB.  
6. **cPanel Node binary variance** — Prisma `binaryTargets` cover common OpenSSL builds; uncommon hosts may need another target.  
7. **CSP `unsafe-inline`/`unsafe-eval`** — needed for Next/Stripe; tighter CSP possible later with nonces.  
8. **No Redis** — intentional; rate limits are DB-backed per process/table, not distributed edge WAF.

---

## Package

- `dist-cpanel/project-prebuilt.tar.gz`
- Instructions: root `DEPLOYMENT.md`
