Refactor enrollment validation error to break circular import

This commit is contained in:
2025-10-22 18:01:32 -06:00
parent 438c7e1ed9
commit 1cde8e57de
6 changed files with 26 additions and 31 deletions

View File

@@ -7,9 +7,11 @@ from dataclasses import dataclass
from typing import Optional from typing import Optional
from Data.Engine.domain.device_auth import DeviceFingerprint, sanitize_service_context 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.integrations.crypto import keys as crypto_keys
from Data.Engine.services.enrollment.errors import EnrollmentValidationError
__all__ = [ __all__ = [
"EnrollmentRequestBuilder", "EnrollmentRequestBuilder",

View File

@@ -15,6 +15,7 @@ __all__ = [
"EnrollmentApprovalStatus", "EnrollmentApprovalStatus",
"EnrollmentApproval", "EnrollmentApproval",
"EnrollmentRequest", "EnrollmentRequest",
"EnrollmentValidationError",
"ProofChallenge", "ProofChallenge",
] ]
@@ -41,6 +42,24 @@ def _require(value: Optional[str], field: str) -> str:
return text 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) @dataclass(frozen=True, slots=True)
class EnrollmentCode: class EnrollmentCode:
"""Installer code metadata loaded from the persistence layer.""" """Installer code metadata loaded from the persistence layer."""

View File

@@ -15,9 +15,9 @@ from .enrollment import (
EnrollmentService, EnrollmentService,
EnrollmentStatus, EnrollmentStatus,
EnrollmentTokenBundle, EnrollmentTokenBundle,
EnrollmentValidationError,
PollingResult, PollingResult,
) )
from Data.Engine.domain.device_enrollment import EnrollmentValidationError
from .jobs.scheduler_service import SchedulerService from .jobs.scheduler_service import SchedulerService
from .github import GitHubService, GitHubTokenPayload from .github import GitHubService, GitHubTokenPayload
from .realtime import AgentRealtimeService, AgentRecord from .realtime import AgentRealtimeService, AgentRecord

View File

@@ -7,9 +7,9 @@ from .enrollment_service import (
EnrollmentService, EnrollmentService,
EnrollmentStatus, EnrollmentStatus,
EnrollmentTokenBundle, EnrollmentTokenBundle,
EnrollmentValidationError,
PollingResult, PollingResult,
) )
from Data.Engine.domain.device_enrollment import EnrollmentValidationError
__all__ = [ __all__ = [
"EnrollmentRequestResult", "EnrollmentRequestResult",

View File

@@ -23,10 +23,10 @@ from Data.Engine.domain.device_enrollment import (
EnrollmentApproval, EnrollmentApproval,
EnrollmentApprovalStatus, EnrollmentApprovalStatus,
EnrollmentCode, EnrollmentCode,
EnrollmentValidationError,
) )
from Data.Engine.services.auth.device_auth_service import DeviceRecord from Data.Engine.services.auth.device_auth_service import DeviceRecord
from Data.Engine.services.auth.token_service import JWTIssuer 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.enrollment.nonce_cache import NonceCache
from Data.Engine.services.rate_limit import SlidingWindowRateLimiter from Data.Engine.services.rate_limit import SlidingWindowRateLimiter

View File

@@ -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})"