2.8 KiB
2.8 KiB
2026-07-16 — P0 security (WT-A)
Closes the deployment-readiness P0s for auth, CORS, body size, hygiene, and client-side secret handling.
Files changed
New:
server/src/config/index.js— single source of truth for env-derived config. Crashes on missing required vars in production.server/scripts/lint-no-backups.js—npm run lint:hygienefails if any*.bak/*.orig/*~is staged.server/scripts/refactor-jwt-secret.js— one-shot script that rewrote 56 files.server/scripts/smoke-test.js— post-change smoke test (health, login, offline secret, me/credentials, 2MB body rejection).server/.env.example— documents all env vars with required-in-prod set..harness/changelogs/2026-07-16-p0-security.md— this file.
Modified (56 server files):
- All controllers (54) +
server/src/index.js+server/src/services/wsHub.jsno longer hardcode'africa-alert-secret-key-2024'. They importconst { jwtSecret: JWT_SECRET } = require('../config')(or'./config'forindex.js). server/src/index.js: CORS restricted toALLOWED_ORIGINSin prod (permissive in dev). JSON body limit dropped to 1mb. Added/api/healthendpoint + 413 error handler forentity.too.large.client/src/lib/offlineAuth.ts:OFFLINE_JWT_SECRETnow sourced fromlocalStorage(populated at login from the newoffline_jwt_secretresponse field). Dev fallback only inimport.meta.env.DEV; null in prod unlessALLOW_CLIENT_OFFLINE_MINT=true.client/src/store/auth.ts: capturesoffline_jwt_secretfrom/api/auth/loginresponse and caches it viacacheOfflineJwtSecret.server/package.json: new scriptslint:hygieneandrefactor:jwt-secret.README.md: production security checklist section.
Deleted:
server/src/controllers/sync.controller.js.bak(6045 bytes).
Verification
Smoke test (node server/scripts/smoke-test.js):
- ✓
GET /api/health→ 200 - ✓
POST /api/auth/loginreturnstoken+offline_jwt_secret - ✓
GET /api/auth/me/credentials(with token) → 200 - ✓ 2MB JSON body → 413 (was 500 before the error handler)
- 5/5 checks pass
Regression net: 14/14 Playwright E2E specs green (cd client && npx playwright test).
Hygiene: npm run lint:hygiene → "OK — no .bak / .orig / ~ files in server/src or client/src".
Select-String -Path 'server\src' -Pattern "'africa-alert-secret-key-2024'" → 0 matches.
Select-String -Path 'client\src' -Pattern "OFFLINE_JWT_SECRET\s*=\s*'africa-alert" → 0 matches.
Known follow-ups (deferred to WT-B, WT-C)
WT-B(offline cache) is independent and should land before the next deploy.WT-C(docker) will addHEALTHCHECKthat hits/api/health(already present now).- The dev fallback string
dev-only-insecure-secret-do-not-use-in-productionis intentional; the prod crash on missingJWT_SECRETis inserver/src/config/index.js.