""" Service Module Registry models — extracted from compliance/db/models.py. Sprint 3: registry of all Breakpilot services/modules for compliance mapping, per-module regulation applicability, and per-module risk aggregation. Re-exported from ``compliance.db.models`` for backwards compatibility. DO NOT change __tablename__, column names, or relationship strings. """ import uuid import enum from datetime import datetime, timezone from sqlalchemy import ( Column, String, Text, Integer, Boolean, DateTime, ForeignKey, Enum, JSON, Index, Float, ) from sqlalchemy.orm import relationship from classroom_engine.database import Base # RiskLevelEnum is re-used across aggregates; sourced here from control_models. from compliance.db.control_models import RiskLevelEnum # noqa: F401 # ============================================================================ # ENUMS # ============================================================================ class ServiceTypeEnum(str, enum.Enum): """Type of Breakpilot service/module.""" BACKEND = "backend" # API/Backend services DATABASE = "database" # Data storage AI = "ai" # AI/ML services COMMUNICATION = "communication" # Chat/Video/Messaging STORAGE = "storage" # File/Object storage INFRASTRUCTURE = "infrastructure" # Load balancer, reverse proxy MONITORING = "monitoring" # Logging, metrics SECURITY = "security" # Auth, encryption, secrets class RelevanceLevelEnum(str, enum.Enum): """Relevance level of a regulation to a service.""" CRITICAL = "critical" # Non-compliance = shutdown HIGH = "high" # Major risk MEDIUM = "medium" # Moderate risk LOW = "low" # Minor risk # ============================================================================ # MODELS # ============================================================================ class ServiceModuleDB(Base): """ Registry of all Breakpilot services/modules for compliance mapping. Tracks which regulations apply to which services, enabling: - Service-specific compliance views - Aggregated risk per service - Gap analysis by module """ __tablename__ = 'compliance_service_modules' id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) name = Column(String(100), unique=True, nullable=False, index=True) # e.g., "consent-service" display_name = Column(String(200), nullable=False) # e.g., "Go Consent Service" description = Column(Text) # Technical details service_type = Column(Enum(ServiceTypeEnum), nullable=False) port = Column(Integer) # Primary port (if applicable) technology_stack = Column(JSON) # e.g., ["Go", "Gin", "PostgreSQL"] repository_path = Column(String(500)) # e.g., "/consent-service" docker_image = Column(String(200)) # e.g., "breakpilot-pwa-consent-service" # Data categories handled data_categories = Column(JSON) # e.g., ["personal_data", "consent_records"] processes_pii = Column(Boolean, default=False) # Handles personally identifiable info? processes_health_data = Column(Boolean, default=False) # Handles special category health data? ai_components = Column(Boolean, default=False) # Contains AI/ML components? # Status is_active = Column(Boolean, default=True) criticality = Column(String(20), default="medium") # "critical", "high", "medium", "low" # Compliance aggregation compliance_score = Column(Float) # Calculated score 0-100 last_compliance_check = Column(DateTime) # Owner owner_team = Column(String(100)) # e.g., "Backend Team" owner_contact = Column(String(200)) # e.g., "backend@breakpilot.app" # Timestamps created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) # Relationships regulation_mappings = relationship("ModuleRegulationMappingDB", back_populates="module", cascade="all, delete-orphan") module_risks = relationship("ModuleRiskDB", back_populates="module", cascade="all, delete-orphan") __table_args__ = ( Index('ix_module_type_active', 'service_type', 'is_active'), ) def __repr__(self): return f"" class ModuleRegulationMappingDB(Base): """ Maps services to applicable regulations with relevance level. Enables filtering: "Show all GDPR requirements for consent-service" """ __tablename__ = 'compliance_module_regulations' id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) module_id = Column(String(36), ForeignKey('compliance_service_modules.id'), nullable=False, index=True) regulation_id = Column(String(36), ForeignKey('compliance_regulations.id'), nullable=False, index=True) relevance_level = Column(Enum(RelevanceLevelEnum), nullable=False, default=RelevanceLevelEnum.MEDIUM) notes = Column(Text) # Why this regulation applies applicable_articles = Column(JSON) # List of specific articles that apply # Timestamps created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) # Relationships module = relationship("ServiceModuleDB", back_populates="regulation_mappings") regulation = relationship("RegulationDB") __table_args__ = ( Index('ix_module_regulation', 'module_id', 'regulation_id', unique=True), ) class ModuleRiskDB(Base): """ Service-specific risks aggregated from requirements and controls. """ __tablename__ = 'compliance_module_risks' id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) module_id = Column(String(36), ForeignKey('compliance_service_modules.id'), nullable=False, index=True) risk_id = Column(String(36), ForeignKey('compliance_risks.id'), nullable=False, index=True) # Module-specific assessment module_likelihood = Column(Integer) # 1-5, may differ from global module_impact = Column(Integer) # 1-5, may differ from global module_risk_level = Column(Enum(RiskLevelEnum)) assessment_notes = Column(Text) # Module-specific notes # Timestamps created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc)) updated_at = Column(DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc)) # Relationships module = relationship("ServiceModuleDB", back_populates="module_risks") risk = relationship("RiskDB") __table_args__ = ( Index('ix_module_risk', 'module_id', 'risk_id', unique=True), ) __all__ = [ "ServiceTypeEnum", "RelevanceLevelEnum", "ServiceModuleDB", "ModuleRegulationMappingDB", "ModuleRiskDB", ]