"""Pydantic contracts for the inventory domain.""" from datetime import datetime from typing import Literal from uuid import UUID from pydantic import BaseModel, ConfigDict, Field, IPvAnyAddress LifecycleStatus = Literal["active", "spare", "retired"] class InventoryTag(BaseModel): id: UUID name: str created_at: datetime updated_at: datetime class InventoryMinerSummary(BaseModel): id: UUID asset_id: str | None = None current_mac: str | None = None current_ip: str | None = None model: str | None = None lifecycle_status: LifecycleStatus runtime_status: str site_id: UUID | None = None room_id: UUID | None = None tags: list[InventoryTag] = Field(default_factory=list) created_at: datetime updated_at: datetime last_seen_at: datetime | None = None class InventoryMinerDetail(InventoryMinerSummary): hostname: str | None = None miner_sn: str | None = None control_board_sn: str | None = None psu_serial: str | None = None firmware_version: str | None = None notes: str | None = None first_seen_at: datetime | None = None class InventoryCreateRequest(BaseModel): asset_id: str = Field(min_length=1, max_length=120) current_mac: str | None = Field(default=None, max_length=64) current_ip: IPvAnyAddress | None = None hostname: str | None = Field(default=None, max_length=255) miner_sn: str | None = Field(default=None, max_length=255) control_board_sn: str | None = Field(default=None, max_length=255) psu_serial: str | None = Field(default=None, max_length=255) model: str | None = Field(default=None, max_length=255) firmware_version: str | None = Field(default=None, max_length=255) lifecycle_status: str = "active" site_id: UUID | None = None room_id: UUID | None = None notes: str | None = None tags: list[str] = Field(default_factory=list) class InventoryMetadataUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") asset_id: str | None = Field(default=None, max_length=120) miner_sn: str | None = Field(default=None, max_length=255) psu_serial: str | None = Field(default=None, max_length=255) model: str | None = Field(default=None, max_length=255) notes: str | None = None class InventoryUpdateRequest(BaseModel): asset_id: str | None = Field(default=None, max_length=120) current_mac: str | None = Field(default=None, max_length=64) current_ip: IPvAnyAddress | None = None hostname: str | None = Field(default=None, max_length=255) miner_sn: str | None = Field(default=None, max_length=255) control_board_sn: str | None = Field(default=None, max_length=255) psu_serial: str | None = Field(default=None, max_length=255) model: str | None = Field(default=None, max_length=255) firmware_version: str | None = Field(default=None, max_length=255) lifecycle_status: str | None = None site_id: UUID | None = None room_id: UUID | None = None notes: str | None = None tags: list[str] | None = None class InventorySearchFilters(BaseModel): query: str | None = None asset_id: str | None = None lifecycle_status: str | None = None tags: list[str] = Field(default_factory=list) limit: int = Field(default=100, ge=1, le=500) offset: int = Field(default=0, ge=0) class InventoryListMeta(BaseModel): limit: int offset: int returned: int class InventoryMinerListResponse(BaseModel): data: list[InventoryMinerSummary] meta: InventoryListMeta error: None = None class InventoryMinerDetailResponse(BaseModel): data: InventoryMinerDetail meta: dict[str, object] = Field(default_factory=dict) error: None = None