""" Control and ControlMapping Pydantic schemas — extracted from compliance/api/schemas.py. Phase 1 Step 3: the monolithic ``compliance.api.schemas`` module is being split per domain under ``compliance.schemas``. This module is re-exported from ``compliance.api.schemas`` for backwards compatibility. """ from datetime import datetime, date from typing import Optional, List, Any, Dict from pydantic import BaseModel, ConfigDict, Field from compliance.schemas.common import ( PaginationMeta, RegulationType, ControlType, ControlDomain, ControlStatus, RiskLevel, EvidenceStatus, ) # ============================================================================ # Control Schemas # ============================================================================ class ControlBase(BaseModel): control_id: str domain: str control_type: str title: str description: Optional[str] = None pass_criteria: str implementation_guidance: Optional[str] = None code_reference: Optional[str] = None documentation_url: Optional[str] = None is_automated: bool = False automation_tool: Optional[str] = None automation_config: Optional[Dict[str, Any]] = None owner: Optional[str] = None review_frequency_days: int = 90 class ControlCreate(ControlBase): pass class ControlUpdate(BaseModel): title: Optional[str] = None description: Optional[str] = None pass_criteria: Optional[str] = None implementation_guidance: Optional[str] = None code_reference: Optional[str] = None documentation_url: Optional[str] = None is_automated: Optional[bool] = None automation_tool: Optional[str] = None automation_config: Optional[Dict[str, Any]] = None owner: Optional[str] = None status: Optional[str] = None status_notes: Optional[str] = None class ControlResponse(ControlBase): id: str status: str status_notes: Optional[str] = None last_reviewed_at: Optional[datetime] = None next_review_at: Optional[datetime] = None created_at: datetime updated_at: datetime evidence_count: Optional[int] = None requirement_count: Optional[int] = None model_config = ConfigDict(from_attributes=True) class ControlListResponse(BaseModel): controls: List[ControlResponse] total: int class PaginatedControlResponse(BaseModel): """Paginated response for controls - optimized for large datasets.""" data: List[ControlResponse] pagination: PaginationMeta class ControlReviewRequest(BaseModel): status: str status_notes: Optional[str] = None # ============================================================================ # Control Mapping Schemas # ============================================================================ class MappingBase(BaseModel): requirement_id: str control_id: str coverage_level: str = "full" notes: Optional[str] = None class MappingCreate(MappingBase): pass class MappingResponse(MappingBase): id: str requirement_article: Optional[str] = None requirement_title: Optional[str] = None control_control_id: Optional[str] = None control_title: Optional[str] = None created_at: datetime model_config = ConfigDict(from_attributes=True) class MappingListResponse(BaseModel): mappings: List[MappingResponse] total: int