Prefer persisted sources in map federation
This commit is contained in:
@@ -34,6 +34,10 @@
|
||||
reported as an NGI administrative boundary layer.
|
||||
- Made bounded API coverage spatially honest: a persisted provider selection
|
||||
is operational only for selections contained by its retained source bbox.
|
||||
- Kept reusable persisted datasets ahead of on-demand catalog placeholders in
|
||||
the workbench, so national Statbel 2025 population data is no longer
|
||||
mislabeled as a 2019 thematic raster. Selection-bounded SPW/UrbIS results
|
||||
remain available through the exact on-demand acquisition path.
|
||||
|
||||
## Autonomous Belgium and North Sea RC program (2026-07-17)
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ def test_regional_on_demand_sources_require_a_bounded_drawn_selection() -> None:
|
||||
assert "regionalOnDemandThemeActive" in workspace
|
||||
assert "regionalRasterThemeActive || regionalOnDemandThemeActive" in workspace
|
||||
assert "Teken een begrensde rechthoek voor deze regionale analyse." in workspace
|
||||
assert "Vlaamse kaartbronnen worden begrensd opgehaald, bewaard en hergebruikt" in workspace
|
||||
assert "regionale kaartbronnen worden begrensd opgehaald, bewaard en hergebruikt" in workspace
|
||||
|
||||
|
||||
def test_frontend_does_not_contact_external_map_services_directly() -> None:
|
||||
|
||||
@@ -31,6 +31,19 @@
|
||||
- Bounded provider materialization now also checks its persisted
|
||||
`bbox_epsg4326`; one small PICC/UrbIS/GRB/raster acquisition can no longer
|
||||
claim that an entire region is locally loaded.
|
||||
- The live governed Statbel apply materialized the reviewed 2025 `NEW` edition
|
||||
as Dataset `ee0a46e5-6139-4b0a-93b5-9dabb3b3dfc7`: 20,781 statistical
|
||||
sectors, 565 municipalities, four repaired geometries and a reconciled
|
||||
national total of 11,825,551 inhabitants (11,817,897 spatially located plus
|
||||
7,654 explicitly unlocated).
|
||||
- Live bounded PICC and UrbIS persistence proved the same service path:
|
||||
54 Walloon building geometries retained in Dataset
|
||||
`0c3c0a11-c00e-4c84-87be-8ffa64302dec` and 47 Brussels building geometries
|
||||
in Dataset `de53ccc0-a494-4c4e-bd0d-16d807bfefe7`.
|
||||
- Corrected the map catalog precedence so reusable persisted datasets win over
|
||||
on-demand placeholders. National Statbel 2025 population is now presented
|
||||
as the active source, while selection-bounded PICC/UrbIS acquisitions remain
|
||||
available only through an exact bounded request.
|
||||
- Focused backend and frontend suites passed before full release validation;
|
||||
full local and Tower evidence follows in the final P5 gate.
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ applicable live bounded journey fails.
|
||||
|
||||
## P0 - Existing national layers become usable
|
||||
|
||||
**State: implemented locally; live release evidence pending under P5.**
|
||||
**State: complete; live national and maritime source journeys proven.**
|
||||
|
||||
### Work
|
||||
|
||||
@@ -97,7 +97,7 @@ applicable live bounded journey fails.
|
||||
|
||||
## P1 - National Statbel population
|
||||
|
||||
**State: implementation complete; reviewed live national materialization pending.**
|
||||
**State: complete; reviewed 2025 national edition materialized live.**
|
||||
|
||||
### Work
|
||||
|
||||
@@ -120,9 +120,17 @@ applicable live bounded journey fails.
|
||||
from the same authoritative Statbel edition.
|
||||
- Mol remains within its documented baseline tolerance.
|
||||
|
||||
### Live evidence
|
||||
|
||||
- Reviewed dataset: `ee0a46e5-6139-4b0a-93b5-9dabb3b3dfc7`.
|
||||
- 20,781 persisted sectors and all 565 municipalities are represented.
|
||||
- National reconciliation: 11,825,551 inhabitants, including 7,654 explicitly
|
||||
retained as unlocated rather than silently assigned to geometry.
|
||||
- A bounded Mol selection returns an explicitly labelled area-weighted estimate.
|
||||
|
||||
## P2 - Wallonia bounded topographic baseline
|
||||
|
||||
**State: implemented locally; live Wallonia journey pending under P5.**
|
||||
**State: complete; bounded Wallonia acquisition and analysis proven live.**
|
||||
|
||||
### Governed source
|
||||
|
||||
@@ -158,9 +166,16 @@ Initial allowlisted layers:
|
||||
- Provider failures and record-limit truncation fail closed.
|
||||
- No direct provider-to-`vector_features` write exists.
|
||||
|
||||
### Live evidence
|
||||
|
||||
- Dataset `0c3c0a11-c00e-4c84-87be-8ffa64302dec` retained 54 valid building
|
||||
geometries for the bounded Wallonia smoke selection.
|
||||
- The persisted selection reported 54 buildings and 0.525363 ha without
|
||||
extending operational coverage beyond the retained bbox.
|
||||
|
||||
## P3 - Brussels bounded UrbIS baseline
|
||||
|
||||
**State: implemented locally; live Brussels journey pending under P5.**
|
||||
**State: complete; bounded Brussels acquisition and analysis proven live.**
|
||||
|
||||
### Governed source
|
||||
|
||||
@@ -183,6 +198,13 @@ capabilities probe before implementation is marked operational.
|
||||
parcels.
|
||||
- Catalogue-only or failed capabilities evidence remains `not_configured`.
|
||||
|
||||
### Live evidence
|
||||
|
||||
- Dataset `de53ccc0-a494-4c4e-bd0d-16d807bfefe7` retained 47 UrbIS building
|
||||
geometries for the bounded Brussels smoke selection.
|
||||
- The persisted selection reported 47 buildings and 0.528894 ha without
|
||||
claiming coverage outside the retained bbox.
|
||||
|
||||
## P4 - Maritime and bathymetry hardening
|
||||
|
||||
**State: complete with MDK acquisition visibly blocked by strict-TLS evidence.**
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ maritieme databronnen bruikbaar in de volgende versie.
|
||||
|
||||
- [x] P0: bestaande NGI/RBINS-lagen als kaartthema en selectieanalyse ontsluiten.
|
||||
- [x] P0: readiness baseren op bruikbare analysethema's, niet alleen datasetaantal.
|
||||
- [ ] P1: nationale Statbel-populatieflow veilig operationaliseren.
|
||||
- [x] P1: nationale Statbel-populatieflow veilig operationaliseren.
|
||||
- [x] P2: bounded SPW PICC voor Waalse gebouwen, wegen en hydrographie.
|
||||
- [x] P3: bounded UrbIS voor Brusselse gebouwen en percelen.
|
||||
- [x] P4: maritieme thema's harden en bathymetrie fail-closed onderzoeken.
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
getFeatureBBox,
|
||||
getFeatureCollectionBBox,
|
||||
getFeatureGeometrySummary,
|
||||
isSelectionBoundedDataset,
|
||||
normalizeBboxFromCorners,
|
||||
operationalScopeProjectLabel,
|
||||
parseBboxInput,
|
||||
@@ -411,6 +412,9 @@ function datasetCoversSelectedArea(
|
||||
selectedAreaName: string | null | undefined,
|
||||
regionalScope = false,
|
||||
): boolean {
|
||||
if (isSelectionBoundedDataset(dataset.source_metadata)) {
|
||||
return false
|
||||
}
|
||||
const selectedZones = selectedAreaCoverageZones(selectedAreaName)
|
||||
const configuredZones = dataset.source_metadata?.['coverage_zones']
|
||||
if (selectedZones && Array.isArray(configuredZones) && configuredZones.length > 0) {
|
||||
@@ -929,19 +933,25 @@ export function MapWorkspace({
|
||||
}
|
||||
if (flandersScopeSelected && officialMapProducts.thematic.length > 0) {
|
||||
for (const product of officialMapProducts.thematic) {
|
||||
result[product.theme] = null
|
||||
if (!result[product.theme]) {
|
||||
result[product.theme] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flandersScopeSelected && officialMapProducts.grb.length > 0) {
|
||||
for (const product of officialMapProducts.grb) {
|
||||
result[product.key] = null
|
||||
if (!result[product.key]) {
|
||||
result[product.key] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
if (officialMapProducts.officialVector.length > 0) {
|
||||
for (const product of officialMapProducts.officialVector.filter((item) =>
|
||||
productCoversZones(item.coverage_zones, selectedCoverageZones),
|
||||
)) {
|
||||
result[product.theme] = null
|
||||
if (!result[product.theme]) {
|
||||
result[product.theme] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -1077,7 +1087,9 @@ export function MapWorkspace({
|
||||
}
|
||||
return result
|
||||
}, [onDemandProductsForZones, selectedCoverageZones])
|
||||
const activeOnDemandMapProduct = onDemandProductMap.get(activeTheme.id) ?? null
|
||||
const activeOnDemandMapProduct = themeDatasetMap[activeTheme.id]
|
||||
? null
|
||||
: onDemandProductMap.get(activeTheme.id) ?? null
|
||||
const activeThemeMapStyle = DATA_THEME_MAP_STYLES[activeTheme.id]
|
||||
const analysisOverlayActive = mapContentMode === 'analysis' && analysisLayerAvailable && Boolean(mapFeatureCollection)
|
||||
const selectedOrthophotoProduct = orthophotoProducts.find((item) => item.key === selectedOrthophotoProductKey) ?? null
|
||||
@@ -1665,6 +1677,16 @@ export function MapWorkspace({
|
||||
: []
|
||||
const availableThemes: Array<MapThemeQuery<DataThemeId>> = []
|
||||
for (const theme of DATA_THEMES) {
|
||||
const dataset = themeDatasetMap[theme.id]
|
||||
if (dataset) {
|
||||
availableThemes.push({
|
||||
themeId: theme.id,
|
||||
dataset,
|
||||
partitioned: regionalScopeSelected
|
||||
&& (isPartitionedRaster(dataset) || isPartitionedBathymetry(dataset)),
|
||||
})
|
||||
continue
|
||||
}
|
||||
const onDemandProducts = resolvedProducts.filter((product) => product.theme === theme.id)
|
||||
if (onDemandProducts.length > 0) {
|
||||
for (const onDemandProduct of onDemandProducts) {
|
||||
@@ -1679,15 +1701,6 @@ export function MapWorkspace({
|
||||
}
|
||||
continue
|
||||
}
|
||||
const dataset = themeDatasetMap[theme.id]
|
||||
if (dataset) {
|
||||
availableThemes.push({
|
||||
themeId: theme.id,
|
||||
dataset,
|
||||
partitioned: regionalScopeSelected
|
||||
&& (isPartitionedRaster(dataset) || isPartitionedBathymetry(dataset)),
|
||||
})
|
||||
}
|
||||
}
|
||||
await loadThemeInsights(bbox, availableThemes, areaId)
|
||||
}
|
||||
@@ -1992,7 +2005,7 @@ export function MapWorkspace({
|
||||
</small>
|
||||
</div>
|
||||
{officialMapProductsLoading && selectedProjectId ? (
|
||||
<p className="geo-data-notice">Beschikbare Vlaamse kaartbronnen worden gecontroleerd…</p>
|
||||
<p className="geo-data-notice">Beschikbare officiële regionale kaartbronnen worden gecontroleerd…</p>
|
||||
) : null}
|
||||
{officialMapProductsError && selectedProjectId ? (
|
||||
<p className="error">{officialMapProductsError}</p>
|
||||
@@ -2154,7 +2167,7 @@ export function MapWorkspace({
|
||||
: regionalRasterThemeActive
|
||||
? 'Teken een rechthoek; de juiste gemeentelijke rasters worden automatisch gecombineerd.'
|
||||
: onDemandThemeActive
|
||||
? 'Teken een rechthoek; officiële Vlaamse kaartbronnen worden begrensd opgehaald, bewaard en hergebruikt.'
|
||||
? 'Teken een rechthoek; officiële regionale kaartbronnen worden begrensd opgehaald, bewaard en hergebruikt.'
|
||||
: regionalBathymetryThemeActive
|
||||
? 'Teken een rechthoek of analyseer Vlaanderen; alleen overlappende VHA-partities worden samengevoegd.'
|
||||
: 'Sleep een rechthoek of analyseer het volledige werkgebied.'}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
bboxesEqual,
|
||||
isSelectionBoundedDataset,
|
||||
normalizeBboxFromCorners,
|
||||
parseBboxInput,
|
||||
productCoversZones,
|
||||
@@ -63,4 +64,18 @@ describe('map workspace selection guards', () => {
|
||||
expect(productCoversZones(['wallonia'], ['flanders', 'wallonia'])).toBe(true)
|
||||
expect(productCoversZones(['brussels'], ['wallonia'])).toBe(false)
|
||||
})
|
||||
|
||||
it('distinguishes selection-bounded acquisitions from reusable regional datasets', () => {
|
||||
expect(isSelectionBoundedDataset({
|
||||
geometry_clipped_to_selection: true,
|
||||
bbox_epsg4326: [4.55, 50.58, 4.56, 50.59],
|
||||
})).toBe(true)
|
||||
expect(isSelectionBoundedDataset({
|
||||
geometry_clipped_to_selection: false,
|
||||
bbox_epsg4326: [2.5, 49.5, 6.4, 51.6],
|
||||
})).toBe(false)
|
||||
expect(isSelectionBoundedDataset({
|
||||
geometry_clipped_to_selection: true,
|
||||
})).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -35,6 +35,14 @@ export function productCoversZones(productZones: string[], selectedZones: string
|
||||
return selectedZones === null || selectedZones.some((zone) => productZones.includes(zone))
|
||||
}
|
||||
|
||||
export function isSelectionBoundedDataset(
|
||||
sourceMetadata: Record<string, unknown> | null | undefined,
|
||||
): boolean {
|
||||
return sourceMetadata?.['geometry_clipped_to_selection'] === true
|
||||
&& Array.isArray(sourceMetadata?.['bbox_epsg4326'])
|
||||
&& sourceMetadata['bbox_epsg4326'].length === 4
|
||||
}
|
||||
|
||||
export function operationalScopeProjectLabel(project: ProjectRead): string {
|
||||
if (project.name === MOL_PROJECT_NAME) {
|
||||
return 'Mol'
|
||||
|
||||
Reference in New Issue
Block a user