← back to Codex Review 2026 05 03
morning-review.md
98 lines
# Morning Review Queue · 2026-05-04
Findings the overnight loop did NOT auto-apply. Sorted by project. Severity: H/M/L.
## site-factory
**Note:** All 8 PHI4 findings reference files that do not exist in `/Users/stevestudio2/Projects/site-factory` (no `utils/`, `models/`, `pages/`, or `components/` directories — actual structure is `admin/`, `critic/`, `db/`, `orchestrator/`, `sites/`, `stages/`, `viewer/`). PHI4 appears to have hallucinated a generic Next.js project. Other 7 panelists (Codex, Claude, Qwen, Kimi, DeepSeek-R1, GPT-OSS, Mistral) returned empty sections. Recommend re-running debate with concrete file context, or treating these as non-actionable.
Hallucinated findings (preserved for audit):
- H · `utils/dbConnect.js:10-15` — DB connection per request, suggest singleton (file does not exist)
- H · `models/userModel.js:30-35` — overly complex query builder (file does not exist)
- M · `pages/api/authenticate.js:25-30` — dead branches in auth (file does not exist)
- H · `components/Navbar.js:60-65` — over-componentized nav items (file does not exist)
- M · `utils/helpers.js:5-10` — unused utility functions (file does not exist)
- H · `pages/api/dataFetch.js:40-45` — sequential queries should use Promise.all (file does not exist)
- H · `components/UserList.js:20-25` — re-renders from inline fns (file does not exist)
- M · `pages/api/userUpdate.js:35-40` — duplicate error handling (file does not exist)
## VictoryStays
**Note:** `cross_exam.md` is empty — the 8-way debate crashed mid-loop (codex quota exceeded, kimi moonshot call failed, mac1-panel ollama unreachable). Only `round_1/claude.txt` produced adversarial findings; qwen/phi4 returned summaries (non-actionable). Queueing all 13 claude.txt findings — all touch the **victorystays** CNCP-listed PM2 service, so per overnight rules everything goes to morning regardless of severity.
All findings reference `/Users/stevestudio2/Projects/VictoryStays/`. Severity from claude.txt headers (CRITICAL→H, HIGH→H, MEDIUM→M).
### CRITICAL (security/correctness, ship-blocking)
- H · `server.js:38` — Block regex `/^\/(data|scripts|logs|admin|node_modules|package(?:-lock)?\.json|.*\.(?:py|md|sh|env)$)/i` omits `.js`, so `GET /server.js`, `/api-claim.js`, `/api-deep-dive.js`, `/ecosystem.config.js`, `/api-newspapers.js` are all served by static middleware. Full source disclosure (incl. ecosystem env). Fix: add `|.*\.js$`, or stop serving `__dirname` and whitelist a `public/` dir.
- H · `api-claim.js:109-120` — `patchHandler` does `loadClaims() → mutate → fs.writeFileSync` while `POST /api/claim` does `fs.appendFileSync` on the same file with no lock. Concurrent POST during PATCH silently loses claims (and the postcard code). Fix: serialize via write queue or `proper-lockfile` (note: dependency change, needs Steve auth).
- H · `api-claim.js:35-73` — POST has no rate limit, no email-format check, no captcha; one curl loop fills `claims.jsonl` and spams the operator firehose. Fix: `express-rate-limit` (5/min/IP) + email regex + min body length (note: new dep).
### HIGH
- H · `server.js:79` — `app.get('/api/claim', requireAdmin, …)` gates the *public* APN-lookup branch (api-claim.js:91-95) behind `ADMIN_KEY`. Either move admin check inside `handler` so non-admin GETs with `?apn=` still work, or document/remove that branch — currently dead code.
- H · `api-deep-dive.js:175` — `if (!addr.includes(street)) continue;` substring-matches; `"BEDFORD"` matches `"BEDFORD VIEW DR"`, `"WHITTIER"` matches `"WHITTIER BLVD"`. Fix: word-boundary regex `new RegExp(\`\\\\b${street}\\\\b\`).test(addr)`.
- H · `home.html:334, 364` — `<a href="${it.url}">` and `<a href="${a.url}">` interpolate URLs raw. Server-encoded today, but breaks on `&` and lacks `javascript:` scheme guard. Fix: `escapeHtml(url)` + reject non-http(s).
- H · `api-deep-dive.js:351-357` — `/api/deep-dive` triggers synchronous external LOC fetch per call (5s timeout, in-memory `Map` cache only). Attacker iterating addresses pegs the request loop and evicts the 500-entry cache. Fix: move LOC into background `victorystays-enrich` step, or add per-IP rate limit + persistent LRU TTL.
### MEDIUM
- M · `scripts/pull-all-city-parcels.py:60, 65` — `la-noho` lists `"91602"` twice; `la-westside` lists `"90230"` twice (also in `culver-city`). Wastes ArcGIS quota and double-inserts parcels. Fix: dedupe via `set()` per-city + cross-city exclusivity assertion.
- M · `ecosystem.config.js:42-43` — `max_restarts: 50` + `restart_delay: 5000` means a transient upstream blip permanently stops the enricher after ~4 min of crash-looping. Fix: drop `max_restarts` (use pm2 default), rely on `min_uptime`.
- M · `api-deep-dive.js:55` & `api-newspapers.js:15` — `_curatedCache` and LOC `CACHE` Map are process-lifetime forever; editing `data/*-residents.json` requires pm2 restart. Fix: `mtime` check or 10-min TTL.
- M · `server.js:38` (second issue) — Block regex misses `.env.local`, `.env.production`, `.git/*`, top-level `.bak`/`.swp`, arbitrary `*.json` outside `data/` (`tsconfig.json`, future `secrets.json`). Tighten to positive `public/` allowlist.
- M · `api-deep-dive.js:154-160` — `parseYearRange("1956-present")` correct, but `"c. 1956"` / `"early 1960s"` falls into single-year branch and silently returns just first 4-digit run — `"early 1960s · sold 1972"` becomes `start=1960, end=null`, hiding the sale year. Fix: capture *last* 4-digit run as `end` when two are present.
- M · `api-claim.js:55` — `req.ip || req.headers['x-forwarded-for']` — without `app.set('trust proxy', …)`, `req.ip` is loopback (CF/proxy upstream) and the `x-forwarded-for` fallback is attacker-controlled. Fix: `app.set('trust proxy', 'loopback')` (or CF IP list) and just use `req.ip`.
- M · `search.html:178`, `beverly-hills.html:22007`, `templates/city.html:503` — `escapeHTML(a.rollYear)`, `escapeHTML(p.zip)`, `escapeHTML(d.links.assessor)`: HTML-escaping a URL inside `href="…"` doesn't block `javascript:` schemes. Fix: scheme-validate before insertion (`/^https?:/i.test(url)`).
**Why all queued, none auto-applied:** Every file above serves the `victorystays` CNCP-listed PM2 service. None match auto-apply criteria (no typo/grammar/dead-import/formatting fixes in this batch). Three CRITICAL findings (rate-limit, file-lock) imply new npm dependencies, which auto-rules forbid touching.
## malden-house
**Note:** All 4 PHI4 findings reference files that do not exist in `/Users/stevestudio2/Projects/malden-house` (no `pages/`, `components/`, `utils/`, or `services/` directories — actual structure is flat vanilla HTML/CSS/JS: `index.html`, `browse.{html,css,js}`, `dashboard.*`, `network.*`, `rental.*`, `schedule.*`, `signup.js`, `theme.js`, `neighborhoods.js`, `test-e2e.js`). PHI4 hallucinated a generic Next.js project. Other 7 panelists (Codex, Claude, Qwen, Kimi, DeepSeek-R1, GPT-OSS, Mistral) returned empty/count-only sections — Claude explicitly said "No changes to review." Nothing actionable. Recommend re-running debate with concrete file context, or treating all as non-actionable.
Hallucinated findings (preserved for audit):
- H · `pages/api/users.js:15-20` — nested DB callbacks, suggest async/await (file does not exist)
- H · `components/UserForm.js:10-12` — excessive abstraction in custom hook (file does not exist)
- M · `utils/dbUtils.js:5-8` — unused DB utility functions (file does not exist)
- H · `services/userService.js:22-25` — over-engineered service layer (file does not exist)
Mistral returned count-only ("CRITICAL: 4, HIGH: 6, MEDIUM: 0") with no file references — non-actionable.
## jill-website
**Note:** All PHI4 findings reference files that do not exist in `/Users/stevestudio2/Projects/jill-website` (no `pages/`, `components/`, or `utils/` directories — actual project is an Express app with `server.js`, `src/`, `views/`, `scripts/`, `tasks/`, `jillzmesses/`). PHI4 emitted only stub headers with no body content (`**\`pages/api/users.js\`:**`, `**\`components/UserProfile.js\`:**`, `**\`utils/db.js\`:**`) and empty severity buckets (CRITICAL/HIGH/MEDIUM all empty). Other 7 panelists (Codex, Claude, Qwen, Kimi, DeepSeek-R1, GPT-OSS, Mistral) returned fully empty sections. Recommend re-running debate with concrete file context, or treating these as non-actionable.
Hallucinated stub findings (preserved for audit, no severity assignable):
- ? · `pages/api/users.js` — header only, no body (file does not exist in jill-website)
- ? · `components/UserProfile.js` — header only, no body (file does not exist in jill-website)
- ? · `utils/db.js` — header only, no body (file does not exist in jill-website)
## stayclaim
cross_exam.md non-actionable: 7 panelists emitted nothing; PHI4 emitted only severity-bucket headers ("**Critical Findings**", "**High Findings**", "**Medium Findings**", "**No Critical Findings**") with no file references or finding bodies. Nothing to triage, nothing to queue. Note kept for audit symmetry with sibling projects.
## wholivedthere
**Note:** All 3 PHI4 findings reference files that do not exist in `/Users/stevestudio2/Projects/wholivedthere` (no `pages/`, `components/`, or `utils/` directories — actual structure is `data/`, `mcp-la-records/`, `public/`, `scripts/` with top-level `PLAN.md`, `CHANGES.md`, `INTEGRATION.md`, `REVIEW-2026-05-04.md`, `PLAN-geo-archival.md`). PHI4 hallucinated a generic Next.js project. Other 7 panelists (Codex, Claude, Qwen, Kimi, DeepSeek-R1, GPT-OSS, Mistral) returned fully empty sections; Mistral emitted only empty severity-bucket headers. Recommend re-running debate with concrete file context, or treating these as non-actionable.
Hallucinated findings (preserved for audit):
- H · `pages/api/user.js:45` — nested promise chain instead of async/await for DB ops (file does not exist)
- H · `components/UserForm.js:12` — unnecessary abstraction with custom hooks for form state (file does not exist)
- M · `utils/db.js:78` — dead branch in error handling logic (file does not exist)
## claimmyaddress
**Note:** Project `/Users/stevestudio2/Projects/claimmyaddress/` contains NO code files — only `README.md`, `CHANGES.md`, `.env`, `.env.example`. All 6 PHI4 findings reference `CITADEL_BACKEND/*` paths (not even matching the project name) that do not exist anywhere in the workdir; PHI4 hallucinated a phantom TypeScript/Next.js backend. Kimi explicitly said the diff was truncated and declined to review. Other 6 panelists (Codex, Claude, Qwen, DeepSeek-R1, GPT-OSS) returned empty sections. Mistral returned a vague meta-summary with no file refs. Nothing actionable. Recommend re-running debate with concrete file context, or treating all as non-actionable.
Hallucinated findings (preserved for audit):
- H · `CITADEL_BACKEND/pages/api/user.ts` — excessive nested async functions, suggest flatten (path does not exist; project has no `CITADEL_BACKEND/`, no `pages/`, no `.ts` files)
- H · `CITADEL_BACKEND/pages/api/user.ts` — unnecessary custom-hook abstraction (path does not exist)
- H · `CITADEL_BACKEND/pages/api/auth.ts` — redundant middleware checks (path does not exist)
- H · `CITADEL_BACKEND/pages/api/auth.ts` — over-engineered error handling (path does not exist)
- H · `CITADEL_BACKEND/utils/db.ts` — dead branch in DB connection logic (path does not exist)
- M · `CITADEL_BACKEND/utils/db.ts` — unnecessary data-access abstraction layers (path does not exist)
## bubbesblock
**Audit note (overnight-yolo 2026-05-03):** Cross-exam produced no actionable findings.
- Project state: `/Users/stevestudio2/Projects/bubbesblock` contains only `README.md`, `CHANGES.md`, `.env`, `.env.example` (plus `.git`). No source code yet.
- Codex / Claude / Qwen / Kimi / DeepSeek-R1 / GPT-OSS / Mistral: all returned empty findings sections in `cross_exam.md`.
- PHI4: emitted only file-header stubs with no bodies — `pages/api/user.js`, `components/UserProfile.js`, `utils/auth.js`, `services/userService.js`, `models/UserModel.js` — and empty CRITICAL/HIGH/MEDIUM severity buckets. None of those paths exist in this project; PHI4 appears to have hallucinated a generic Next.js layout.
**Recommendation:** treat this run as a no-op. If a real review is wanted, re-run claude-codex once bubbesblock has actual source files committed; the panel had nothing to read against.