← back to Nationalrealestate
TK-16: add Orange County CA (06059) parcel coverage + centroid lat/lng flag — pass 6, CA sweep begins
9af391117973c3834400169449d9e5b550a70ee2 · 2026-08-10 15:19:18 -0700 · Steve Abrams
First of the 'all California, radiating from LA' sweep. OC Public Works legal-lots
layer, ~982,299 parcels. COVERAGE-ONLY (CA AB-1785 suppresses sale price → priced=0,
no events) like la-county/san-diego: address + assessed value + centroid lat/lng.
New general Source flag centroid:true → returnCentroid+outSR=4326 = lightweight lat/lng
from f.centroid without downloading ~982k polygons. AssessmentNo is the parcel key
(LegalLotID repeats across condo units); value fields are string-typed (num parses);
total_value = AssdAmt || LandVal+ImprovedVal. pageSize=2000 matches maxRecordCount.
Verified e2e vs local usre: 3993 parcels all w/ lat/lng, real address/value, priced=0
as expected, parcel_source(06059). tsc clean (my files). Local master, NOT pushed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M SOURCES.mdM src/ingest/parcels/arcgis_sales.tsM src/ingest/parcels/engine.tsM src/jobs/hourly_loop.ts
Diff
commit 9af391117973c3834400169449d9e5b550a70ee2
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 10 15:19:18 2026 -0700
TK-16: add Orange County CA (06059) parcel coverage + centroid lat/lng flag — pass 6, CA sweep begins
First of the 'all California, radiating from LA' sweep. OC Public Works legal-lots
layer, ~982,299 parcels. COVERAGE-ONLY (CA AB-1785 suppresses sale price → priced=0,
no events) like la-county/san-diego: address + assessed value + centroid lat/lng.
New general Source flag centroid:true → returnCentroid+outSR=4326 = lightweight lat/lng
from f.centroid without downloading ~982k polygons. AssessmentNo is the parcel key
(LegalLotID repeats across condo units); value fields are string-typed (num parses);
total_value = AssdAmt || LandVal+ImprovedVal. pageSize=2000 matches maxRecordCount.
Verified e2e vs local usre: 3993 parcels all w/ lat/lng, real address/value, priced=0
as expected, parcel_source(06059). tsc clean (my files). Local master, NOT pushed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
SOURCES.md | 4 +++-
src/ingest/parcels/arcgis_sales.ts | 21 +++++++++++++++++++++
src/ingest/parcels/engine.ts | 1 +
src/jobs/hourly_loop.ts | 1 +
4 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/SOURCES.md b/SOURCES.md
index f10c4cf..47a72a7 100644
--- a/SOURCES.md
+++ b/SOURCES.md
@@ -108,7 +108,7 @@ incl. 8 gated/blocked states → `BROKER-COVERAGE.md`. Adapters: `src/ingest/bro
## Free priced-DEED feeds — config-driven ArcGIS (`src/ingest/parcels/arcgis_sales.ts`)
-Each entry is a keyless ArcGIS REST layer that publishes real recorded SALE PRICE; one `SOURCES` config maps a page of features → parcel row + `parcel_event(event_type='sale')` with grantor/grantee/doc + a `source_url` deep-link. Registered in `parcel_source`, paginated over time by the hourly loop (`src/jobs/hourly_loop.ts`, `runSources` = the config's `cursorKey`). Live configs: `oregon-rlis` (41051/67/05), `spokane` (53063), `alameda` (06001), `deschutes` (41017), `crook` (41013), `sonoma` (06097), `colorado` (statewide composite `08*`), `maricopa` (04013), `thurston` (53067), `palm-beach` (12099), `klamath` (41035), `marion` (41047), `yakima` (53077), `lane` (41039), `jackson` (41029).
+Each entry is a keyless ArcGIS REST layer that publishes real recorded SALE PRICE; one `SOURCES` config maps a page of features → parcel row + `parcel_event(event_type='sale')` with grantor/grantee/doc + a `source_url` deep-link. Registered in `parcel_source`, paginated over time by the hourly loop (`src/jobs/hourly_loop.ts`, `runSources` = the config's `cursorKey`). Live configs: `oregon-rlis` (41051/67/05), `spokane` (53063), `alameda` (06001), `deschutes` (41017), `crook` (41013), `sonoma` (06097), `colorado` (statewide composite `08*`), `maricopa` (04013), `thurston` (53067), `palm-beach` (12099), `klamath` (41035), `marion` (41047), `yakima` (53077), `lane` (41039), `jackson` (41029), `orange-county` (06059, coverage-only — AB-1785, no price).
- **Klamath County OR (41035)** — added 2026-07-27 (TK-16). ArcGIS Online FeatureServer `https://services.arcgis.com/H6Mh1bySxR4oHx6x/arcgis/rest/services/KC_ParcelSales/FeatureServer/0` (item `f6314b12b8cc4c35899157172601bf59`, "KC_ParcelSales" = Klamath County Parcel Sales). `where=SALE_PRICE>1000` → **38,796** priced sales. Rich fields: `SALE_PRICE` (int), `SALE_DATE` (epoch-ms), `OWNER_NAME` (→ grantee), `MIN_SITUS_ADDRESS`+`FIRST_CITY_NAME`, `SUM_FINSQFT`/`SUM_BEDRMS`/`SUM_BATH`, `MIN_YRBLT`, `SUM_Tot_Appr` (total appraised → `total_value`), `SALEBK` (→ doc_number, internal double-spaces collapsed by `clean()`), `FIRST_PROP_ID` (→ apn/source_id), `FIRST_PCLCD` (→ use_desc). Server caps pages at 1000. Verified end-to-end against the local `usre` DB (1,000 parcels + 1,000 sale events + links + source registration on first batch).
@@ -119,3 +119,5 @@ Each entry is a keyless ArcGIS REST layer that publishes real recorded SALE PRIC
- **Lane County OR / Eugene (41039)** — added 2026-08-10 (TK-16, pass 4). Lane County "AddressParcelSales" ArcGIS MapServer, layer 1 "Sales (last 3 years)" `https://lcmaps.lanecounty.org/arcgis/rest/services/AT/AddressParcelSales/MapServer/1` (HTTPS only — the HTTP endpoint returns an Esri "Application Error" page). `where=SalesLayerCityJoin_SalesforGISLayerAll_sale_price>1000` → **~6,731** priced sales (a rolling last-3-years window, so it stays fresh rather than deep-historical). NOTE: this is a JOIN layer, so every attribute key is prefixed `SalesLayerCityJoin_SalesforGISLayerAll_` (bound to a local `P` const in `toRecords`; the un-prefixed `DeedDate` is the exception). Rich fields: `sale_price` (int → `last_sale_price`), `DeedDate` (epoch-ms → `last_sale_date`), `deed_transfer_no` (space-padded → doc_number, trimmed by `clean()`), `deed_type` (WD/PR/... → doc_type), `situs_address`/`city`/`zip`, `stat_class` (property class → use_desc), `maplot` (13-char taxlot → apn/source_id — MUST be the first `outField` since the per-parcel GIS deep-link is `where=<first>='<apn>'`). `reject_code` (ratio-study/arm's-length flag e.g. "Sale Adjusted") is kept, not filtered, and preserved in the row's raw-source JSON for provenance. Verified end-to-end against the local `usre` DB; `tsc` clean.
- **Jackson County OR / Medford (41029)** — added 2026-08-10 (TK-16, pass 5). Jackson County Assessment "LatestSales" FeatureServer `https://spatial.jacksoncountyor.gov/arcgis/rest/services/Assessment/LatestSales/FeatureServer/0` (HTTPS only — HTTP 302-redirects). `where=SalesPrice>1000` → **58,400** priced sales. An unusually rich, CLEAN (unqualified-key) layer: `SalesPrice` (double → `last_sale_price`), `SalesDate` (epoch-ms → `last_sale_date`), `DocumentNumber` (→ doc_number, e.g. `2025-18743`), `DocumentTypeDescription` (deed type e.g. "BARGAIN & SALE" → doc_type; null on some rows), `Grantor`+`Grantee` NAMES (both real), `SiteAddress`/`SiteCity`, `StatClassDescription` (→ use_desc), `YearBuilt`, `SquareFeet` (→ sqft), `maptaxlot` (→ apn/source_id — first `outField` for the deep-link). Also carries `DocumentURL` (recorded-instrument image link) preserved in raw. Verified end-to-end against the local `usre` DB; `tsc` clean.
+
+- **Orange County CA (06059)** — added 2026-08-10 (TK-16, pass 6; first of the "all California, radiating from LA" sweep). OC Public Works ArcGIS `https://ocgis.com/arcpub/rest/services/LegalLotsAttributeOpenData/FeatureServer/0`, **~982,299** parcels. **COVERAGE-ONLY** — CA **AB-1785** suppresses recorded sale price, so like `la-county`/`san-diego-sandag` this config carries NO price/sale-events (`priced=0`); it ingests address + assessed value + centroid lat/lng. Fields: `AssessmentNo` (→ apn/source_id — NOT `LegalLotID`, which repeats across condo units), `SiteAddress`, `SiteCityState` (→ city), `SiteZip5`, `LandVal`/`ImprovedVal`/`AssdAmt` (all `esriFieldTypeString` holding numbers — `num()` parses; `total_value = AssdAmt || LandVal+ImprovedVal` since `AssdAmt` is often null on condo units), `GPLU_DESC`/`ZC_DESCR` (use — almost entirely null, ~1.5k of 982k). lat/lng via the new `centroid:true` Source flag → `returnCentroid=true&outSR=4326` (reads `f.centroid.{x,y}`; native SR is CA State Plane VI feet, so `outSR=4326` is required), which avoids downloading ~982k polygons. `maxRecordCount=2000` (pageSize matched). Verified end-to-end against the local `usre` DB; `tsc` clean.
diff --git a/src/ingest/parcels/arcgis_sales.ts b/src/ingest/parcels/arcgis_sales.ts
index 7efcbfb..b57d3d8 100644
--- a/src/ingest/parcels/arcgis_sales.ts
+++ b/src/ingest/parcels/arcgis_sales.ts
@@ -38,6 +38,7 @@ interface Rec {
interface Source {
key: string; label: string; layer: string; where: string; outFields: string; cursorKey: string;
geometry: boolean; orderBy: string; pageSize?: number; // a valid field for stable resultOffset paging (OID name varies)
+ centroid?: boolean; // request returnCentroid+outSR=4326 (lightweight lat/lng from f.centroid) without downloading full polygons — for geometry-only assessor rolls (e.g. Orange County)
toRecords: (features: any[]) => Rec[];
// TK-50 field-level provenance: our parcel field → the exact source attribute
// it was mapped from in toRecords(). Registered into source_field_map at
@@ -367,6 +368,25 @@ const SOURCES: Record<string, Source> = {
grantor: clean(a.Grantor), grantee: clean(a.Grantee),
docNum: clean(a.DocumentNumber), docType: clean(a.DocumentTypeDescription), raw: a } as Rec; }).filter(Boolean) as Rec[],
},
+ 'orange-county': {
+ // Orange County CA — LA's neighbor, ~982k parcels. CA AB-1785 suppresses recorded
+ // sale price, so this is a COVERAGE config (no price/events, priced=0) like la-county
+ // /san-diego-sandag: address + assessed value + centroid lat/lng. Value fields are
+ // STRING-typed (num() parses); AssdAmt often null on condo units → fall back to
+ // LandVal+ImprovedVal. lat/lng via returnCentroid (centroid:true) — no polygon download.
+ key: 'orange-county', label: 'Orange County CA (Assessor legal lots)', cursorKey: 'orange_county',
+ geometry: false, centroid: true, orderBy: 'OBJECTID', pageSize: 2000,
+ layer: 'https://ocgis.com/arcpub/rest/services/LegalLotsAttributeOpenData/FeatureServer/0',
+ where: 'AssessmentNo IS NOT NULL',
+ outFields: 'AssessmentNo,SiteAddress,SiteCityState,SiteZip5,LandVal,ImprovedVal,AssdAmt,GPLU_DESC,ZC_DESCR',
+ fieldMap: { source_id: 'AssessmentNo', address: 'SiteAddress', city: 'SiteCityState', zip: 'SiteZip5',
+ use_desc: 'GPLU_DESC|ZC_DESCR', total_value: 'AssdAmt|LandVal+ImprovedVal', lat: 'centroid.y', lng: 'centroid.x' },
+ toRecords: (fs) => fs.map(f => { const a = f.attributes; const apn = s(a.AssessmentNo); if (!apn) return null;
+ const c = f.centroid || {}; const land = num(a.LandVal), imp = num(a.ImprovedVal), assd = num(a.AssdAmt);
+ return { fips: '06059', apn, address: clean(a.SiteAddress), city: clean(a.SiteCityState), zip: s(a.SiteZip5),
+ lat: num(c.y), lng: num(c.x), use: clean(a.GPLU_DESC) || clean(a.ZC_DESCR),
+ totalValue: assd || ((land || 0) + (imp || 0) || null), raw: a } as Rec; }).filter(Boolean) as Rec[],
+ },
};
const execFileP = promisify(execFile);
@@ -403,6 +423,7 @@ async function fetchPage(src: Source, offset: number): Promise<any[]> {
u.searchParams.set('resultRecordCount', String(src.pageSize || PAGE));
u.searchParams.set('returnGeometry', src.geometry ? 'true' : 'false');
if (src.geometry) u.searchParams.set('outSR', '4326');
+ if (src.centroid) { u.searchParams.set('returnCentroid', 'true'); u.searchParams.set('outSR', '4326'); } // lightweight lat/lng via f.centroid, no polygon download
u.searchParams.set('f', 'json');
// some county servers (Spokane MapServer) are slow — retry transient timeouts.
let lastErr: any;
diff --git a/src/ingest/parcels/engine.ts b/src/ingest/parcels/engine.ts
index 27bec0e..41d577f 100644
--- a/src/ingest/parcels/engine.ts
+++ b/src/ingest/parcels/engine.ts
@@ -39,6 +39,7 @@ const ADAPTERS: Record<string, () => Promise<{ run: () => Promise<{ upserted: nu
yakima: async () => { const m = await import('./arcgis_sales.ts'); return { run: m.ingestArcgisSales('yakima') }; },
lane: async () => { const m = await import('./arcgis_sales.ts'); return { run: m.ingestArcgisSales('lane') }; },
jackson: async () => { const m = await import('./arcgis_sales.ts'); return { run: m.ingestArcgisSales('jackson') }; },
+ 'orange-county': async () => { const m = await import('./arcgis_sales.ts'); return { run: m.ingestArcgisSales('orange-county') }; },
};
async function main() {
diff --git a/src/jobs/hourly_loop.ts b/src/jobs/hourly_loop.ts
index 68c92c9..64549f2 100644
--- a/src/jobs/hourly_loop.ts
+++ b/src/jobs/hourly_loop.ts
@@ -75,6 +75,7 @@ const JOBS: Job[] = [
{ name: 'deeds-yakima',script:'src/ingest/parcels/engine.ts', args: ['yakima'], minIntervalHours: 3, runSources: ['yakima'] },
{ name: 'deeds-lane', script: 'src/ingest/parcels/engine.ts', args: ['lane'], minIntervalHours: 4, runSources: ['lane'] },
{ name: 'deeds-jackson',script:'src/ingest/parcels/engine.ts', args: ['jackson'], minIntervalHours: 3, runSources: ['jackson'] },
+ { name: 'parcels-orange',script:'src/ingest/parcels/engine.ts', args: ['orange-county'], minIntervalHours: 2, runSources: ['orange_county'] },
// TK-5: full San Diego County (1.09M) via SANDAG — zoning + assessed value; was in engine but missing from rotation.
{ name: 'parcels-sd-sandag', script: 'src/ingest/parcels/engine.ts', args: ['san-diego-sandag'], minIntervalHours: 2, runSources: ['san_diego_sandag'] },
// TK-5: Santa Clara County CA (San Jose, 493k) — situs address; was in engine but missing from rotation.
← 04c5f48 TK-16: add Jackson County OR (41029) priced-deed feed + curl
·
back to Nationalrealestate
·
TK-16: add Ventura County CA (06111) situs-address coverage 0386ff5 →