Parent: #228
Depends on: #267 (server-side validation unification refactor)
Add shapefile as a perimeter input format on the unified server endpoint introduced in #267 . Server-side validation only — UI work is tracked in #268 .
Scope
Accept shapefile uploads in two forms:
Zipped bundle (.zip containing .shp + sidecars)
Direct multipart upload of .shp plus sidecar files
Validate before attempting import:
All required sidecar files present (.shp, .shx, .dbf, .prj at minimum)
File integrity (parseable headers, consistent record counts)
CRS readable from .prj
Geometry type is polygon (perimeters)
Coordinate values fall in plausible ranges
Use gdal-async to parse the shapefile (already a backend dependency, currently used only for output generation)
Return a normalized GeoJSON FeatureCollection from the endpoint, same contract as the GeoJSON/KML parsers in Refactor: unify server-side perimeter validation (GeoJSON + KML) #267
Surface validation failures with actionable error messages (which file is missing/bad, which check failed) using the same ValidationError shape
Out of scope
Acceptance
Unit tests covering each validation rule (missing sidecar, wrong geometry type, bad CRS, corrupt header, etc.)
Integration test: known-good shapefile (zipped + raw) → endpoint returns normalized GeoJSON; known-bad shapefile → 400 with descriptive fieldErrors
No regressions in existing GeoJSON / KML import paths
Parent: #228
Depends on: #267 (server-side validation unification refactor)
Add shapefile as a perimeter input format on the unified server endpoint introduced in #267. Server-side validation only — UI work is tracked in #268.
Scope
.zipcontaining.shp+ sidecars).shpplus sidecar files.shp,.shx,.dbf,.prjat minimum).prjgdal-asyncto parse the shapefile (already a backend dependency, currently used only for output generation)FeatureCollectionfrom the endpoint, same contract as the GeoJSON/KML parsers in Refactor: unify server-side perimeter validation (GeoJSON + KML) #267ValidationErrorshapeOut of scope
Acceptance
fieldErrors