""" Pydantic schemas for Machine model. Request and response schemas for technician's machines used for MSP work. """ from datetime import datetime from typing import Optional from uuid import UUID from pydantic import BaseModel, Field class MachineBase(BaseModel): """Base schema with shared Machine fields.""" hostname: str = Field(..., description="Machine hostname from `hostname` command") machine_fingerprint: Optional[str] = Field(None, description="SHA256 hash: hostname + username + platform + home_directory") friendly_name: Optional[str] = Field(None, description="Human-readable name like 'Main Laptop' or 'Home Desktop'") machine_type: Optional[str] = Field(None, description="Type of machine: laptop, desktop, workstation, vm") platform: Optional[str] = Field(None, description="Operating system platform: win32, darwin, linux") os_version: Optional[str] = Field(None, description="Operating system version") username: Optional[str] = Field(None, description="Username from `whoami` command") home_directory: Optional[str] = Field(None, description="User home directory path") has_vpn_access: bool = Field(False, description="Whether machine can connect to client networks") vpn_profiles: Optional[str] = Field(None, description="JSON array of available VPN profiles") has_docker: bool = Field(False, description="Whether Docker is installed") has_powershell: bool = Field(False, description="Whether PowerShell is installed") powershell_version: Optional[str] = Field(None, description="PowerShell version if installed") has_ssh: bool = Field(True, description="Whether SSH is available") has_git: bool = Field(True, description="Whether Git is installed") typical_network_location: Optional[str] = Field(None, description="Typical network location: home, office, mobile") static_ip: Optional[str] = Field(None, description="Static IP address if applicable (supports IPv4/IPv6)") claude_working_directory: Optional[str] = Field(None, description="Primary working directory for Claude Code") additional_working_dirs: Optional[str] = Field(None, description="JSON array of additional working directories") installed_tools: Optional[str] = Field(None, description='JSON object with tool versions like {"git": "2.40", "docker": "24.0"}') available_mcps: Optional[str] = Field(None, description="JSON array of available MCP servers") mcp_capabilities: Optional[str] = Field(None, description="JSON object with MCP capabilities") available_skills: Optional[str] = Field(None, description="JSON array of available skills") skill_paths: Optional[str] = Field(None, description="JSON object mapping skill names to paths") preferred_shell: Optional[str] = Field(None, description="Preferred shell: powershell, bash, zsh, cmd") package_manager_commands: Optional[str] = Field(None, description="JSON object with package manager commands") is_primary: bool = Field(False, description="Whether this is the primary machine") is_active: bool = Field(True, description="Whether machine is currently active") last_seen: Optional[datetime] = Field(None, description="Last time machine was seen") last_session_id: Optional[str] = Field(None, description="UUID of last session from this machine") notes: Optional[str] = Field(None, description="Additional notes about the machine") class MachineCreate(MachineBase): """Schema for creating a new Machine.""" pass class MachineUpdate(BaseModel): """Schema for updating an existing Machine. All fields are optional.""" hostname: Optional[str] = Field(None, description="Machine hostname from `hostname` command") machine_fingerprint: Optional[str] = Field(None, description="SHA256 hash: hostname + username + platform + home_directory") friendly_name: Optional[str] = Field(None, description="Human-readable name like 'Main Laptop' or 'Home Desktop'") machine_type: Optional[str] = Field(None, description="Type of machine: laptop, desktop, workstation, vm") platform: Optional[str] = Field(None, description="Operating system platform: win32, darwin, linux") os_version: Optional[str] = Field(None, description="Operating system version") username: Optional[str] = Field(None, description="Username from `whoami` command") home_directory: Optional[str] = Field(None, description="User home directory path") has_vpn_access: Optional[bool] = Field(None, description="Whether machine can connect to client networks") vpn_profiles: Optional[str] = Field(None, description="JSON array of available VPN profiles") has_docker: Optional[bool] = Field(None, description="Whether Docker is installed") has_powershell: Optional[bool] = Field(None, description="Whether PowerShell is installed") powershell_version: Optional[str] = Field(None, description="PowerShell version if installed") has_ssh: Optional[bool] = Field(None, description="Whether SSH is available") has_git: Optional[bool] = Field(None, description="Whether Git is installed") typical_network_location: Optional[str] = Field(None, description="Typical network location: home, office, mobile") static_ip: Optional[str] = Field(None, description="Static IP address if applicable (supports IPv4/IPv6)") claude_working_directory: Optional[str] = Field(None, description="Primary working directory for Claude Code") additional_working_dirs: Optional[str] = Field(None, description="JSON array of additional working directories") installed_tools: Optional[str] = Field(None, description='JSON object with tool versions like {"git": "2.40", "docker": "24.0"}') available_mcps: Optional[str] = Field(None, description="JSON array of available MCP servers") mcp_capabilities: Optional[str] = Field(None, description="JSON object with MCP capabilities") available_skills: Optional[str] = Field(None, description="JSON array of available skills") skill_paths: Optional[str] = Field(None, description="JSON object mapping skill names to paths") preferred_shell: Optional[str] = Field(None, description="Preferred shell: powershell, bash, zsh, cmd") package_manager_commands: Optional[str] = Field(None, description="JSON object with package manager commands") is_primary: Optional[bool] = Field(None, description="Whether this is the primary machine") is_active: Optional[bool] = Field(None, description="Whether machine is currently active") last_seen: Optional[datetime] = Field(None, description="Last time machine was seen") last_session_id: Optional[str] = Field(None, description="UUID of last session from this machine") notes: Optional[str] = Field(None, description="Additional notes about the machine") class MachineResponse(MachineBase): """Schema for Machine responses with ID and timestamps.""" id: UUID = Field(..., description="Unique identifier for the machine") created_at: datetime = Field(..., description="Timestamp when the machine was created") updated_at: datetime = Field(..., description="Timestamp when the machine was last updated") model_config = {"from_attributes": True}