diff --git a/.env.example b/.env.example index 276e0181..2b1feca7 100644 --- a/.env.example +++ b/.env.example @@ -31,8 +31,8 @@ FLOOD_HAZARD_MAX_RESPONSE_MB=160 THEMATIC_RASTER_ENABLED=true THEMATIC_RASTER_WCS_URL=https://www.mercator.vlaanderen.be/raadpleegdienstenmercatorpubliek/wcs THEMATIC_RASTER_MIN_SIDE_M=100 -THEMATIC_RASTER_MAX_SIDE_M=20000 -THEMATIC_RASTER_MAX_PIXELS=12000000 +THEMATIC_RASTER_MAX_SIDE_M=60000 +THEMATIC_RASTER_MAX_PIXELS=30000000 THEMATIC_RASTER_TIMEOUT_SECONDS=300 THEMATIC_RASTER_MAX_RESPONSE_MB=160 YOLO_ENABLED=false diff --git a/backend/README.md b/backend/README.md index 9d320bcb..7ea8f549 100644 --- a/backend/README.md +++ b/backend/README.md @@ -1316,6 +1316,10 @@ Settings: `THEMATIC_RASTER_ENABLED`, `THEMATIC_RASTER_WCS_URL`, `THEMATIC_RASTER_MIN_SIDE_M`, `THEMATIC_RASTER_MAX_SIDE_M`, `THEMATIC_RASTER_MAX_PIXELS`, `THEMATIC_RASTER_TIMEOUT_SECONDS` and `THEMATIC_RASTER_MAX_RESPONSE_MB`. +The default thematic ceiling is 60 km and 30 million cells so the exact +Kempen work area fits. External WCS transfers remain split into fixed 10 km +tiles, product identifiers remain server-allowlisted and other raster +pipelines retain their smaller independent limits. Provision the official DOV soil polygons for Mol through the existing vector upload path: diff --git a/backend/app/core/config.py b/backend/app/core/config.py index b33e9a87..83af58c3 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -59,8 +59,8 @@ class Settings(BaseSettings): validation_alias="THEMATIC_RASTER_WCS_URL", ) thematic_raster_min_side_m: float = Field(default=100.0, gt=0, validation_alias="THEMATIC_RASTER_MIN_SIDE_M") - thematic_raster_max_side_m: float = Field(default=20_000.0, gt=0, validation_alias="THEMATIC_RASTER_MAX_SIDE_M") - thematic_raster_max_pixels: int = Field(default=12_000_000, ge=1, validation_alias="THEMATIC_RASTER_MAX_PIXELS") + thematic_raster_max_side_m: float = Field(default=60_000.0, gt=0, validation_alias="THEMATIC_RASTER_MAX_SIDE_M") + thematic_raster_max_pixels: int = Field(default=30_000_000, ge=1, validation_alias="THEMATIC_RASTER_MAX_PIXELS") thematic_raster_timeout_seconds: int = Field(default=300, ge=1, validation_alias="THEMATIC_RASTER_TIMEOUT_SECONDS") thematic_raster_max_response_mb: int = Field(default=160, ge=1, validation_alias="THEMATIC_RASTER_MAX_RESPONSE_MB") redis_url: str | None = Field(default=None, validation_alias="REDIS_URL") diff --git a/backend/tests/test_sprint213_thematic_rasters.py b/backend/tests/test_sprint213_thematic_rasters.py index 87aa559b..83b7f400 100644 --- a/backend/tests/test_sprint213_thematic_rasters.py +++ b/backend/tests/test_sprint213_thematic_rasters.py @@ -148,6 +148,29 @@ def test_request_is_bounded_allowlisted_and_uses_native_wcs_resolution() -> None assert exc_info.value.code == "THEMATIC_RASTER_PRODUCT_NOT_SUPPORTED" +def test_complete_kempen_scope_fits_the_tiled_thematic_guardrails() -> None: + settings = Settings(_env_file=None) + request = ThematicRasterAcquireRequest( + bbox={ + "min_x": 4.59723873, + "min_y": 51.01047967, + "max_x": 5.26224853, + "max_y": 51.50511313, + "crs": "EPSG:4326", + }, + product_key="space_occupation_2025", + ) + + prepared = ThematicRasterAcquisitionService._prepared_request(request, settings) + + assert prepared["width"] * prepared["height"] <= 30_000_000 + assert len(ThematicRasterAcquisitionService._tile_bounds(prepared)) > 1 + + with pytest.raises(AppError) as exc_info: + ThematicRasterAcquisitionService._prepared_request(payload(side_m=61_000.0), settings) + assert exc_info.value.code == "THEMATIC_RASTER_SELECTION_TOO_LARGE" + + def test_binary_and_normalized_products_fail_closed_on_invalid_values() -> None: binary = ThematicRasterAcquisitionService._product("space_occupation_2025") score = ThematicRasterAcquisitionService._product("service_level_2022") diff --git a/deploy/unraid/geointel-unraid-template.xml b/deploy/unraid/geointel-unraid-template.xml index 8600f1b5..fd577449 100644 --- a/deploy/unraid/geointel-unraid-template.xml +++ b/deploy/unraid/geointel-unraid-template.xml @@ -45,8 +45,8 @@ 12000000 true https://www.mercator.vlaanderen.be/raadpleegdienstenmercatorpubliek/wcs - 20000 - 12000000 + 60000 + 30000000 true http://host.docker.internal:11434 qwen3.5:9b diff --git a/deploy/unraid/geointel.env.example b/deploy/unraid/geointel.env.example index 226a9192..1e01892d 100644 --- a/deploy/unraid/geointel.env.example +++ b/deploy/unraid/geointel.env.example @@ -49,6 +49,16 @@ FLOOD_HAZARD_MAX_PIXELS=12000000 FLOOD_HAZARD_TIMEOUT_SECONDS=300 FLOOD_HAZARD_MAX_RESPONSE_MB=160 +# Allowlisted Departement Omgeving policy rasters. Regional requests are +# transferred as fixed 10 km WCS tiles before exact Area clipping. +THEMATIC_RASTER_ENABLED=true +THEMATIC_RASTER_WCS_URL=https://www.mercator.vlaanderen.be/raadpleegdienstenmercatorpubliek/wcs +THEMATIC_RASTER_MIN_SIDE_M=100 +THEMATIC_RASTER_MAX_SIDE_M=60000 +THEMATIC_RASTER_MAX_PIXELS=30000000 +THEMATIC_RASTER_TIMEOUT_SECONDS=300 +THEMATIC_RASTER_MAX_RESPONSE_MB=160 + # Optional configured-YOLO runtime. Keep disabled unless a local model is mounted. GEOINTEL_INSTALL_AI=false YOLO_ENABLED=false diff --git a/deploy/unraid/run-dockerman-container.sh b/deploy/unraid/run-dockerman-container.sh index 9e61ec1c..fd241acd 100644 --- a/deploy/unraid/run-dockerman-container.sh +++ b/deploy/unraid/run-dockerman-container.sh @@ -46,8 +46,8 @@ FLOOD_HAZARD_MAX_RESPONSE_MB="${FLOOD_HAZARD_MAX_RESPONSE_MB:-160}" THEMATIC_RASTER_ENABLED="${THEMATIC_RASTER_ENABLED:-true}" THEMATIC_RASTER_WCS_URL="${THEMATIC_RASTER_WCS_URL:-https://www.mercator.vlaanderen.be/raadpleegdienstenmercatorpubliek/wcs}" THEMATIC_RASTER_MIN_SIDE_M="${THEMATIC_RASTER_MIN_SIDE_M:-100}" -THEMATIC_RASTER_MAX_SIDE_M="${THEMATIC_RASTER_MAX_SIDE_M:-20000}" -THEMATIC_RASTER_MAX_PIXELS="${THEMATIC_RASTER_MAX_PIXELS:-12000000}" +THEMATIC_RASTER_MAX_SIDE_M="${THEMATIC_RASTER_MAX_SIDE_M:-60000}" +THEMATIC_RASTER_MAX_PIXELS="${THEMATIC_RASTER_MAX_PIXELS:-30000000}" THEMATIC_RASTER_TIMEOUT_SECONDS="${THEMATIC_RASTER_TIMEOUT_SECONDS:-300}" THEMATIC_RASTER_MAX_RESPONSE_MB="${THEMATIC_RASTER_MAX_RESPONSE_MB:-160}" YOLO_ENABLED="${YOLO_ENABLED:-false}" diff --git a/docker-compose.unraid.yml b/docker-compose.unraid.yml index ac820c14..e307df27 100644 --- a/docker-compose.unraid.yml +++ b/docker-compose.unraid.yml @@ -44,8 +44,8 @@ services: THEMATIC_RASTER_ENABLED: ${THEMATIC_RASTER_ENABLED:-true} THEMATIC_RASTER_WCS_URL: ${THEMATIC_RASTER_WCS_URL:-https://www.mercator.vlaanderen.be/raadpleegdienstenmercatorpubliek/wcs} THEMATIC_RASTER_MIN_SIDE_M: ${THEMATIC_RASTER_MIN_SIDE_M:-100} - THEMATIC_RASTER_MAX_SIDE_M: ${THEMATIC_RASTER_MAX_SIDE_M:-20000} - THEMATIC_RASTER_MAX_PIXELS: ${THEMATIC_RASTER_MAX_PIXELS:-12000000} + THEMATIC_RASTER_MAX_SIDE_M: ${THEMATIC_RASTER_MAX_SIDE_M:-60000} + THEMATIC_RASTER_MAX_PIXELS: ${THEMATIC_RASTER_MAX_PIXELS:-30000000} THEMATIC_RASTER_TIMEOUT_SECONDS: ${THEMATIC_RASTER_TIMEOUT_SECONDS:-300} THEMATIC_RASTER_MAX_RESPONSE_MB: ${THEMATIC_RASTER_MAX_RESPONSE_MB:-160} YOLO_ENABLED: ${YOLO_ENABLED:-false} diff --git a/docker-compose.yml b/docker-compose.yml index f4eb2071..1c253397 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -49,8 +49,8 @@ services: THEMATIC_RASTER_ENABLED: ${THEMATIC_RASTER_ENABLED:-true} THEMATIC_RASTER_WCS_URL: ${THEMATIC_RASTER_WCS_URL:-https://www.mercator.vlaanderen.be/raadpleegdienstenmercatorpubliek/wcs} THEMATIC_RASTER_MIN_SIDE_M: ${THEMATIC_RASTER_MIN_SIDE_M:-100} - THEMATIC_RASTER_MAX_SIDE_M: ${THEMATIC_RASTER_MAX_SIDE_M:-20000} - THEMATIC_RASTER_MAX_PIXELS: ${THEMATIC_RASTER_MAX_PIXELS:-12000000} + THEMATIC_RASTER_MAX_SIDE_M: ${THEMATIC_RASTER_MAX_SIDE_M:-60000} + THEMATIC_RASTER_MAX_PIXELS: ${THEMATIC_RASTER_MAX_PIXELS:-30000000} THEMATIC_RASTER_TIMEOUT_SECONDS: ${THEMATIC_RASTER_TIMEOUT_SECONDS:-300} THEMATIC_RASTER_MAX_RESPONSE_MB: ${THEMATIC_RASTER_MAX_RESPONSE_MB:-160} YOLO_ENABLED: ${YOLO_ENABLED:-false}