Add a new endpoint POST /api/v1/ingest/with-images that accepts:
metadata — JSON string with source_slug, external_id, payloadimages — 0–N binary image files via multipart/form-dataThe parser downloads images from its own source and uploads them directly to our service. We never fight foreign CDNs again.
router_properties.py)metadata: str = Form(...) — validated as JSON, must contain source_slug + payload with title|descriptionimages: list[UploadFile] = File(default=[]) — streamed to disk, not held in memoryraw_parsing_data (status = pending)UploadFile to /var/lib/vmk/images/temp/{raw_id}/{idx}{ext}_uploaded_image_paths into raw.payloadawait pipeline.process(raw.id) — synchronous, because images are already local and we want immediate resultIngestResponseproperty_pipeline.py)_stage_process_images checks raw.payload.get("_uploaded_image_paths")
_stage_process_uploaded_images(property_id, paths)_stage_process_remote_images(property_id, urls) (existing behaviour)_process_uploaded_one:
temp/{raw_id}/ to permanent /{property_id}/{hash}.{ext}PropertyImage row with downloaded statusOllamaClient.image_to_base64image_downloader.py)ImageDownloader.process_local_file(property_id, temp_path, order):
download() return type (PropertyImageDownloadResult)UploadFile already spills large files to disk — we just copy.curl -F examplerequests multipart example/ingest (URLs) vs /ingest/with-images (binary)src/vmk_data_collector/api/v1/router_properties.pysrc/vmk_data_collector/services/property_pipeline.pysrc/vmk_data_collector/services/image_downloader.pyREADME.mdproperty_id, snapshot_id, validation result right away.