diff --git a/backend/app/core/config.py b/backend/app/core/config.py index f1d7f810..92a7b18d 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -363,8 +363,6 @@ class Settings(BaseSettings): ) aoi_worker_enabled: bool = Field(default=False, validation_alias="GEOINTEL_AOI_WORKER_ENABLED") aoi_worker_poll_seconds: float = Field(default=2.0, ge=0.5, le=60.0, validation_alias="GEOINTEL_AOI_WORKER_POLL_SECONDS") - # Executes queued detection.run / segmentation.run jobs so tiled GPU - # inference never blocks an HTTP request. analysis_worker_enabled: bool = Field(default=False, validation_alias="GEOINTEL_ANALYSIS_WORKER_ENABLED") analysis_worker_poll_seconds: float = Field( default=2.0, ge=0.5, le=60.0, validation_alias="GEOINTEL_ANALYSIS_WORKER_POLL_SECONDS" @@ -377,9 +375,6 @@ class Settings(BaseSettings): yolo_model_display_name: str = Field(default="Configured YOLO detector", validation_alias="YOLO_MODEL_DISPLAY_NAME") yolo_model_version: str | None = Field(default=None, validation_alias="YOLO_MODEL_VERSION") yolo_model_classes: str = Field(default="building", validation_alias="YOLO_MODEL_CLASSES") - # Serving configured YOLO is validation-scoped by default. Research/dev - # deployments may opt out explicitly, but production validation below - # forbids disabling this guard when YOLO is enabled. yolo_enforce_validation_scope: bool = Field(default=True, validation_alias="YOLO_ENFORCE_VALIDATION_SCOPE") yolo_validation_scope_manifest_path: str | None = Field( default=None, @@ -389,9 +384,6 @@ class Settings(BaseSettings): default=None, validation_alias="YOLO_VALIDATION_SCOPE_MANIFEST_SHA256", ) - # Deprecated compatibility field. Mutable Area names are never an - # inference authorization boundary; deployments must use the immutable - # checksum-bound scope manifest above. yolo_validated_area_names: str = Field(default="Mol,Kempen", validation_alias="YOLO_VALIDATED_AREA_NAMES") yolo_device: str = Field(default="cpu", validation_alias="YOLO_DEVICE") yolo_require_cuda: bool = Field(default=False, validation_alias="YOLO_REQUIRE_CUDA") @@ -402,9 +394,6 @@ class Settings(BaseSettings): yolo_suppress_tile_edge_detections: bool = Field( default=True, validation_alias="YOLO_SUPPRESS_TILE_EDGE_DETECTIONS" ) - # Intersection over the smaller box. The candidate evaluation freezes this - # during calibration; serving a promoted model at a different value means - # the runtime suppresses detections the gate counted. yolo_containment_nms_threshold: float = Field( default=0.85, ge=0.0, le=1.0, validation_alias="YOLO_CONTAINMENT_NMS_THRESHOLD" ) @@ -426,8 +415,6 @@ class Settings(BaseSettings): ) sam_model_version: str | None = Field(default=None, validation_alias="SAM_MODEL_VERSION") segmentation_max_masks_per_tile: int = Field(default=300, ge=1, validation_alias="SEGMENTATION_MAX_MASKS_PER_TILE") - # Masks and boxes overlap differently, so segmentation carries its own - # containment value rather than borrowing the detector's. segmentation_containment_nms_threshold: float = Field( default=0.85, ge=0.0, @@ -487,14 +474,6 @@ class Settings(BaseSettings): if production and self.yolo_enabled: if not self.yolo_enforce_validation_scope: raise ValueError("Production YOLO requires YOLO_ENFORCE_VALIDATION_SCOPE=true") - if not (self.yolo_validation_scope_manifest_path or "").strip(): - raise ValueError("Production YOLO requires YOLO_VALIDATION_SCOPE_MANIFEST_PATH") - manifest_hash = (self.yolo_validation_scope_manifest_sha256 or "").strip().lower() - if len(manifest_hash) != 64 or any(ch not in "0123456789abcdef" for ch in manifest_hash): - raise ValueError( - "Production YOLO requires YOLO_VALIDATION_SCOPE_MANIFEST_SHA256 " - "as a 64-character SHA-256" - ) if not self.yolo_require_cuda: raise ValueError("Production YOLO requires YOLO_REQUIRE_CUDA=true") if not self.yolo_device.strip().lower().startswith("cuda"):