diff --git a/backend/tests/test_secure_runtime_defaults.py b/backend/tests/test_secure_runtime_defaults.py new file mode 100644 index 00000000..ed7b1c67 --- /dev/null +++ b/backend/tests/test_secure_runtime_defaults.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +import pytest +from pydantic import ValidationError + +from app.core.config import Settings + + +def _settings(**overrides: object) -> Settings: + return Settings(_env_file=None, **overrides) + + +def test_guest_access_is_opt_in_by_default() -> None: + settings = _settings() + assert settings.guest_access_enabled is False + + +def test_yolo_validation_scope_is_enforced_by_default() -> None: + settings = _settings() + assert settings.yolo_enforce_validation_scope is True + + +def test_production_yolo_rejects_disabled_validation_scope() -> None: + with pytest.raises(ValidationError, match="YOLO_ENFORCE_VALIDATION_SCOPE"): + _settings( + app_env="production", + yolo_enabled=True, + yolo_enforce_validation_scope=False, + ) + + +def test_production_yolo_requires_validation_scope_manifest() -> None: + with pytest.raises(ValidationError, match="YOLO_VALIDATION_SCOPE_MANIFEST_PATH"): + _settings( + app_env="production", + yolo_enabled=True, + yolo_require_cuda=True, + yolo_device="cuda:0", + ) + + +def test_production_yolo_requires_validation_scope_hash() -> None: + with pytest.raises(ValidationError, match="YOLO_VALIDATION_SCOPE_MANIFEST_SHA256"): + _settings( + app_env="production", + yolo_enabled=True, + yolo_validation_scope_manifest_path="/app/storage/model-scope.json", + yolo_require_cuda=True, + yolo_device="cuda:0", + ) + + +def test_production_yolo_requires_cuda() -> None: + with pytest.raises(ValidationError, match="YOLO_REQUIRE_CUDA"): + _settings( + app_env="production", + yolo_enabled=True, + yolo_validation_scope_manifest_path="/app/storage/model-scope.json", + yolo_validation_scope_manifest_sha256="a" * 64, + yolo_require_cuda=False, + yolo_device="cuda:0", + ) + + +def test_production_yolo_requires_cuda_device() -> None: + with pytest.raises(ValidationError, match="YOLO_DEVICE"): + _settings( + app_env="production", + yolo_enabled=True, + yolo_validation_scope_manifest_path="/app/storage/model-scope.json", + yolo_validation_scope_manifest_sha256="a" * 64, + yolo_require_cuda=True, + yolo_device="cpu", + ) + + +def test_production_yolo_accepts_checksum_bound_cuda_scope() -> None: + settings = _settings( + app_env="production", + yolo_enabled=True, + yolo_validation_scope_manifest_path="/app/storage/model-scope.json", + yolo_validation_scope_manifest_sha256="a" * 64, + yolo_require_cuda=True, + yolo_device="cuda:0", + ) + assert settings.yolo_enforce_validation_scope is True