Date: 2026-05-28 Owner: platform team Previous passes: v2, v3, v4
Audit pass 4 closed regressions + 11 high-impact items (#147-#157) and filed 24 remaining v4 findings as discrete tasks (#158-#181). The stop hook on the "find all" goal flagged that pass 4 hadn't gone broad enough; this fifth sweep used five more parallel read-only explore agents over surface area that passes 1-4 didn't touch:
| Agent | Findings | Top themes |
|---|---|---|
| schema / migrations / pools | 8 | nullable user_id on payments/api-keys; FK no ON DELETE; pool size drift; status string-not-enum |
| test coverage / gating | 10 | MFA/Stripe/AWS/LLM/TTS all describe.skip on never-set env; wide-range assertions; 16+ control-room E2E skip |
| secrets / crypto / env | 9 | JWT_SECRET hardcoded fallbacks in 3 sites; AUDIT/CDN/WATERMARK key defaults; raw-concat KDF |
| concurrency / races | 15 | check-then-act in svc-auth registration + OAuth; EventEmitter leaks; non-atomic counter increments |
| error handling / null | 8 | 20 silent catches in 3 services; double-! on Map.get; parseInt NaN flowing to DB; 8 process.exit(1) |
50 net-new actionable findings, all filed as discrete tasks #183-#232.
In-session closure#
| # | Task fix | Area |
|---|---|---|
| 207 | iris/api parseInt → parsePositiveIntParam | Err-7 (this commit) |
The rest are tracked in the task list. They're not bundled in-session because each finding lives in a different service and applying them in one commit would create a giant change-set with no per-service review boundary.
Top tier — recommended next-up#
- Sec5-1 (#224) — JWT_SECRET hardcoded fallbacks in 3 svc-auth sites. Production deploy without env var lands on a literal string an attacker can read in the source repo and forge tokens with. Must close before anything ships.
- Sec5-3 (#226) — AUDIT_SECRET_KEY hardcoded fallback compromises audit-log tamper detection. The HMAC can be re-computed from source.
- Con-3 / Con-4 (#211, #212) — svc-auth user registration + OAuth callback have check-then-act races that allow duplicate users on the same email.
- Con-11 (#219) — yemaya BullMQ workers have idempotencyKey declared but no consumer enforces it. Retries double-bill.
- Sch-2 / Sch-3 (#184, #185) — nullable userId on PaymentSubscription
- ApiKey lets orphan rows accumulate with no revocation path.
Out of scope for this audit#
Six surfaces were intentionally NOT covered this pass; flagged for a later pass 6 if needed:
- Container-image security beyond the SHA pin (#145) — Trivy results, CIS docker bench, image-as-root, USER directive sweep
- Infrastructure-as-code (Terraform / Pulumi) drift
- Runtime SBOM completeness
- Policy / RLS (row-level security) on Postgres
- Multi-tenant isolation correctness across the 14 prisma schemas
- E2E test coverage of the v6-egbe game-server flow