""" Regulation & Requirement models — extracted from compliance/db/models.py. The foundational compliance aggregate: regulations (GDPR, AI Act, CRA, ...) and the individual requirements they contain. 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, Date, ForeignKey, Enum, JSON, Index, ) from sqlalchemy.orm import relationship from classroom_engine.database import Base # ============================================================================ # ENUMS # ============================================================================ class RegulationTypeEnum(str, enum.Enum): """Type of regulation/standard.""" EU_REGULATION = "eu_regulation" # Directly applicable EU law EU_DIRECTIVE = "eu_directive" # Requires national implementation DE_LAW = "de_law" # German national law BSI_STANDARD = "bsi_standard" # BSI technical guidelines INDUSTRY_STANDARD = "industry_standard" # ISO, OWASP, etc. # ============================================================================ # MODELS # ============================================================================ class RegulationDB(Base): """ Represents a regulation, directive, or standard. Examples: GDPR, AI Act, CRA, BSI-TR-03161 """ __tablename__ = 'compliance_regulations' id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) code = Column(String(20), unique=True, nullable=False, index=True) # e.g., "GDPR", "AIACT" name = Column(String(200), nullable=False) # Short name full_name = Column(Text) # Full official name regulation_type = Column(Enum(RegulationTypeEnum), nullable=False) source_url = Column(String(500)) # EUR-Lex URL or similar local_pdf_path = Column(String(500)) # Local PDF if available effective_date = Column(Date) # When it came into force description = Column(Text) # Brief description is_active = Column(Boolean, default=True) # 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 requirements = relationship("RequirementDB", back_populates="regulation", cascade="all, delete-orphan") def __repr__(self): return f"" class RequirementDB(Base): """ Individual requirement from a regulation. Examples: GDPR Art. 32(1)(a), AI Act Art. 9, BSI-TR O.Auth_1 """ __tablename__ = 'compliance_requirements' id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4())) regulation_id = Column(String(36), ForeignKey('compliance_regulations.id'), nullable=False, index=True) # Requirement identification article = Column(String(50), nullable=False) # e.g., "Art. 32", "O.Auth_1" paragraph = Column(String(20)) # e.g., "(1)(a)" requirement_id_external = Column(String(50)) # External ID (e.g., BSI ID) title = Column(String(300), nullable=False) # Requirement title description = Column(Text) # Brief description requirement_text = Column(Text) # Original text from regulation # Breakpilot-specific interpretation and implementation breakpilot_interpretation = Column(Text) # How Breakpilot interprets this implementation_status = Column(String(30), default="not_started") # not_started, in_progress, implemented, verified implementation_details = Column(Text) # How we implemented it code_references = Column(JSON) # List of {"file": "...", "line": ..., "description": "..."} documentation_links = Column(JSON) # List of internal doc links # Evidence for auditors evidence_description = Column(Text) # What evidence proves compliance evidence_artifacts = Column(JSON) # List of {"type": "...", "path": "...", "description": "..."} # Audit-specific fields auditor_notes = Column(Text) # Notes from auditor review audit_status = Column(String(30), default="pending") # pending, in_review, approved, rejected last_audit_date = Column(DateTime) last_auditor = Column(String(100)) is_applicable = Column(Boolean, default=True) # Applicable to Breakpilot? applicability_reason = Column(Text) # Why/why not applicable priority = Column(Integer, default=2) # 1=Critical, 2=High, 3=Medium # Source document reference source_page = Column(Integer) # Page number in source document source_section = Column(String(100)) # Section in source document # 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 = relationship("RegulationDB", back_populates="requirements") control_mappings = relationship("ControlMappingDB", back_populates="requirement", cascade="all, delete-orphan") __table_args__ = ( Index('ix_requirement_regulation_article', 'regulation_id', 'article'), Index('ix_requirement_audit_status', 'audit_status'), Index('ix_requirement_impl_status', 'implementation_status'), ) def __repr__(self): return f"" __all__ = ["RegulationTypeEnum", "RegulationDB", "RequirementDB"]