diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index 23fba89c..2aa19774 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -10990,3 +10990,20 @@ Remaining in this pass: - run the complete readiness gate, deploy the immutable revision and repeat both the large overview rectangle and a regional partitioned rectangle in the live browser. + +## 2026-07-21 - Persisted raster scale guard + +Live verification of the first scale-aware release showed that on-demand +provider fan-out was resolved, but already persisted 5 m terrain and flood +rasters could still enter a Belgium-scale analysis. The shared selection guard +now applies the same real pixel budgets to persisted rasters: country-scale +overview analysis keeps PostGIS vector and national statistical sources, while +high-resolution rasters require detail or safely bounded regional extent. + +Validation: + +- frontend typecheck, 29 unit tests and the production build passed; +- the map acquisition, component-boundary and density regression contracts + passed (12 tests); +- live redeployment and a repeated Belgium-scale rectangle follow on the + immutable patch revision. diff --git a/frontend/src/components/map/MapWorkspace.tsx b/frontend/src/components/map/MapWorkspace.tsx index 7dfbda6d..9b2c888a 100644 --- a/frontend/src/components/map/MapWorkspace.tsx +++ b/frontend/src/components/map/MapWorkspace.tsx @@ -34,6 +34,7 @@ import { normalizeBboxFromCorners, operationalScopeProjectLabel, parseBboxInput, + persistedDatasetSupportsSelection, productCoversZones, readablePropertyName, resultCountLabel, @@ -1154,7 +1155,8 @@ export function MapWorkspace({ if (boundedThemes.has(theme.id)) { return true } - if (!themeDatasetMap[theme.id]) { + const dataset = themeDatasetMap[theme.id] + if (!dataset || !persistedDatasetSupportsSelection(dataset, mapSelectionBbox)) { return false } const coverageTheme = COVERAGE_THEME_BY_MAP_THEME[theme.id] @@ -1830,7 +1832,7 @@ export function MapWorkspace({ const availableThemes: Array> = [] for (const theme of DATA_THEMES) { const dataset = themeDatasetMap[theme.id] - if (dataset) { + if (dataset && persistedDatasetSupportsSelection(dataset, bbox)) { availableThemes.push({ themeId: theme.id, dataset, @@ -1865,7 +1867,12 @@ export function MapWorkspace({ setMapAnalysisDurationMs(null) setSelectionBbox(bbox) const tasks: Array> = [loadAllThemeResults(bbox, areaId)] - if (activeThemeAvailable && !regionalPartitionedThemeActive && !onDemandThemeActive) { + const activeDatasetSupportsSelection = !activeThemeDataset + || persistedDatasetSupportsSelection(activeThemeDataset, bbox) + if ( + activeThemeAvailable && !regionalPartitionedThemeActive && !onDemandThemeActive + && activeDatasetSupportsSelection + ) { tasks.push(onRunMapSelectionExtract(bbox, areaId)) } if (analysisMode === 'evolution' && earlierDatasetId && laterDatasetId) { diff --git a/frontend/src/components/map/mapWorkspaceUtils.test.ts b/frontend/src/components/map/mapWorkspaceUtils.test.ts index bd6ecb0f..78ad4cda 100644 --- a/frontend/src/components/map/mapWorkspaceUtils.test.ts +++ b/frontend/src/components/map/mapWorkspaceUtils.test.ts @@ -5,6 +5,7 @@ import { isSelectionBoundedDataset, normalizeBboxFromCorners, parseBboxInput, + persistedDatasetSupportsSelection, productCoversZones, resultMetricLabel, selectedAreaCoverageZones, @@ -138,4 +139,22 @@ describe('map workspace selection guards', () => { } expect(() => splitSelectionBbox(selection)).toThrow('detailpartities') }) + + it('keeps persisted high-resolution rasters out of overview selections', () => { + const overview: VectorSelectionBBox = { + min_x: 2.5, + min_y: 49.5, + max_x: 6.4, + max_y: 51.5, + crs: 'EPSG:4326', + } + expect(persistedDatasetSupportsSelection( + { dataset_type: 'raster', source_name: 'digitaal_vlaanderen_dhmv' }, + overview, + )).toBe(false) + expect(persistedDatasetSupportsSelection( + { dataset_type: 'vector', source_name: 'statbel' }, + overview, + )).toBe(true) + }) }) diff --git a/frontend/src/components/map/mapWorkspaceUtils.ts b/frontend/src/components/map/mapWorkspaceUtils.ts index 9114e1a2..0afcf3e1 100644 --- a/frontend/src/components/map/mapWorkspaceUtils.ts +++ b/frontend/src/components/map/mapWorkspaceUtils.ts @@ -100,6 +100,23 @@ export function selectionAnalysisScale(bbox: VectorSelectionBBox): SelectionAnal return 'overview' } +export function persistedDatasetSupportsSelection( + dataset: { dataset_type: string; source_name?: string | null }, + bbox: VectorSelectionBBox, +): boolean { + if (dataset.dataset_type !== 'raster') return true + const scale = selectionAnalysisScale(bbox) + if (scale === 'overview') return false + const dimensions = selectionDimensions(bbox) + if (dataset.source_name === 'digitaal_vlaanderen_dhmv' || dataset.source_name === 'vmm_flood_hazard') { + return dimensions.areaSquareMetres <= 280_000_000 + } + if (dataset.source_name === 'department_omgeving_thematic_raster') { + return dimensions.areaSquareMetres <= 2_800_000_000 + } + return scale === 'detail' +} + export function splitSelectionBbox( bbox: VectorSelectionBBox, maxTileSideMetres = 18_000,