Keep orthophoto release evidence immutable
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:23:46 +02:00
parent 06d05f03a6
commit 0c2ebc1ffc
5 changed files with 79 additions and 3 deletions
+3
View File
@@ -25,6 +25,9 @@
- Made official `YYYY.NN` orthophoto Datasets take precedence over rolling
acquisition markers in source-catalog comparison. No API, migration,
scheduler, browser fetch or automatic refresh was added.
- 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.
## Sprint 230 Governed orthophoto release preflight (2026-07-17)
@@ -277,6 +277,9 @@ def test_stage_fetches_one_allowlisted_map_and_writes_reviewable_rgb_evidence(tm
assert manifest["normalized_geotiff"]["crs"] == "EPSG:31370"
assert manifest["normalized_geotiff"]["band_count"] == 3
assert Path(manifest["review_preview"]["path"]).read_bytes().startswith(b"\x89PNG")
with pytest.raises(RuntimeError, match="will not be overwritten"):
MANAGER.stage_artifacts(args, release_report, request, opener=opener)
assert len(calls) == 1
def test_getmap_redirect_and_response_limits_fail_closed(tmp_path: Path) -> None:
@@ -397,6 +400,47 @@ def test_official_flight_dates_are_persisted_without_inventing_a_catalog_date()
MANAGER.parse_flight_dates(["spring 2025"])
def test_applied_evidence_is_immutable_on_idempotent_retry(tmp_path: Path) -> None:
args, plan_path, plan, staged = staged_plan(tmp_path)
manifest = MANAGER.validate_staged_artifacts(args, Path(staged["manifest_path"]))
args.approve = True
args.reviewer = "Jens"
review = MANAGER.build_review_evidence(args, plan_path, plan, manifest)
review_path = MANAGER.default_review_path(args, "2025.04")
dataset = {
"id": "dataset-1",
"checksum_sha256": manifest["normalized_geotiff"]["sha256"],
}
final_report = report(status="current", local="2025.04")
final_report["release"]["comparison_status"] = "same"
path, first = MANAGER.applied_evidence(
args,
plan_path,
plan,
review_path,
review,
dataset,
final_report,
reused=False,
)
original_bytes = path.read_bytes()
_, second = MANAGER.applied_evidence(
args,
plan_path,
plan,
review_path,
review,
dataset,
final_report,
reused=True,
)
assert second == first
assert path.read_bytes() == original_bytes
assert second["dataset_status"] == "imported"
def test_release_manager_is_packaged_and_compiled_by_readiness() -> None:
dockerfile = (ROOT / "deploy" / "unraid" / "Dockerfile.all-in-one").read_text(encoding="utf-8")
readiness = (ROOT / "scripts" / "run_readiness_check.sh").read_text(encoding="utf-8")
+2
View File
@@ -9787,6 +9787,8 @@ Implemented:
- Made the latest official `YYYY.NN` Dataset authoritative for source-catalog
comparison even when a newer-imported rolling marker also exists. No API,
migration, release table, Job type or frontend behavior changed.
- Made stage, review and applied evidence write-once. Exact apply retries reuse
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.
+3 -1
View File
@@ -168,7 +168,9 @@ flight-day preflight identities; review binds a named approval; applied
evidence binds both to the immutable Dataset id and checksum. Paths outside
this root, changed files and changed provider/local state fail closed. Only the
normalized GeoTIFF enters ordinary Dataset storage through DatasetService.
Existing `most_recent_at_*` raster metadata is never rewritten.
Existing release evidence and `most_recent_at_*` raster metadata are never
rewritten. An exact apply retry validates and returns the original applied
evidence rather than replacing it.
DHMV II DTM/DSM outputs are also normal raster Dataset files. The provider WCS
returns multipart coverage data; GeoIntel retains response and extracted
+27 -2
View File
@@ -446,6 +446,10 @@ def stage_artifacts(
geotiff_path = directory / f"orthophoto_{edition}_{selection_key(list(args.bbox))}.tif"
preview_path = directory / "review-preview.png"
manifest_path = directory / "staged-manifest.json"
if directory.exists() and any(directory.iterdir()):
raise RuntimeError(
f"Governed orthophoto evidence already exists and will not be overwritten: {directory}"
)
max_bytes = args.max_response_mb * 1024 * 1024
content, content_type, final_url = fetch_map(
request_identity,
@@ -888,6 +892,22 @@ def applied_evidence(
*,
reused: bool,
) -> tuple[Path, dict[str, Any]]:
path = plan_path.with_name("applied-evidence.json")
if path.is_file():
existing = json.loads(path.read_text(encoding="utf-8"))
if existing.get("applied_evidence_sha256") != canonical_sha256(existing, "applied_evidence_sha256"):
raise RuntimeError("Existing orthophoto applied evidence checksum is invalid")
if (
existing.get("project_id") != args.project_id
or existing.get("scope") != args.scope
or existing.get("edition") != plan["edition"]
or existing.get("staged_plan_sha256") != plan["plan_sha256"]
or existing.get("review_sha256") != review["review_sha256"]
or existing.get("dataset_id") != dataset["id"]
or existing.get("dataset_checksum_sha256") != dataset["checksum_sha256"]
):
raise RuntimeError("Existing orthophoto applied evidence does not match this approved Dataset")
return path, existing
payload: dict[str, Any] = {
"schema_version": 1,
"status": "applied",
@@ -908,7 +928,6 @@ def applied_evidence(
"existing_snapshots_retained": True,
}
payload["applied_evidence_sha256"] = canonical_sha256(payload, "applied_evidence_sha256")
path = plan_path.with_name("applied-evidence.json")
write_json(path, payload)
return path, payload
@@ -939,10 +958,12 @@ def main() -> int:
edition = require_edition(args, report)
if args.action == "stage":
authorization = authorize_stage(args, report)
plan_path = governed_path(args, args.plan_path or default_plan_path(args, edition))
if plan_path.exists():
raise RuntimeError(f"Governed orthophoto plan already exists and will not be overwritten: {plan_path}")
request_identity = map_request(report)
staged = stage_artifacts(args, report, request_identity)
plan = build_staged_plan(args, report, authorization, staged)
plan_path = governed_path(args, args.plan_path or default_plan_path(args, edition))
write_json(plan_path, plan)
print(
json.dumps(
@@ -958,6 +979,10 @@ def main() -> int:
if args.action == "review":
review = build_review_evidence(args, plan_path, plan, manifest)
review_path = governed_path(args, args.review_path or default_review_path(args, edition))
if review_path.exists():
raise RuntimeError(
f"Governed orthophoto review already exists and will not be overwritten: {review_path}"
)
write_json(review_path, review)
print(json.dumps({"status": "approved", "review_path": str(review_path), **review}, ensure_ascii=False, indent=2))
return 0