# app/modules/prospecting/schemas/security_audit.py """Pydantic schemas for security audit responses.""" import json from datetime import datetime from pydantic import BaseModel, Field, field_validator class SecurityAuditFinding(BaseModel): """A single security finding.""" title: str severity: str category: str detail: str is_positive: bool = False class SecurityAuditResponse(BaseModel): """Schema for security audit detail response.""" id: int prospect_id: int score: int grade: str detected_language: str | None = None findings: list[SecurityAuditFinding] = Field(default=[], validation_alias="findings_json") findings_count_critical: int = 0 findings_count_high: int = 0 findings_count_medium: int = 0 findings_count_low: int = 0 findings_count_info: int = 0 has_https: bool | None = None has_valid_ssl: bool | None = None ssl_expires_at: datetime | None = None missing_headers: list[str] = Field(default=[], validation_alias="missing_headers_json") exposed_files: list[str] = Field(default=[], validation_alias="exposed_files_json") technologies: list[str] = Field(default=[], validation_alias="technologies_json") scan_error: str | None = None created_at: datetime updated_at: datetime @field_validator("findings", mode="before") @classmethod def parse_findings(cls, v): if isinstance(v, str): return json.loads(v) return v @field_validator("missing_headers", mode="before") @classmethod def parse_missing_headers(cls, v): if isinstance(v, str): return json.loads(v) return v or [] @field_validator("exposed_files", mode="before") @classmethod def parse_exposed_files(cls, v): if isinstance(v, str): return json.loads(v) return v or [] @field_validator("technologies", mode="before") @classmethod def parse_technologies(cls, v): if isinstance(v, str): return json.loads(v) return v or [] class Config: from_attributes = True class SecurityAuditSingleResponse(BaseModel): """Response for single-prospect security audit.""" domain: str score: int grade: str findings_count: int