← back to Codex Review 2026 04 30

consensus/malden-house.md

65 lines

# Consensus — malden-house
Generated 2026-04-30T23:48:03-07:00. Source: codex review/fix/rereview/round-2 artifacts (round-3 was quota-blocked).

## Codex pass-1 review (top risks)
## Top Risks (P0 — fix this week)
- [signup.js](/Users/stevestudio2/Projects/malden-house/signup.js:217): email verification is hardcoded `verified: true`; anyone can “claim” any address/email locally. Fix with server-side account creation, signed email tokens, and address ownership rules.
- [rental.js](/Users/stevestudio2/Projects/malden-house/rental.js:735): guest inquiries are saved to the visitor’s own `localStorage`, not the host’s inbox; production inquiries silently disappear. Fix with a backend endpoint/email delivery and explicit failure UI.
- [network.js](/Users/stevestudio2/Projects/malden-house/network.js:33): public source exposes Tailscale IPs, public server IPs, hostnames, service names, and ports. Remove `network.html/js` from public builds or gate behind auth/VPN-only hosting.
- [dashboard.js](/Users/stevestudio2/Projects/malden-house/dashboard.js:30), [browse.js](/Users/stevestudio2/Projects/malden-house/browse.js:35), [rental.js](/Users/stevestudio2/Projects/malden-house/rental.js:374): trusted `localStorage`/geocoder fields are rendered through template `innerHTML`; malicious stored records can execute markup/script-like payloads. Build DOM nodes with `textContent` or sanitize all interpolated fields.
- [signup.js](/Users/stevestudio2/Projects/malden-house/signup.js:263): demo seed includes Steve’s real-looking email/phone/address in source and UI. Replace with fake fixtures before any public repo/deploy.


## Round-1 applied
## Applied

- `dashboard.js:17` — added a tiny HTML/attribute escaping helper — needed before using template `innerHTML` with stored records.
- `dashboard.js:39` — escaped rental card fields, image attributes, slugs, chips, address text, and host names — prevents malicious `localStorage` records from injecting markup.
- `dashboard.js:149` — escaped inquiry inbox names, email text, dates, events, street labels, and data attributes — prevents stored inquiry fields from rendering as HTML.
- `dashboard.js:193` — escaped photo picker labels/values and photo `src` attributes — keeps stored rental/photo metadata inside attributes/text.
- `browse.js:7` — added the same escaping helper — needed for the browse card renderer.
- `browse.js:44` — escaped browse card image attributes, chip text, address/city fields, and host names; encoded the map query — prevents stored rental data injection.
- `rental.js:35` — added HTML/attribute escaping helpers — needed for dynamic rental templates.
- `rental.js:89` — escaped trailer and cover fields from stored address, host, and venue data — prevents injected markup during trailer playback.
- `rental.js:329` — escaped the property card subline while preserving its `<br>` layout — prevents address/county markup injection.
- `rental.js:383` — escaped nearest-venue headline, name, sports, drive minutes, and date chip fields — prevents venue string injection in the event grid.
- `rental.js:503` — escaped drive-meta minutes, contact heading host name, footer host name, countdown banner text, closest-event text, and inquiry thank-you fields — closes remaining touched `innerHTML` paths fed by stored/user data.


## Codex re-review verdict: FIX BEFORE SHIP

## New issues introduced
`rental.js:35` — `escapeHtml(s)` uses `String(s || "")`, so numeric `0` becomes empty; applied numeric call-sites like `rental.js:503` can render blank drive minutes — P2


## Round-2 applied
## Round 2 Applied

- `dashboard.js:17` — changed `escapeHtml` to preserve numeric `0`, and added `formatMoney()` — fixes rereview concern that `String(s || "")` collapses zero values.
- `dashboard.js:62` — escaped stored `r.price.mid` before card `innerHTML` insertion — fixes rereview missed call-site `dashboard.js:59`.
- `browse.js:7` — changed `escapeHtml` to preserve numeric `0`, and added `formatMoney()` — fixes rereview concern that `String(s || "")` collapses zero values.
- `browse.js:66` — escaped stored `r.price.mid` before browse card `innerHTML` insertion — fixes rereview missed call-site `browse.js:63`.
- `rental.js:35` — changed `escapeHtml` to preserve numeric `0`, and added `formatMoney()` — fixes rereview concern/new issue around numeric display.
- `rental.js:142` — escaped stored `price.mid` in trailer outro pricing — fixes rereview missed call-site `rental.js:139`.
- `rental.js:424` — passed escaped `address.city` into dynamic guide heading templates while preserving intended `<br>` markup — fixes rereview missed call-site `rental.js:422`.
- `rental.js:459` — passed escaped `address.city` into dynamic history heading templates while preserving intended `<br>` markup — fixes rereview missed call-site `rental.js:459`.
- `rental.js:622` — escaped stored `price.mid`, `price.low`, `price.high`, and `baseline.base` in the price card — fixes rereview missed call-site `rental.js:619`.
- `signup.js:147` — added HTML/attribute escaping helpers for signup dynamic HTML — supports the rereview signup and autocomplete findings.
- `signup.js:240` — escaped submitted/geocoded signup status fields before `setStatus(...innerHTML...)` — fixes rereview missed call-site `signup.js:226`.
- `signup.js:328` — escaped Nominatim autocomplete `data-val`, line 1, and line 2 fields before `innerHTML` insertion — fixes rereview missed call-site `signup.js:312`.


## Still deferred for Steve

- P0 — `signup.js:217` — email verification is hardcoded as `verified: true` — requires backend accounts, signed email tokens, and ownership rules.
- P0 — `rental.js:735` — guest inquiries save only to visitor `localStorage` — needs backend/email delivery and failure UX.
- P0 — `network.js:33` — network viewer exposes IPs, hostnames, service names, and ports — removal/gating needs a deploy/access decision.
- P0 — `signup.js:263` — demo seed contains Steve's real-looking contact/address fixture — content/PII cleanup needs Steve.
- P1 — `signup.js:219` — slug collisions overwrite rentals — durable handling belongs with server-side claim rules.
- P1 — `signup.js:9`, `rental.js:3` — schema mismatch wipes stored data — migration/backup behavior touches user data.
- P1 — `dashboard.js:220` — photo uploads can exceed `localStorage` quota — storage migration is larger than a surgical safe fix.
- P1 — `schedule.js:5` — venue data is duplicated — shared-data refactor is outside the safe list.
- P1 — `test-e2e.js:12` — smoke test depends on live Nominatim and sleeps — test changes were out of scope.
- P1 — `network.js:28` — `no-cors` polling can show false green health — needs a same-origin proxy or removal decision.