feat(provenance): govern source snapshots and data inputs
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user