import uuid from datetime import datetime from typing import Literal from pydantic import BaseModel, ConfigDict, Field, computed_field GDPRMaturity = Literal[ "unknown", "non_compliant", "initial", "developing", "defined", "managed", "certified", ] GDPR_WARNING_LEVELS = {"unknown", "non_compliant", "initial"} PricingModel = Literal["free", "paid", "freemium", "usage_based", "unknown"] AuthType = Literal["api_key", "oauth", "cli", "none", "unknown"] class TPSCCatalogCreate(BaseModel): slug: str name: str provider: str | None = None category: str | None = None website_url: str | None = None pricing_model: PricingModel = "unknown" gdpr_maturity: GDPRMaturity = "unknown" gdpr_notes: str | None = None dpa_available: bool = False tos_url: str | None = None privacy_policy_url: str | None = None data_processing_regions: list[str] | None = None data_retention_notes: str | None = None status: str = "active" class TPSCCatalogRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID slug: str name: str provider: str | None category: str | None website_url: str | None pricing_model: str gdpr_maturity: str gdpr_notes: str | None dpa_available: bool tos_url: str | None privacy_policy_url: str | None data_processing_regions: list[str] | None data_retention_notes: str | None status: str created_at: datetime updated_at: datetime @computed_field @property def gdpr_warning(self) -> bool: return self.gdpr_maturity in GDPR_WARNING_LEVELS class TPSCEntryCreate(BaseModel): service_slug: str purpose: str | None = None auth_type: str | None = None endpoint_override: str | None = None notes: str | None = None class TPSCEntryRead(TPSCEntryCreate): model_config = ConfigDict(from_attributes=True) id: uuid.UUID snapshot_id: uuid.UUID catalog_id: uuid.UUID | None = None gdpr_maturity: str | None = None gdpr_warning: bool = False pricing_model: str | None = None class TPSCIngestRequest(BaseModel): repo_slug: str source_file: str = "tpsc.yaml" entries: list[TPSCEntryCreate] class TPSCSnapshotRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID repo_id: uuid.UUID | None = None snapshot_at: datetime source_file: str | None = None entry_count: int entries: list[TPSCEntryRead] = Field(default_factory=list) class TPSCGDPRWarning(BaseModel): repo_slug: str | None service_slug: str gdpr_maturity: str purpose: str | None pricing_model: str | None class TPSCGDPRReport(BaseModel): generated_at: datetime total_services: int warning_count: int warnings: list[TPSCGDPRWarning] by_maturity: dict[str, int]