""" ISMS Governance (Scope, Context, Policy, Objective, SoA) 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, ) # ============================================================================ # ISO 27001 ISMS Schemas (Kapitel 4-10) # ============================================================================ # --- Enums --- class ApprovalStatus(str): DRAFT = "draft" UNDER_REVIEW = "under_review" APPROVED = "approved" SUPERSEDED = "superseded" class FindingType(str): MAJOR = "major" MINOR = "minor" OFI = "ofi" POSITIVE = "positive" class FindingStatus(str): OPEN = "open" IN_PROGRESS = "in_progress" CAPA_PENDING = "capa_pending" VERIFICATION_PENDING = "verification_pending" VERIFIED = "verified" CLOSED = "closed" class CAPAType(str): CORRECTIVE = "corrective" PREVENTIVE = "preventive" BOTH = "both" # --- ISMS Scope (ISO 27001 4.3) --- class ISMSScopeBase(BaseModel): """Base schema for ISMS Scope.""" scope_statement: str included_locations: Optional[List[str]] = None included_processes: Optional[List[str]] = None included_services: Optional[List[str]] = None excluded_items: Optional[List[str]] = None exclusion_justification: Optional[str] = None organizational_boundary: Optional[str] = None physical_boundary: Optional[str] = None technical_boundary: Optional[str] = None class ISMSScopeCreate(ISMSScopeBase): """Schema for creating ISMS Scope.""" pass class ISMSScopeUpdate(BaseModel): """Schema for updating ISMS Scope.""" scope_statement: Optional[str] = None included_locations: Optional[List[str]] = None included_processes: Optional[List[str]] = None included_services: Optional[List[str]] = None excluded_items: Optional[List[str]] = None exclusion_justification: Optional[str] = None organizational_boundary: Optional[str] = None physical_boundary: Optional[str] = None technical_boundary: Optional[str] = None class ISMSScopeResponse(ISMSScopeBase): """Response schema for ISMS Scope.""" id: str version: str status: str approved_by: Optional[str] = None approved_at: Optional[datetime] = None effective_date: Optional[date] = None review_date: Optional[date] = None created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class ISMSScopeApproveRequest(BaseModel): """Request to approve ISMS Scope.""" approved_by: str effective_date: date review_date: date # --- ISMS Context (ISO 27001 4.1, 4.2) --- class ContextIssue(BaseModel): """Single context issue.""" issue: str impact: str treatment: Optional[str] = None class InterestedParty(BaseModel): """Single interested party.""" party: str requirements: List[str] relevance: str class ISMSContextBase(BaseModel): """Base schema for ISMS Context.""" internal_issues: Optional[List[ContextIssue]] = None external_issues: Optional[List[ContextIssue]] = None interested_parties: Optional[List[InterestedParty]] = None regulatory_requirements: Optional[List[str]] = None contractual_requirements: Optional[List[str]] = None swot_strengths: Optional[List[str]] = None swot_weaknesses: Optional[List[str]] = None swot_opportunities: Optional[List[str]] = None swot_threats: Optional[List[str]] = None class ISMSContextCreate(ISMSContextBase): """Schema for creating ISMS Context.""" pass class ISMSContextResponse(ISMSContextBase): """Response schema for ISMS Context.""" id: str version: str status: str approved_by: Optional[str] = None approved_at: Optional[datetime] = None last_reviewed_at: Optional[datetime] = None next_review_date: Optional[date] = None created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) # --- ISMS Policies (ISO 27001 5.2) --- class ISMSPolicyBase(BaseModel): """Base schema for ISMS Policy.""" policy_id: str title: str policy_type: str # "master", "operational", "technical" description: Optional[str] = None policy_text: str applies_to: Optional[List[str]] = None review_frequency_months: int = 12 related_controls: Optional[List[str]] = None class ISMSPolicyCreate(ISMSPolicyBase): """Schema for creating ISMS Policy.""" authored_by: str class ISMSPolicyUpdate(BaseModel): """Schema for updating ISMS Policy.""" title: Optional[str] = None description: Optional[str] = None policy_text: Optional[str] = None applies_to: Optional[List[str]] = None review_frequency_months: Optional[int] = None related_controls: Optional[List[str]] = None class ISMSPolicyResponse(ISMSPolicyBase): """Response schema for ISMS Policy.""" id: str version: str status: str authored_by: Optional[str] = None reviewed_by: Optional[str] = None approved_by: Optional[str] = None approved_at: Optional[datetime] = None effective_date: Optional[date] = None next_review_date: Optional[date] = None document_path: Optional[str] = None created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class ISMSPolicyListResponse(BaseModel): """List response for ISMS Policies.""" policies: List[ISMSPolicyResponse] total: int class ISMSPolicyApproveRequest(BaseModel): """Request to approve ISMS Policy.""" reviewed_by: str approved_by: str effective_date: date # --- Security Objectives (ISO 27001 6.2) --- class SecurityObjectiveBase(BaseModel): """Base schema for Security Objective.""" objective_id: str title: str description: Optional[str] = None category: str # "availability", "confidentiality", "integrity", "compliance" specific: Optional[str] = None measurable: Optional[str] = None achievable: Optional[str] = None relevant: Optional[str] = None time_bound: Optional[str] = None kpi_name: Optional[str] = None kpi_target: Optional[str] = None kpi_unit: Optional[str] = None measurement_frequency: Optional[str] = None owner: Optional[str] = None target_date: Optional[date] = None related_controls: Optional[List[str]] = None related_risks: Optional[List[str]] = None class SecurityObjectiveCreate(SecurityObjectiveBase): """Schema for creating Security Objective.""" pass class SecurityObjectiveUpdate(BaseModel): """Schema for updating Security Objective.""" title: Optional[str] = None description: Optional[str] = None kpi_current: Optional[str] = None progress_percentage: Optional[int] = None status: Optional[str] = None class SecurityObjectiveResponse(SecurityObjectiveBase): """Response schema for Security Objective.""" id: str kpi_current: Optional[str] = None status: str progress_percentage: int achieved_date: Optional[date] = None approved_by: Optional[str] = None approved_at: Optional[datetime] = None created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class SecurityObjectiveListResponse(BaseModel): """List response for Security Objectives.""" objectives: List[SecurityObjectiveResponse] total: int # --- Statement of Applicability (SoA) --- class SoAEntryBase(BaseModel): """Base schema for SoA Entry.""" annex_a_control: str # e.g., "A.5.1" annex_a_title: str annex_a_category: Optional[str] = None is_applicable: bool applicability_justification: str implementation_status: str = "planned" implementation_notes: Optional[str] = None breakpilot_control_ids: Optional[List[str]] = None coverage_level: str = "full" evidence_description: Optional[str] = None risk_assessment_notes: Optional[str] = None compensating_controls: Optional[str] = None class SoAEntryCreate(SoAEntryBase): """Schema for creating SoA Entry.""" pass class SoAEntryUpdate(BaseModel): """Schema for updating SoA Entry.""" is_applicable: Optional[bool] = None applicability_justification: Optional[str] = None implementation_status: Optional[str] = None implementation_notes: Optional[str] = None breakpilot_control_ids: Optional[List[str]] = None coverage_level: Optional[str] = None evidence_description: Optional[str] = None class SoAEntryResponse(SoAEntryBase): """Response schema for SoA Entry.""" id: str evidence_ids: Optional[List[str]] = None reviewed_by: Optional[str] = None reviewed_at: Optional[datetime] = None approved_by: Optional[str] = None approved_at: Optional[datetime] = None version: str created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class SoAListResponse(BaseModel): """List response for SoA.""" entries: List[SoAEntryResponse] total: int applicable_count: int not_applicable_count: int implemented_count: int planned_count: int class SoAApproveRequest(BaseModel): """Request to approve SoA entry.""" reviewed_by: str approved_by: str # --- Audit Findings (Major/Minor/OFI) ---