Prefer governed orthophoto editions in source status
GeoIntel CI / docs-smoke (push) Canceled after 0s
GeoIntel CI / contract-smoke (push) Canceled after 0s

This commit is contained in:
Codex
2026-07-17 02:33:15 +02:00
parent 0c2ebc1ffc
commit 0befca02f8
4 changed files with 84 additions and 10 deletions
+3
View File
@@ -28,6 +28,9 @@
- Made staged, reviewed and applied release evidence write-once. An idempotent
apply validates and reuses the existing evidence instead of changing its
timestamp or authorization history.
- Made the read-only source-freshness audit prefer the governed official
`YYYY.NN` orthophoto edition over retained legacy `most_recent_at_*` labels,
while preserving the existing rolling-source review interval.
## Sprint 230 Governed orthophoto release preflight (2026-07-17)
@@ -4,6 +4,7 @@ from collections import defaultdict
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from pathlib import Path
import re
from typing import Iterable
from uuid import UUID
@@ -51,6 +52,7 @@ SOURCE_POLICIES: dict[str, SourcePolicy] = {
}
DEFAULT_POLICY = SourcePolicy("Niet-geclassificeerde bron", "edition")
_ORTHOPHOTO_EDITION = re.compile(r"^20\d{2}\.\d{2}$")
def _as_utc(value: datetime | None) -> datetime | None:
@@ -81,10 +83,16 @@ def _latest_dataset(datasets: list[Dataset]) -> Dataset:
)
def _latest_source_version(policy: SourcePolicy, datasets: list[Dataset]) -> str | None:
def _latest_source_version(source_name: str, policy: SourcePolicy, datasets: list[Dataset]) -> str | None:
versioned = [item for item in datasets if item.source_version]
if not versioned:
return None
if source_name == "digitaal_vlaanderen_orthophoto":
official_editions = [
item for item in versioned if _ORTHOPHOTO_EDITION.fullmatch((item.source_version or "").strip())
]
if official_editions:
return _latest_dataset(official_editions).source_version
if policy.refresh_policy == "rolling_snapshot":
named_current = [
item
@@ -258,7 +266,7 @@ class SourceFreshnessService:
version_count=sum(len(versions_by_dataset.get(item.id, [])) for item in source_datasets),
latest_imported_at=_latest_datetime(item.imported_at for item in source_datasets),
latest_observed_at=_latest_datetime(item.observed_at for item in source_datasets),
latest_source_version=_latest_source_version(policy, source_datasets),
latest_source_version=_latest_source_version(source_name, policy, source_datasets),
refresh_policy=policy.refresh_policy,
review_interval_days=policy.review_interval_days,
next_review_at=next_review_at,
@@ -157,6 +157,33 @@ def test_rolling_orthophoto_prefers_explicit_current_snapshot_over_historical_ob
assert report.items[0].latest_source_version == "most_recent_at_2026-07-14"
def test_orthophoto_freshness_prefers_governed_official_edition_over_rolling_marker() -> None:
legacy = _dataset(
"digitaal_vlaanderen_orthophoto",
imported_at=NOW - timedelta(days=2),
observed_at=datetime(2026, 7, 15, tzinfo=timezone.utc),
source_version="most_recent_at_2026-07-15",
)
official = _dataset(
"digitaal_vlaanderen_orthophoto",
imported_at=NOW - timedelta(days=1),
observed_at=datetime(2025, 4, 5, tzinfo=timezone.utc),
source_version="2025.04",
)
report = SourceFreshnessService.build_report(
legacy.project_id,
[legacy, official],
[_version(legacy), _version(official)],
now=NOW,
)
item = report.items[0]
assert item.latest_source_version == "2025.04"
assert item.refresh_policy == "rolling_snapshot"
assert item.review_interval_days == 180
def test_spatial_partitions_do_not_become_a_false_historical_series() -> None:
first = _dataset(
"dov_soil_map",
+44 -8
View File
@@ -9791,13 +9791,49 @@ Implemented:
the original checksum-bound evidence and never rewrite approval history.
Validation so far:
- 38 focused Sprint 222/230/231 tests pass with deprecations treated as errors.
Coverage includes official-edition ordering, first-baseline authorization,
GetMap allowlisting/limits, RGB/CRS normalization, preview generation,
tampering, preflight drift, named review, loopback-only apply and complete
upload provenance.
- 48 focused Sprint 221/222/230/231 tests pass. The release-management suite
contains 11 direct plan/stage/review/apply tests. Coverage includes
official-edition ordering in both catalog and source-freshness views,
first-baseline authorization, GetMap allowlisting/limits, RGB/CRS
normalization, preview generation, tampering, preflight drift, named review,
loopback-only apply and complete upload provenance.
- Complete local readiness passed with 878 backend tests, 110 documented
routes, one Alembic head `202607160001`, frontend typecheck and production
build. Target compile and Ruff checks also passed.
Live validation:
- Commits `06d05f0` and `0c2ebc1` were pushed, deployed through the repository
to Tower and validated against PostGIS 3.6. The all-in-one container became
healthy on port 1202 and passed migrations, schema/collation, API proxy and
browser shell checks.
- The packaged operator staged official edition `2025.04` for bbox
`5.110,51.180,5.117,51.185`: one 921,848-byte official WMS response became a
496x562, three-band EPSG:31370 GeoTIFF at an approximately one-metre grid.
All 20 deterministic flight-day samples reported `2025-04-05`.
- The generated preview was visually inspected as a complete RGB orthophoto
with expected Mol roads, buildings and sports context. Named review bound
plan SHA-256 `c6cefd19dc60d7469b4885d9d1f5eff4e52a88808bbe3ac21879c5650e558662`
and review SHA-256
`9f0a3a65eb184fea7f91daa5018c0980ed03b792bd465a98c65f2add2413d90b`.
- Checksum-confirmed apply created exactly one immutable raster Dataset
`3cf14603-03da-42f5-b152-4bbecad7d006`; project total moved from 636 to 637.
Dataset, version and staged GeoTIFF share SHA-256
`f87701de6680f8ad25407996ddfd08056bf0533c05572ae489e9d478a72e7e46`.
The canonical API returns the complete request, catalog, flight-date,
reviewer and artifact provenance.
- An idempotent retry retained 637 Datasets and the same Dataset ID. A live
audit exposed that the applied-evidence timestamp could still be rewritten;
write-once validation was added, tested, redeployed and the evidence file
remained byte-identical on the next retry at SHA-256
`f4ae7b2315aed9370c8ca04dcb57eabf0c0e49c40cf63a862bb4e69bacd4b16d`.
- Browser validation at 1920x911 showed a correctly rendered MapLibre canvas,
coherent regional layer workflow, no horizontal overflow and no console
warnings or errors. A final live API audit found the generic source status
still selected a retained rolling label; source-freshness now prefers the
official edition without changing the 180-day review policy.
Next:
- Run complete readiness, deploy the packaged operator to Tower, inspect the
live bounded Mol review preview and only then apply the first official
`2025.04` immutable baseline with explicit review evidence.
- Surface the existing release evidence read-only in the operator Status
workspace so official/local edition, review identity, Dataset ID and hash
integrity can be inspected without shell access. Keep all refresh actions
operator-only and outside the browser.