Gemini raised 19 findings across five rounds. 14 were real and are fixed. 3 were wrong and are rejected with the evidence. 2 were mine — Gemini caught an error in my own reasoning and a self-inflicted mess, and both are fixed too.
The most expensive one: the appraisal engine was pricing a four-door building's expenses as if it had one door, printing a 3.90% cap rate where 3.27% is honest — about a 19% error in implied value, on a number real buyers and sellers read.
Nothing here changed what the site is meant to do. Two changes touch the shared backend that the live Neuman site also uses; both were regression-tested against the live site and it stayed up.
Finding: market_cap_rate() computed each comparable sale's expenses with a
hardcoded 1 unit, while the rent it compared against covered the whole building.
Reproduced and measured against the live expense module, on a four-door comp:
Root cause: gross rent is rent-per-sqft × total sqft — the whole building —
but insurance scales per door and the repairs floor is per door. One door's costs against four doors'
rent inflates NOI, which inflates the extracted market cap rate.
Then Gemini caught my fix. I first fell back to 1 when the door count was
unknown and called that "conservative". Gemini said that is backwards — it is the flattering guess,
not the safe one. It was right, and worse than either of us assumed: I measured
294 of 400 multifamily comps carry no door count at all, so the fallback was the
common path. Now a sale the MLS filed as income property with no provable door count is
dropped from the sample and counted as skipped, the same as any other sale that cannot carry
its own evidence.
Tested: rebuilt a real report end-to-end — 467 NE 1 AVE, Deerfield Beach, a genuine 4-unit — income approach still stated, cap rate extracted from 21 comparable sales, median 3.66%.
Each adjustment line is capped at 15% of the sale price so one bad MLS field cannot swing the value. But the "is this really comparable" test read the capped total — so a sale that genuinely needed a huge adjustment showed a small one and passed. The test now reads the raw uncapped sum; the capped figure is still what displays.
Finding (Gemini, round 5): nobody had tested whether leads actually deliver.
I posted a real showing request and read it back out of the store. The lead arrived — but
address, listingId, neighborhood and price were
silently thrown away, because the handler whitelisted only name, phone, email, note and kind.
A showing request was reaching the team with no property on it.
Fixed and re-tested — the same post now stores:
Forms that call the field message or summary instead of note
are now aliased too, and anything else a form sends is kept rather than dropped.
Confirmed live: the API answered "No account found with that email" — so anyone could test addresses and map the customer list. Both real and unknown emails now get the identical answer. Verified on this site and the live one; login and session endpoints regression-tested; live site stayed up throughout. Reset-email failures are now logged instead of silently swallowed, and the rate-limit table evicts aged-out entries instead of wiping every visitor's counter at once.
The Meta Pixel loaded on preview pages and pulled the real pixel id from the shared config, so review clicks landed in production ad analytics. It is now gated to the production hostname — dark on the preview, and it wakes up by itself at cutover with nothing to remember.
The existing guard clicks tool buttons but skips the tool pages themselves. I wrote a second guard
that crawls every local link on every page against the filesystem. First run found 30 dead
links. I curl-tested ten distinct targets: nine were real live 404s —
/premium.html, /analyze.html, /find, /push.html,
/area.html, /motivated.html, /migration_map.html,
/re_sold_rented.html, /datamined_login.html. The tenth,
/listing?key=, redirected into a directory that returns 403.
All ten now retarget to the real local page, wired into the link fixer so future copies inherit it. Current state: all local links resolve, 192 pages checked.
Only the hand-built pages carried it; the copied tool pages had none. It is now injected by the one script that already walks every page and runs inside both copy scripts — so copies get it forever, not just today. Live on the tool pages.
Gemini, round 5: neither of us had checked IDX compliance. Confirmed: only one page carried the "Listing data © MIAMI Association of REALTORS®, deemed reliable but not guaranteed" line, while six other pages render the same feed. Now injected on every page that pulls listing-level MLS data. Verified live.
The site replaces a live brokerage site with existing search rankings. There was no redirect plan. Built three things:
| File | What it does |
|---|---|
cutover_redirects.py | Generates 108 verified 301s for old URLs that moved. It refuses to write the file if any target does not exist — it failed twice and made me map seven more pages by hand. |
cutover_noindex.py | Turns search engines on: 174 pages plus 13 generator
scripts, so noindex cannot sneak back on the next rebuild. Dry-run unless you pass
--do. |
CUTOVER.md | The ordered runbook — backup, switch, redirects, reset-email domain, search engines on, rollback path. |
The nav swapper's pattern could run past the end of its own <nav> element and
swap the wrong list. One live page has the shape that triggers it. Nothing was broken yet; it is
bounded now, and re-running the swapper reports "applied to 0 pages" — proof it is idempotent.
Gemini reviewed these rejections and agreed with all three.
Evidence: the backend binds 127.0.0.1:25062 only — verified with
ss -tlnp — and every nginx location does
proxy_set_header X-Real-IP $remote_addr;, which overwrites whatever the client
sent. There is no path from the public internet that reaches the app with an attacker-chosen IP.
The other half of that finding — a global counter wipe — was real, and is fixed.
Evidence: it would change nothing. The inner test needs
len(near) ≥ 3 AND len(near) < len(kept); with exactly three comps kept that is
"at least 3 and fewer than 3" — unsatisfiable either way. It also matches appraisal practice:
you cannot drop a comparable when you are already at the minimum of three.
Evidence: I read all three return paths of the function that builds those records. Every one of them sets the key. No live crash path.
| Check | Result |
|---|---|
| Tool-button guard (signed out) | 120 buttons across 206 pages — every one opens what it promises |
| Every local link on every page | all resolve, 192 pages checked |
| Redirect map | 108 lines, 0 unmapped, every target verified to exist |
| All 9 doors + home, live over HTTPS | 200 each |
| Login / forgot / reset pages | 200 each; wrong password still rejected cleanly |
| Lead submission, end to end | posted and read back, with the property attached |
| Appraisal engine, end to end | real 4-unit report rebuilt, income approach intact |
| Both backend services after restart | active; live Neuman site 200 throughout |
</body> tag; your own audit scope excludes
them. Say the word and they get the strip or get pulled from the deploy.This is not a statement that the site is ready to launch. It is ready for you to walk it. The cutover runbook exists and its steps are testable, but no one has done a rehearsal, and the signed-in half of the site has never been swept by a guard.
| Repository | Commits |
|---|---|
/opt/apps/prestige-neuman | pixel gate · Equal Housing · MLS attribution ·
bounded nav regex · check_all_links.py · 10 link retargets · cutover kit |
/opt/apps/bk-fl-calc | reset enumeration closed · email failures logged · rate-limit eviction · lead property context |
/opt/apps/remined | cap-rate door count · unknown-door comps dropped · over-adjusted judged on raw figures |