← back to Commercialrealestate
CRCP DRE: contrarian fixes — verified only on exact match, drop dead DB branch
6abac2e3e7b10cd98d9d9f60c5b20ddcc5889fd3 · 2026-07-10 17:17:39 -0700 · Steve Abrams
- pick(): surname-only match REMOVED (wrong-person risk). Now dre_verified=true
ONLY for a single exact full-name match; >1 exact or first+last -> 'probable'
(license shown, never badged verified). Invariant: no probable is dre_verified.
- serve.js: removed the broken DB-first branch (broker table has no license_type/
license_status/license_expiration/firm_name cols; it always threw + was swallowed).
Snapshot is the canonical DRE store (prod has no Postgres).
- viewer: 'probable' badge/pill/filter, is_proof_run coverage banner, unmatched=no-license.
- Regen 25-agent proof: 10 verified, 9 probable, 6 unmatched, 0 errors. Rendered
headless (cards/badges verified). $0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M data/licensed-agents.jsonM public/licensed-agents.htmlM scripts/fetch-dre-licenses.jsM scripts/serve.js
Diff
commit 6abac2e3e7b10cd98d9d9f60c5b20ddcc5889fd3
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jul 10 17:17:39 2026 -0700
CRCP DRE: contrarian fixes — verified only on exact match, drop dead DB branch
- pick(): surname-only match REMOVED (wrong-person risk). Now dre_verified=true
ONLY for a single exact full-name match; >1 exact or first+last -> 'probable'
(license shown, never badged verified). Invariant: no probable is dre_verified.
- serve.js: removed the broken DB-first branch (broker table has no license_type/
license_status/license_expiration/firm_name cols; it always threw + was swallowed).
Snapshot is the canonical DRE store (prod has no Postgres).
- viewer: 'probable' badge/pill/filter, is_proof_run coverage banner, unmatched=no-license.
- Regen 25-agent proof: 10 verified, 9 probable, 6 unmatched, 0 errors. Rendered
headless (cards/badges verified). $0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
data/licensed-agents.json | 104 ++++++++++++++++++++++++++----------------
public/licensed-agents.html | 13 ++++--
scripts/fetch-dre-licenses.js | 55 ++++++++++++----------
scripts/serve.js | 19 +++-----
4 files changed, 110 insertions(+), 81 deletions(-)
diff --git a/data/licensed-agents.json b/data/licensed-agents.json
index 17aaf5c..ddc403e 100644
--- a/data/licensed-agents.json
+++ b/data/licensed-agents.json
@@ -1,16 +1,17 @@
{
"meta": {
"source": "California Department of Real Estate — public license lookup (www2.dre.ca.gov/PublicASP/pplinfo.asp)",
- "note": "Public government data. Every dre_verified record was confirmed against the live DRE lookup by name -> License ID -> detail. Unmatched/ambiguous agents are labeled honestly, never fabricated.",
+ "note": "Public government data. dre_verified=true ONLY for a single exact full-name DRE match. \"probable\" = license found but the name match was not unique (>1 exact, or first+last only) — shown but never badged verified. Unmatched agents labeled honestly, never fabricated.",
"cost": "$0 (local plain-HTTP, no captcha, no paid API)",
- "fetched_at": "2026-07-11T00:07:47.403Z",
+ "fetched_at": "2026-07-11T00:15:32.878Z",
"total_agents": 556,
+ "is_proof_run": true,
"counts": {
- "verified": 19,
+ "verified": 10,
+ "probable": 9,
"unmatched": 6,
- "ambiguous": 0,
"errors": 0,
- "from_cache": 6,
+ "from_cache": 0,
"in_snapshot": 25
}
},
@@ -29,6 +30,7 @@
"responsible_broker_id": "02078273",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=02203716"
@@ -46,9 +48,10 @@
"responsible_broker": "",
"responsible_broker_id": "",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01141632"
},
{
@@ -56,6 +59,7 @@
"dre_query": "Prichard, Tony",
"brokerage": "BERKSHIRE HATHAWAY HOMESEVICES Crest Real estate",
"dre_verified": false,
+ "dre_match": "unmatched",
"status_label": "unmatched",
"match_confidence": "no-match",
"candidates": 0
@@ -74,6 +78,7 @@
"responsible_broker_id": "01190835",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=00977686"
@@ -92,6 +97,7 @@
"responsible_broker_id": "",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01843510"
@@ -109,9 +115,10 @@
"responsible_broker": "",
"responsible_broker_id": "",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=00698730"
},
{
@@ -127,9 +134,10 @@
"responsible_broker": "SFRE LA Ventura, Inc. 345 E COLORADO BLVD PASADENA, CA 91101",
"responsible_broker_id": "02221897",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=00638098"
},
{
@@ -146,6 +154,7 @@
"responsible_broker_id": "00616212",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=02038924"
@@ -164,6 +173,7 @@
"responsible_broker_id": "",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01279085"
@@ -182,6 +192,7 @@
"responsible_broker_id": "",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01239506"
@@ -199,9 +210,10 @@
"responsible_broker": "",
"responsible_broker_id": "",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01904809"
},
{
@@ -209,6 +221,7 @@
"dre_query": "BRAY, JONATHAN",
"brokerage": "PULTE HOMES OF CALIFORNIA, INC",
"dre_verified": false,
+ "dre_match": "unmatched",
"status_label": "unmatched",
"match_confidence": "ambiguous(2)",
"candidates": 2
@@ -218,6 +231,7 @@
"dre_query": "Liu, Mandy",
"brokerage": "BluEleven Realty Group",
"dre_verified": false,
+ "dre_match": "unmatched",
"status_label": "unmatched",
"match_confidence": "no-match",
"candidates": 0
@@ -236,6 +250,7 @@
"responsible_broker_id": "",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01782549"
@@ -245,6 +260,7 @@
"dre_query": "Kim, Kenny",
"brokerage": "Coldwell Banker Realty",
"dre_verified": false,
+ "dre_match": "unmatched",
"status_label": "unmatched",
"match_confidence": "ambiguous(6)",
"candidates": 6
@@ -262,9 +278,10 @@
"responsible_broker": "",
"responsible_broker_id": "",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01927654"
},
{
@@ -280,9 +297,10 @@
"responsible_broker": "Realty World Legends Of Santa Clarita Valley Inc 25115 AVENUE STANFORD STE B121 VALENCIA, CA 91355",
"responsible_broker_id": "01251341",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=00891062"
},
{
@@ -290,6 +308,7 @@
"dre_query": "Ross, Brenda",
"brokerage": "Equity Union",
"dre_verified": false,
+ "dre_match": "unmatched",
"status_label": "unmatched",
"match_confidence": "ambiguous(2)",
"candidates": 2
@@ -308,6 +327,7 @@
"responsible_broker_id": "",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01747381"
@@ -317,6 +337,7 @@
"dre_query": "Park, Jerry",
"brokerage": "AVM Real Estate Services",
"dre_verified": false,
+ "dre_match": "unmatched",
"status_label": "unmatched",
"match_confidence": "ambiguous(2)",
"candidates": 2
@@ -328,15 +349,16 @@
"license": "01854651",
"license_type": "Salesperson",
"license_city": "CALABASAS",
- "status": "",
- "expiration": "",
- "issued": "",
- "responsible_broker": "",
- "responsible_broker_id": "",
- "discipline": "unknown",
+ "status": "LICENSED",
+ "expiration": "11/24/28",
+ "issued": "11/25/08",
+ "responsible_broker": "Pinnacle Estate Properties Inc 23733 MALIBU RD STE 500 MALIBU, CA 90265",
+ "responsible_broker_id": "00905345",
+ "discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
- "status_label": "unknown",
+ "status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01854651"
},
{
@@ -353,6 +375,7 @@
"responsible_broker_id": "01904054",
"discipline": "none",
"match_confidence": "exact",
+ "dre_match": "verified",
"dre_verified": true,
"status_label": "active",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01450380"
@@ -370,9 +393,10 @@
"responsible_broker": "",
"responsible_broker_id": "",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01200471"
},
{
@@ -388,9 +412,10 @@
"responsible_broker": "",
"responsible_broker_id": "",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=01453736"
},
{
@@ -406,9 +431,10 @@
"responsible_broker": "Best Realty & Investment Inc 17057 CHATSWORTH ST GRANADA HILLS, CA 91344",
"responsible_broker_id": "01816803",
"discipline": "none",
- "match_confidence": "surname-only",
- "dre_verified": true,
- "status_label": "active",
+ "match_confidence": "first+last",
+ "dre_match": "probable",
+ "dre_verified": false,
+ "status_label": "probable",
"dre_url": "https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=00994541"
}
]
diff --git a/public/licensed-agents.html b/public/licensed-agents.html
index 9d64e07..299f5e3 100644
--- a/public/licensed-agents.html
+++ b/public/licensed-agents.html
@@ -61,6 +61,7 @@ let DATA=[], META={}, filt='all', q='', sortKey='name';
const esc=s=>String(s??'').replace(/[&<>"]/g,c=>({'&':'&','<':'<','>':'>','"':'"'}[c]));
function statusClass(a){
+ if(a.dre_match==='probable') return 'b-warn';
if(!a.dre_verified) return a.status_label==='error'?'b-bad':'b-un';
const s=(a.status_label||'').toLowerCase();
if(s==='active') return 'b-active';
@@ -68,6 +69,7 @@ function statusClass(a){
return 'b-warn';
}
function statusText(a){
+ if(a.dre_match==='probable') return 'probable';
if(!a.dre_verified) return a.status_label==='error'?'DRE error':(a.match_confidence||'unmatched');
return a.status||a.status_label||'?';
}
@@ -77,9 +79,10 @@ function expNum(a){ const m=/(\d{2})\/(\d{2})\/(\d{2})/.exec(a.expiration||'');
function render(){
let rows=DATA.filter(a=>{
if(filt==='verified'&&!a.dre_verified) return false;
+ if(filt==='probable'&&a.dre_match!=='probable') return false;
if(filt==='broker'&&!/broker/i.test(a.license_type||'')) return false;
if(filt==='salesperson'&&!/salesperson/i.test(a.license_type||'')) return false;
- if(filt==='unmatched'&&a.dre_verified) return false;
+ if(filt==='unmatched'&&a.license) return false;
if(q){ const hay=(a.agent+' '+(a.brokerage||'')+' '+(a.license||'')+' '+(a.responsible_broker||'')+' '+(a.license_type||'')).toLowerCase(); if(!hay.includes(q)) return false; }
return true;
});
@@ -119,9 +122,10 @@ function pills(){
const defs=[
['all','All',()=>true],
['verified','✔ DRE-verified',a=>a.dre_verified],
+ ['probable','Probable',a=>a.dre_match==='probable'],
['broker','Brokers',a=>/broker/i.test(a.license_type||'')],
['salesperson','Salespersons',a=>/salesperson/i.test(a.license_type||'')],
- ['unmatched','Unmatched',a=>!a.dre_verified],
+ ['unmatched','Unmatched',a=>!a.license],
];
$('#pills').innerHTML=defs.map(([k,l,f])=>`<span class="pill ${filt===k?'on':''}" data-f="${k}">${l} <b>${n(f)}</b></span>`).join('');
document.querySelectorAll('.pill').forEach(p=>p.onclick=()=>{filt=p.dataset.f;pills();render();});
@@ -130,8 +134,9 @@ async function load(){
let d; try{ d=await (await fetch('/api/agents/licensed')).json(); }catch(e){ $('#note').textContent='Failed to load /api/agents/licensed'; return; }
DATA=d.agents||[]; META=d.meta||{};
const c=META.counts||{};
- $('#note').innerHTML=`Source: <b>${esc(d.source||'?')}</b> · ${esc(d.label||'')} `+
- (c.verified!=null?`— <span class="verified">${c.verified} verified</span>, ${c.unmatched||0} unmatched, ${c.errors||0} errors of ${META.total_agents||DATA.length}. ${esc(META.cost||'')}`:'');
+ const proof=META.is_proof_run?` <b style="color:var(--warn)">⚠ PROOF RUN — ${c.in_snapshot||DATA.length} of ${META.total_agents} agents processed so far</b>`:'';
+ $('#note').innerHTML=`Source: <b>${esc(d.source||'?')}</b> · ${esc(d.label||'')}${proof} `+
+ (c.verified!=null?`— <span class="verified">${c.verified} verified</span>, ${c.probable||0} probable, ${c.unmatched||0} unmatched, ${c.errors||0} errors. ${esc(META.cost||'')}`:'');
pills(); render();
}
// controls
diff --git a/scripts/fetch-dre-licenses.js b/scripts/fetch-dre-licenses.js
index 18118c4..2946e7b 100644
--- a/scripts/fetch-dre-licenses.js
+++ b/scripts/fetch-dre-licenses.js
@@ -111,25 +111,26 @@ function parseDetail(html) {
responsible_broker_id: respBrokerId, responsible_broker: respBrokerName, discipline };
}
-// Choose the best candidate for an agent name (+ optional city hint).
-function pick(cands, wantName, cityHint) {
- if (!cands.length) return { match: null, ambiguity: 'no-match' };
+// Choose the best candidate for an agent name. Returns {match, ambiguity, tier}.
+// tier drives dre_verified: ONLY a single exact full-name match is 'verified'.
+// Weaker matches (>1 exact, or surname+first-name-only) are 'probable' — the
+// license is still surfaced but NEVER badged verified (wrong-person guard).
+function pick(cands, wantName) {
+ if (!cands.length) return { match: null, ambiguity: 'no-match', tier: 'unmatched' };
const norm = s => s.toLowerCase().replace(/[^a-z, ]/g, '').replace(/\s+/g, ' ').trim();
const want = norm(wantName);
const exact = cands.filter(c => norm(c.name) === want);
- if (exact.length === 1) return { match: exact[0], ambiguity: 'exact' };
- if (exact.length > 1) {
- if (cityHint) {
- const byCity = exact.filter(c => c.city && cityHint.toUpperCase().includes(c.city.toUpperCase()));
- if (byCity.length === 1) return { match: byCity[0], ambiguity: 'exact+city' };
- }
- return { match: exact[0], ambiguity: `multi-exact(${exact.length})` };
- }
- // last-name-only fallthrough: if exactly one candidate shares the surname, take it (low confidence)
- const surname = want.split(',')[0];
- const bySur = cands.filter(c => norm(c.name).split(',')[0] === surname);
- if (bySur.length === 1) return { match: bySur[0], ambiguity: 'surname-only' };
- return { match: null, ambiguity: `ambiguous(${cands.length})` };
+ if (exact.length === 1) return { match: exact[0], ambiguity: 'exact', tier: 'verified' };
+ if (exact.length > 1) return { match: exact[0], ambiguity: `multi-exact(${exact.length})`, tier: 'probable' };
+ // fallthrough: exactly one candidate whose surname AND first token match the query
+ const [wLast, wFirst = ''] = want.split(',').map(s => s.trim());
+ const wFirstTok = wFirst.split(' ')[0];
+ const near = cands.filter(c => {
+ const [cLast, cFirst = ''] = norm(c.name).split(',').map(s => s.trim());
+ return cLast === wLast && cFirst.split(' ')[0] === wFirstTok && wFirstTok;
+ });
+ if (near.length === 1) return { match: near[0], ambiguity: 'first+last', tier: 'probable' };
+ return { match: null, ambiguity: `ambiguous(${cands.length})`, tier: 'unmatched' };
}
function loadCache() { try { return JSON.parse(fs.readFileSync(CACHE, 'utf8')); } catch { return {}; } }
@@ -141,7 +142,7 @@ async function main() {
for (const r of (src.results || [])) {
if (!r.agent) continue;
const key = r.agent.trim();
- if (!seen.has(key)) seen.set(key, { agent: key, brokerage: r.brokerage || '', cityHint: '' });
+ if (!seen.has(key)) seen.set(key, { agent: key, brokerage: r.brokerage || '' });
}
const agents = [...seen.values()];
const cache = FORCE ? {} : loadCache();
@@ -162,13 +163,15 @@ async function main() {
try {
const html = await post(dreName);
const cands = parseSearch(html);
- const { match, ambiguity } = pick(cands, dreName, a.cityHint);
+ const { match, ambiguity, tier } = pick(cands, dreName);
if (!match) {
- rec = { ...rec, dre_verified: false, status_label: 'unmatched', match_confidence: ambiguity, candidates: cands.length };
+ rec = { ...rec, dre_verified: false, dre_match: 'unmatched', status_label: 'unmatched', match_confidence: ambiguity, candidates: cands.length };
unmatched++;
} else {
await sleep(jitter());
const detail = parseDetail(await getDetail(match.license));
+ const isVerified = tier === 'verified'; // ONLY exact single-name match earns the badge
+ const live = /LICENSED/i.test(detail.status);
rec = {
...rec,
license: match.license,
@@ -181,11 +184,12 @@ async function main() {
responsible_broker_id: detail.responsible_broker_id,
discipline: detail.discipline,
match_confidence: ambiguity,
- dre_verified: true,
- status_label: /LICENSED/i.test(detail.status) ? 'active' : (detail.status ? detail.status.toLowerCase() : 'unknown'),
+ dre_match: tier, // 'verified' | 'probable'
+ dre_verified: isVerified,
+ status_label: isVerified ? (live ? 'active' : (detail.status ? detail.status.toLowerCase() : 'unknown')) : 'probable',
dre_url: `${BASE}?License_id=${match.license}`,
};
- verified++;
+ if (isVerified) verified++; else ambiguous++; // probable matches counted separately, NOT as verified
}
} catch (e) {
rec = { ...rec, dre_verified: false, status_label: 'error', error: String(e.message).split('\n')[0] };
@@ -202,17 +206,18 @@ async function main() {
const snapshot = {
meta: {
source: 'California Department of Real Estate — public license lookup (www2.dre.ca.gov/PublicASP/pplinfo.asp)',
- note: 'Public government data. Every dre_verified record was confirmed against the live DRE lookup by name -> License ID -> detail. Unmatched/ambiguous agents are labeled honestly, never fabricated.',
+ note: 'Public government data. dre_verified=true ONLY for a single exact full-name DRE match. "probable" = license found but the name match was not unique (>1 exact, or first+last only) — shown but never badged verified. Unmatched agents labeled honestly, never fabricated.',
cost: '$0 (local plain-HTTP, no captcha, no paid API)',
fetched_at: new Date().toISOString(),
total_agents: agents.length,
- counts: { verified, unmatched, ambiguous, errors, from_cache: fromCache, in_snapshot: results.length },
+ is_proof_run: results.length < agents.length,
+ counts: { verified, probable: ambiguous, unmatched, errors, from_cache: fromCache, in_snapshot: results.length },
},
agents: results,
};
fs.writeFileSync(OUT, JSON.stringify(snapshot, null, 1));
console.log(`\n✔ wrote ${OUT}`);
- console.log(` agents total ${agents.length} | verified ${verified} | unmatched ${unmatched} | errors ${errors} | cached ${fromCache}`);
+ console.log(` agents total ${agents.length} | verified ${verified} | probable ${ambiguous} | unmatched ${unmatched} | errors ${errors} | cached ${fromCache}`);
console.log(` cost: $0 (local)`);
}
module.exports = { toDreName, parseSearch, parseDetail, pick };
diff --git a/scripts/serve.js b/scripts/serve.js
index edfe026..6f20099 100644
--- a/scripts/serve.js
+++ b/scripts/serve.js
@@ -230,22 +230,15 @@ app.get('/api/leads/frank', async (req, res) => {
// same idiom as /api/residential so it works locally (Postgres) AND on prod (snapshot JSON,
// produced by scripts/fetch-dre-licenses.js). Public-safe fields only — no mailing addresses.
const LICENSED_LABEL = 'Real-estate agents/brokers verified against the California DRE public license lookup (govt data, $0). Unmatched/ambiguous agents labeled honestly, never fabricated.';
-app.get('/api/agents/licensed', async (req, res) => {
+app.get('/api/agents/licensed', (req, res) => {
+ // DRE license data lives in the snapshot (data/licensed-agents.json, built by
+ // scripts/fetch-dre-licenses.js). The `broker` DB table has no DRE columns, so there is
+ // no DB path for this feed — snapshot is canonical (and prod has no Postgres anyway).
+ // Public-safe fields only; mailing addresses are never included.
const PUBLIC = ['agent', 'brokerage', 'license', 'license_type', 'license_city', 'status',
'status_label', 'expiration', 'issued', 'responsible_broker', 'responsible_broker_id',
- 'discipline', 'match_confidence', 'dre_verified', 'dre_url'];
+ 'discipline', 'match_confidence', 'dre_match', 'dre_verified', 'dre_url'];
const pubOnly = a => Object.fromEntries(PUBLIC.filter(k => k in a).map(k => [k, a[k]]));
- // 1) live DB first (broker table already carries a license column)
- if (brokerdb) {
- try {
- const r = await brokerdb.pool.query(
- `SELECT name AS agent, firm_name AS brokerage, license,
- license_type, license_status AS status, license_expiration AS expiration
- FROM broker WHERE license IS NOT NULL AND license <> '' ORDER BY name LIMIT 5000`);
- if (r.rows.length) return res.json({ agents: r.rows, label: LICENSED_LABEL, source: 'db' });
- } catch (_) { /* columns may not exist yet -> fall through to snapshot */ }
- }
- // 2) snapshot fallback (prod / no-DB)
try {
const { meta = {}, agents = [] } = JSON.parse(fs.readFileSync(path.join(ROOT, 'data', 'licensed-agents.json'), 'utf8'));
return res.json({ agents: agents.map(pubOnly), meta, label: LICENSED_LABEL, source: 'snapshot' });
← e914e06 CRCP: DRE-licensed agents/brokers DB from CA public govt dat
·
back to Commercialrealestate
·
auto-save: 2026-07-10T18:09:50 (1 files) — data/condos-redfi 4c1be11 →