feat(provenance): govern source snapshots and data inputs

This commit is contained in:
Jens
2026-08-01 23:46:17 +02:00
parent cebeb5f3b4
commit 5b3c17b494
96 changed files with 20156 additions and 351 deletions
@@ -12,7 +12,7 @@ from shapely.geometry import Polygon, box
from app.core.errors import AppError
from app.main import app
from app.db.session import get_db
from app.models import AnalysisRun, Dataset, Detection, Metric, QualityCheck, VectorFeature
from app.models import AnalysisRun, Dataset, Detection, Metric, QualityCheck, SourceRegistry, SourceSnapshot, VectorFeature
from app.services.detection_service import DetectionService
@@ -96,11 +96,52 @@ def _source_dataset(project_id, dataset_id):
project_id=project_id,
name="source.tif",
dataset_type="raster",
source="manual",
source_name="manual",
source="test",
source_name="test",
)
def _authoritative_reference(dataset: Dataset) -> Dataset:
"""Model the reference as a fully governed GRB fixture, never test data."""
source_id = uuid4()
snapshot_id = uuid4()
checksum = "a" * 64
source = SourceRegistry(
id=source_id,
source_key="grb",
display_name="GRB QA fixture",
classification="authoritative",
authority_name="Digitaal Vlaanderen",
authority_scope_json={"zone": "Flanders"},
usage_policy_json={"ground_truth_allowed": True, "validation_authority": {"building_validation": "primary"}},
)
snapshot = SourceSnapshot(
id=snapshot_id,
source_registry_id=source_id,
snapshot_key=f"detection-qa-{dataset.id}",
checksum_sha256=checksum,
ingest_status="ingested",
freshness_status="current",
)
dataset.source = "grb"
dataset.source_name = "grb"
dataset.dataset_role = "reference"
dataset.status = "ready"
dataset.checksum_sha256 = checksum
dataset.source_registry_id = source_id
dataset.source_snapshot_id = snapshot_id
dataset.data_contract_key = "geointel.vector.geojson"
dataset.data_contract_version = "1.0.0"
dataset.validation_status = "passed"
dataset.provenance_status = "complete"
dataset.lineage_status = "complete"
dataset.quarantine_status = "not_quarantined"
dataset.source_registry = source
dataset.source_snapshot = snapshot
return dataset
def test_detection_geojson_feature_collection_shape() -> None:
project_id = uuid4()
dataset_id = uuid4()
@@ -201,14 +242,14 @@ def test_detection_qa_persists_quality_check_and_metrics() -> None:
reference_dataset_id = uuid4()
analysis_run_id = uuid4()
detection = _detection(project_id, dataset_id, analysis_run_id, geom=box(0, 0, 1, 1))
reference_dataset = Dataset(
reference_dataset = _authoritative_reference(Dataset(
id=reference_dataset_id,
project_id=project_id,
name="reference.geojson",
dataset_type="vector",
source="manual",
source="test",
dataset_role="reference",
)
))
reference_feature = VectorFeature(
id=uuid4(),
dataset_id=reference_dataset_id,
@@ -262,7 +303,7 @@ def test_detection_qa_rejects_non_overlapping_historical_reference_editions() ->
source_dataset.source_metadata = {"product_key": "2020", "supports_detection": False}
source_dataset.valid_from = datetime(2020, 1, 1, tzinfo=UTC)
source_dataset.valid_to = datetime(2020, 12, 31, 23, 59, 59, tzinfo=UTC)
reference_dataset = Dataset(
reference_dataset = _authoritative_reference(Dataset(
id=reference_dataset_id,
project_id=project_id,
name="current-grb.geojson",
@@ -272,7 +313,7 @@ def test_detection_qa_rejects_non_overlapping_historical_reference_editions() ->
dataset_role="reference",
valid_from=datetime(2026, 7, 1, tzinfo=UTC),
valid_to=datetime(2026, 7, 31, 23, 59, 59, tzinfo=UTC),
)
))
db = FakeSession(
objects={
(AnalysisRun, analysis_run_id): AnalysisRun(
@@ -305,14 +346,14 @@ def test_detection_qa_no_match_case_persists_zero_scores() -> None:
reference_dataset_id = uuid4()
analysis_run_id = uuid4()
detection = _detection(project_id, dataset_id, analysis_run_id, geom=box(0, 0, 1, 1))
reference_dataset = Dataset(
reference_dataset = _authoritative_reference(Dataset(
id=reference_dataset_id,
project_id=project_id,
name="reference.geojson",
dataset_type="vector",
source="manual",
source="test",
dataset_role="reference",
)
))
reference_feature = VectorFeature(
id=uuid4(),
dataset_id=reference_dataset_id,
@@ -349,14 +390,14 @@ def test_configured_yolo_qa_requires_persisted_tile_manifest_provenance() -> Non
reference_dataset_id = uuid4()
analysis_run_id = uuid4()
detection = _detection(project_id, dataset_id, analysis_run_id)
reference_dataset = Dataset(
reference_dataset = _authoritative_reference(Dataset(
id=reference_dataset_id,
project_id=project_id,
name="reference.geojson",
dataset_type="vector",
source="manual",
source="test",
dataset_role="reference",
)
))
reference_feature = VectorFeature(
id=uuid4(),
dataset_id=reference_dataset_id,
@@ -421,14 +462,14 @@ def test_detection_qa_excludes_references_outside_persisted_tile_coverage(tmp_pa
analysis_run_id = uuid4()
manifest_path = _coverage_manifest(tmp_path, dataset_id, bounds=(0.0, 0.0, 1.0, 1.0))
detection = _detection(project_id, dataset_id, analysis_run_id, geom=box(0.1, 0.1, 0.9, 0.9))
reference_dataset = Dataset(
reference_dataset = _authoritative_reference(Dataset(
id=reference_dataset_id,
project_id=project_id,
name="reference.geojson",
dataset_type="vector",
source="manual",
source="test",
dataset_role="reference",
)
))
inside_reference = VectorFeature(
id=uuid4(),
dataset_id=reference_dataset_id,
@@ -489,14 +530,14 @@ def test_detection_qa_reports_box_to_footprint_diagnostic_without_changing_stric
l_shaped_footprint = Polygon(
[(0.0, 0.0), (2.0, 0.0), (2.0, 0.4), (0.4, 0.4), (0.4, 2.0), (0.0, 2.0), (0.0, 0.0)]
)
reference_dataset = Dataset(
reference_dataset = _authoritative_reference(Dataset(
id=reference_dataset_id,
project_id=project_id,
name="reference.geojson",
dataset_type="vector",
source="manual",
source="test",
dataset_role="reference",
)
))
reference_feature = VectorFeature(
id=uuid4(),
dataset_id=reference_dataset_id,