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
+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