- data/sql/100_22c_flat_plans.sql: CREATE TABLE domrf_kn_flat_plans
(ods_id PK, obj_id, plan_image_url, local_path, dimensions, snapshot_date)
+ index on obj_id.
- backend/app/services/scrapers/flat_plans.py (NEW):
* extract_flat_plans(raw_payload) — reserved stub; kn-API audit confirms
plan images are NOT in portal/table payload, only in catalog SSR HTML.
Function probes planImageUrl/layoutImageUrl/planUrl/layoutUrl/imageUrl
for forward-compat if API ever adds the field.
* upsert_flat_plans(db, obj_id, plans, snapshot_date) — UPSERT with
COALESCE guard for local_path/downloaded_at/dimensions.
* download_plan_image_stub() — NotImplementedError placeholder;
real downloader is a future Celery task (#299 / 22d-track).
Audit (obj_id=65136): plan_image absent from kn_object_place_66 payload
(2.3 MB, checked planImage/planUrl/layoutImage/imageUrl — all FALSE).
Source is catalog flat page SSR only. Wiring domrf_kn.py — separate PR.
Issue #297 sub-task 22c.