fix(platform): govern geospatial analysis and raster handoffs
This commit is contained in:
@@ -11,10 +11,20 @@ from fastapi.testclient import TestClient
|
||||
from app.core.config import Settings
|
||||
from app.core.errors import AppError
|
||||
from app.main import app
|
||||
from app.models import AnalysisRun, Dataset, Detection, Job, Project, SourceRegistry, SourceSnapshot
|
||||
from app.models import (
|
||||
AnalysisRun,
|
||||
Dataset,
|
||||
DatasetVersion,
|
||||
Detection,
|
||||
Job,
|
||||
Project,
|
||||
SourceRegistry,
|
||||
SourceSnapshot,
|
||||
)
|
||||
from app.services.detection_service import DetectionService
|
||||
from app.services.model_asset_catalog_service import ModelAssetCatalogService
|
||||
from app.services.runtime_model_provenance_service import RuntimeModelProvenanceService
|
||||
from app.services.tile_manifest_service import TileManifestService
|
||||
|
||||
|
||||
class FakeSession:
|
||||
@@ -98,6 +108,8 @@ def _project_and_raster_dataset():
|
||||
source_name="test-derived-raster",
|
||||
storage_path="storage/uploads/source.tif",
|
||||
checksum_sha256=checksum,
|
||||
crs="EPSG:4326",
|
||||
bounds_json={"min_x": 4.0, "min_y": 51.0, "max_x": 5.0, "max_y": 52.0},
|
||||
source_registry_id=source_registry_id,
|
||||
source_snapshot_id=source_snapshot_id,
|
||||
data_contract_key="geointel.raster.geotiff",
|
||||
@@ -110,17 +122,22 @@ def _project_and_raster_dataset():
|
||||
)
|
||||
dataset.source_registry = source_registry
|
||||
dataset.source_snapshot = source_snapshot
|
||||
dataset.versions.append(
|
||||
DatasetVersion(id=uuid4(), dataset_id=dataset_id, version=1, checksum_sha256=checksum)
|
||||
)
|
||||
db = FakeSession(objects={(Project, project_id): project, (Dataset, dataset_id): dataset})
|
||||
return db, project_id, dataset_id
|
||||
|
||||
|
||||
def _manifest(tmp_path: Path) -> Path:
|
||||
def _manifest(tmp_path: Path, db: FakeSession, dataset: Dataset) -> Path:
|
||||
tile_path = tmp_path / "tile_0000.tif"
|
||||
tile_path.write_bytes(b"tile")
|
||||
binding = TileManifestService.dataset_binding(db, dataset)
|
||||
manifest_path = tmp_path / "manifest.json"
|
||||
manifest_path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
**binding,
|
||||
"tile_set_id": "tiles-fixture",
|
||||
"count": 1,
|
||||
"crs": "EPSG:4326",
|
||||
@@ -133,6 +150,7 @@ def _manifest(tmp_path: Path) -> Path:
|
||||
"transform": [4.0, 0.01, 0.0, 52.0, 0.0, -0.01],
|
||||
"crs": "EPSG:4326",
|
||||
"index": 0,
|
||||
**TileManifestService.tile_integrity(tile_path),
|
||||
}
|
||||
],
|
||||
}
|
||||
@@ -226,7 +244,11 @@ def test_model_asset_catalog_lists_supported_local_model_files(tmp_path: Path) -
|
||||
assert asset.size_bytes == len(b"local model")
|
||||
assert len(asset.sha256) == 64
|
||||
assert asset.active is True
|
||||
assert asset.status == "approved"
|
||||
assert asset.runtime_available is True
|
||||
assert asset.runtime_status == "active"
|
||||
assert asset.governed_validation_status == "not_verified_by_catalog"
|
||||
assert asset.promotion_status == "not_verified_by_catalog"
|
||||
assert asset.status == "runtime_active"
|
||||
assert asset.will_download_models is False
|
||||
|
||||
|
||||
@@ -257,7 +279,10 @@ def test_model_asset_catalog_only_exposes_explicit_active_asset_in_runtime(tmp_p
|
||||
assert response.total == 1
|
||||
assert response.items[0].filename == active_file.name
|
||||
assert response.items[0].active is True
|
||||
assert response.items[0].status == "approved"
|
||||
assert response.items[0].runtime_status == "active"
|
||||
assert response.items[0].governed_validation_status == "not_verified_by_catalog"
|
||||
assert response.items[0].promotion_status == "not_verified_by_catalog"
|
||||
assert response.items[0].status == "runtime_active"
|
||||
|
||||
|
||||
def test_model_asset_catalog_rejects_unknown_asset(tmp_path: Path) -> None:
|
||||
@@ -284,6 +309,9 @@ def test_model_assets_api_returns_canonical_envelope(monkeypatch, tmp_path: Path
|
||||
assert payload["data"]["total"] == 1
|
||||
assert payload["data"]["items"][0]["model_asset_id"] == "building-detector-pt"
|
||||
assert payload["data"]["items"][0]["active"] is True
|
||||
assert payload["data"]["items"][0]["runtime_status"] == "active"
|
||||
assert payload["data"]["items"][0]["governed_validation_status"] == "not_verified_by_catalog"
|
||||
assert payload["data"]["items"][0]["promotion_status"] == "not_verified_by_catalog"
|
||||
assert payload["data"]["items"][0]["will_download_models"] is False
|
||||
|
||||
|
||||
@@ -309,7 +337,7 @@ def test_detection_run_persists_selected_model_asset_parameters(tmp_path, monkey
|
||||
model_id="yolo-configured",
|
||||
model_asset_id="building-detector-pt",
|
||||
confidence_threshold=0.5,
|
||||
tile_manifest_path=str(_manifest(tmp_path)),
|
||||
tile_manifest_path=str(_manifest(tmp_path, db, db.get(Dataset, dataset_id))),
|
||||
settings=settings,
|
||||
yolo_adapter_class=MockYoloAdapter,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user