From dbdc594f94b517d051eea91ff262e2f01a2a99e1 Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 18 Jul 2026 07:28:50 +0200 Subject: [PATCH] Reject manifest metadata as storage paths --- backend/tests/test_rc10_data_operations.py | 2 ++ scripts/audit_data_operations.py | 25 +++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/backend/tests/test_rc10_data_operations.py b/backend/tests/test_rc10_data_operations.py index ac1affc0..c39dab3b 100644 --- a/backend/tests/test_rc10_data_operations.py +++ b/backend/tests/test_rc10_data_operations.py @@ -187,6 +187,8 @@ def test_manifest_ids_dates_and_labels_are_not_treated_as_paths(tmp_path: Path) "generated_at": "2026-07-18T00:00:00Z", "label": "Belgium", "output_path": "scope.geojson", + "output_checksum_sha256": "a" * 64, + "output_crs": "EPSG:4326", } ), encoding="utf-8", diff --git a/scripts/audit_data_operations.py b/scripts/audit_data_operations.py index 1765f9ad..cc25fdcd 100644 --- a/scripts/audit_data_operations.py +++ b/scripts/audit_data_operations.py @@ -143,18 +143,37 @@ def _iter_strings(value: Any) -> Iterable[str]: yield from _iter_strings(nested) +def _manifest_key_is_path(key: str) -> bool: + exact = { + "path", + "paths", + "file", + "files", + "filename", + "filenames", + "artifact", + "artifacts", + "manifest", + "manifests", + "storage_path", + "source_tile_path", + "mask_path", + "output_path", + } + return key in exact or key.endswith(("_path", "_paths", "_file", "_files", "_filename", "_filenames")) + + def _iter_manifest_path_values(value: Any, parent_key: str = "") -> Iterable[str]: - path_tokens = ("path", "file", "artifact", "manifest", "output") if isinstance(value, dict): for key, nested in value.items(): normalized_key = str(key).strip().lower() - if isinstance(nested, str) and any(token in normalized_key for token in path_tokens): + if isinstance(nested, str) and _manifest_key_is_path(normalized_key): yield nested else: yield from _iter_manifest_path_values(nested, normalized_key) elif isinstance(value, (list, tuple)): for nested in value: - if isinstance(nested, str) and any(token in parent_key for token in path_tokens): + if isinstance(nested, str) and _manifest_key_is_path(parent_key): yield nested else: yield from _iter_manifest_path_values(nested, parent_key)