diff --git a/Data/Engine/builders/device_enrollment.py b/Data/Engine/builders/device_enrollment.py index 26f64da..92f1217 100644 --- a/Data/Engine/builders/device_enrollment.py +++ b/Data/Engine/builders/device_enrollment.py @@ -7,9 +7,11 @@ from dataclasses import dataclass from typing import Optional from Data.Engine.domain.device_auth import DeviceFingerprint, sanitize_service_context -from Data.Engine.domain.device_enrollment import ProofChallenge +from Data.Engine.domain.device_enrollment import ( + EnrollmentValidationError, + ProofChallenge, +) from Data.Engine.integrations.crypto import keys as crypto_keys -from Data.Engine.services.enrollment.errors import EnrollmentValidationError __all__ = [ "EnrollmentRequestBuilder", diff --git a/Data/Engine/domain/device_enrollment.py b/Data/Engine/domain/device_enrollment.py index 375e463..85b680f 100644 --- a/Data/Engine/domain/device_enrollment.py +++ b/Data/Engine/domain/device_enrollment.py @@ -15,6 +15,7 @@ __all__ = [ "EnrollmentApprovalStatus", "EnrollmentApproval", "EnrollmentRequest", + "EnrollmentValidationError", "ProofChallenge", ] @@ -41,6 +42,24 @@ def _require(value: Optional[str], field: str) -> str: return text +@dataclass(frozen=True, slots=True) +class EnrollmentValidationError(Exception): + """Raised when enrollment input fails validation.""" + + code: str + http_status: int = 400 + retry_after: Optional[float] = None + + def to_response(self) -> dict[str, object]: + payload: dict[str, object] = {"error": self.code} + if self.retry_after is not None: + payload["retry_after"] = self.retry_after + return payload + + def __str__(self) -> str: # pragma: no cover - debug helper + return f"{self.code} (status={self.http_status})" + + @dataclass(frozen=True, slots=True) class EnrollmentCode: """Installer code metadata loaded from the persistence layer.""" diff --git a/Data/Engine/services/__init__.py b/Data/Engine/services/__init__.py index ec0d241..5a2d092 100644 --- a/Data/Engine/services/__init__.py +++ b/Data/Engine/services/__init__.py @@ -15,9 +15,9 @@ from .enrollment import ( EnrollmentService, EnrollmentStatus, EnrollmentTokenBundle, - EnrollmentValidationError, PollingResult, ) +from Data.Engine.domain.device_enrollment import EnrollmentValidationError from .jobs.scheduler_service import SchedulerService from .github import GitHubService, GitHubTokenPayload from .realtime import AgentRealtimeService, AgentRecord diff --git a/Data/Engine/services/enrollment/__init__.py b/Data/Engine/services/enrollment/__init__.py index 129d32c..063cd7b 100644 --- a/Data/Engine/services/enrollment/__init__.py +++ b/Data/Engine/services/enrollment/__init__.py @@ -7,9 +7,9 @@ from .enrollment_service import ( EnrollmentService, EnrollmentStatus, EnrollmentTokenBundle, - EnrollmentValidationError, PollingResult, ) +from Data.Engine.domain.device_enrollment import EnrollmentValidationError __all__ = [ "EnrollmentRequestResult", diff --git a/Data/Engine/services/enrollment/enrollment_service.py b/Data/Engine/services/enrollment/enrollment_service.py index ae960e7..e921eb2 100644 --- a/Data/Engine/services/enrollment/enrollment_service.py +++ b/Data/Engine/services/enrollment/enrollment_service.py @@ -23,10 +23,10 @@ from Data.Engine.domain.device_enrollment import ( EnrollmentApproval, EnrollmentApprovalStatus, EnrollmentCode, + EnrollmentValidationError, ) from Data.Engine.services.auth.device_auth_service import DeviceRecord from Data.Engine.services.auth.token_service import JWTIssuer -from Data.Engine.services.enrollment.errors import EnrollmentValidationError from Data.Engine.services.enrollment.nonce_cache import NonceCache from Data.Engine.services.rate_limit import SlidingWindowRateLimiter diff --git a/Data/Engine/services/enrollment/errors.py b/Data/Engine/services/enrollment/errors.py deleted file mode 100644 index a77df2d..0000000 --- a/Data/Engine/services/enrollment/errors.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Error types shared across enrollment components.""" - -from __future__ import annotations - -from dataclasses import dataclass -from typing import Optional - -__all__ = ["EnrollmentValidationError"] - - -@dataclass(frozen=True, slots=True) -class EnrollmentValidationError(Exception): - """Raised when enrollment input fails validation.""" - - code: str - http_status: int = 400 - retry_after: Optional[float] = None - - def to_response(self) -> dict[str, object]: - payload: dict[str, object] = {"error": self.code} - if self.retry_after is not None: - payload["retry_after"] = self.retry_after - return payload - - def __str__(self) -> str: # pragma: no cover - debug helper - return f"{self.code} (status={self.http_status})"