from datetime import UTC, datetime from enum import StrEnum from uuid import UUID from pydantic import BaseModel, ConfigDict, Field, field_validator from pydantic.networks import AnyHttpUrl class State(StrEnum): unknown = "unknown" up = "up" down = "down" error = "error" class MonitorInput(BaseModel): name: str = Field(min_length=1, max_length=100) url: AnyHttpUrl timeout_seconds: float | None = Field(default=None, gt=0, le=30) @field_validator("url") @classmethod def reject_credentials(cls, value: AnyHttpUrl) -> AnyHttpUrl: if value.username or value.password: raise ValueError("URL credentials are not allowed") return value class CheckSnapshot(BaseModel): state: State = State.unknown checked_at: datetime | None = None latency_ms: float | None = None http_status: int | None = None error: str | None = None class Monitor(BaseModel): model_config = ConfigDict(frozen=True) id: UUID name: str url: AnyHttpUrl timeout_seconds: float | None created_at: datetime updated_at: datetime revision: int status: CheckSnapshot class CheckResult(CheckSnapshot): monitor_id: UUID def now() -> datetime: return datetime.now(UTC)