Validate legacy GRB snapshot evidence
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-16 19:39:14 +02:00
parent a8b18942f5
commit 2d0e02e16c
3 changed files with 73 additions and 6 deletions
@@ -500,7 +500,10 @@ class TemporalAnalysisService:
dataset.source_name != "grb"
or not str(dataset.temporal_series_key or "").startswith("grb:")
or source_metadata.get("authority_level") != "authoritative"
or source_metadata.get("geometry_clipped_to_area") is not True
or not TemporalAnalysisService._has_governed_grb_area_contract(
source_metadata,
provenance,
)
or provenance.get("operator_tool") not in TemporalAnalysisService.GOVERNED_GRB_IDENTITY_OPERATORS
or provenance.get("reference_truncated") is not False
):
@@ -515,6 +518,44 @@ class TemporalAnalysisService:
prefixes = tuple(sorted(f"{str(collection)}:{str(collection)}." for collection in collections))
return "grb_ogc_feature_id", prefixes
@staticmethod
def _has_governed_grb_area_contract(
source_metadata: dict[str, Any],
provenance: dict[str, Any],
) -> bool:
if source_metadata.get("geometry_clipped_to_area") is True:
return True
partition_checksums = provenance.get("partition_checksums")
artifact_checksum = str(provenance.get("artifact_sha256") or "")
has_valid_checksum = len(artifact_checksum) == 64 and all(
character in "0123456789abcdefABCDEF" for character in artifact_checksum
)
has_valid_partition_checksums = (
isinstance(partition_checksums, dict)
and len(partition_checksums) == 28
and all(
len(str(checksum)) == 64
and all(character in "0123456789abcdefABCDEF" for character in str(checksum))
for checksum in partition_checksums.values()
)
)
return (
source_metadata.get("coverage_scope") == "kempen-transport-region"
and source_metadata.get("scope_type") == "transport_region"
and source_metadata.get("member_count") == 28
and source_metadata.get("partition_count") == 28
and source_metadata.get("partition_strategy")
in {
"municipality_bbox_maximum_boundary_intersection",
"municipality_bbox_maximum_same_dimension_intersection",
}
and bool(provenance.get("manifest_path"))
and bool(provenance.get("source_url") or provenance.get("source_urls"))
and has_valid_checksum
and has_valid_partition_checksums
)
@staticmethod
def _rows_match_identity_contract(rows: list[VectorFeature], prefixes: tuple[str, ...]) -> bool:
identities = [str(row.source_feature_id or "").strip() for row in rows]
@@ -142,8 +142,12 @@ def governed_grb_dataset(*, project_id, observed_day: int) -> Dataset:
dataset.temporal_series_key = "grb:buildings:kempen-transport-region"
dataset.source_metadata = {
"authority_level": "authoritative",
"geometry_clipped_to_area": True,
"collection": "GRB/GBG",
"coverage_scope": "kempen-transport-region",
"scope_type": "transport_region",
"member_count": 28,
"partition_count": 28,
"partition_strategy": "municipality_bbox_maximum_boundary_intersection",
"selection_aggregation": {
"method": "intersection_area",
"label": "Bebouwde grondoppervlakte",
@@ -153,7 +157,13 @@ def governed_grb_dataset(*, project_id, observed_day: int) -> Dataset:
dataset.provenance_metadata = {
"operator_tool": "provision_regional_grb_buildings.py",
"reference_truncated": False,
"manifest_path": "/storage/operator/grb/manifest.json",
"source_url": "https://geo.api.vlaanderen.be/GRB/ogc/features/v1/collections/GBG/items",
"artifact_sha256": "a" * 64,
"partition_checksums": {f"{index:05d}": "b" * 64 for index in range(28)},
}
if observed_day > 14:
dataset.source_metadata["geometry_clipped_to_area"] = True
return dataset
@@ -414,6 +424,13 @@ def test_governed_grb_object_history_fails_closed_for_unverified_identity() -> N
assert warnings == ["De geselecteerde objecten bevatten geen volledig verifieerbare stabiele bronidentiteit."]
def test_legacy_grb_identity_requires_complete_partition_evidence() -> None:
dataset = governed_grb_dataset(project_id=uuid4(), observed_day=14)
dataset.provenance_metadata["partition_checksums"] = {"13025": "b" * 64}
assert TemporalAnalysisService._identity_contract(dataset) is None
def test_temporal_frontend_and_official_operator_contracts_exist() -> None:
workspace = (ROOT / "frontend/src/components/map/MapWorkspace.tsx").read_text(encoding="utf-8")
temporal_api = (ROOT / "frontend/src/services/api/temporal.ts").read_text(encoding="utf-8")