"""Compliance models — frameworks, controls, and technique mappings. Maps compliance frameworks (NIST 800-53, DORA, NIS2, ISO 27001) to MITRE ATT&CK techniques, enabling compliance gap analysis. """ import uuid from datetime import datetime from sqlalchemy import ( Column, String, Text, Boolean, DateTime, ForeignKey, Index, UniqueConstraint, ) from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from app.database import Base class ComplianceFramework(Base): """A compliance framework (e.g. NIST 800-53, ISO 27001).""" __tablename__ = "compliance_frameworks" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) name = Column(String, unique=True, nullable=False) version = Column(String, nullable=True) description = Column(Text, nullable=True) url = Column(String, nullable=True) is_active = Column(Boolean, default=True) created_at = Column(DateTime, default=datetime.utcnow) # Relationships controls = relationship( "ComplianceControl", back_populates="framework", cascade="all, delete-orphan", ) class ComplianceControl(Base): """A control within a compliance framework (e.g. AC-2, PR.AC-1).""" __tablename__ = "compliance_controls" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) framework_id = Column( UUID(as_uuid=True), ForeignKey("compliance_frameworks.id", ondelete="CASCADE"), nullable=False, ) control_id = Column(String, nullable=False) # e.g. "AC-2" title = Column(String, nullable=False) description = Column(Text, nullable=True) category = Column(String, nullable=True) # Relationships framework = relationship("ComplianceFramework", back_populates="controls") technique_mappings = relationship( "ComplianceControlMapping", back_populates="compliance_control", cascade="all, delete-orphan", ) __table_args__ = ( Index('ix_compliance_controls_framework', 'framework_id'), ) class ComplianceControlMapping(Base): """Maps a compliance control to a MITRE ATT&CK technique.""" __tablename__ = "compliance_control_mappings" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) compliance_control_id = Column( UUID(as_uuid=True), ForeignKey("compliance_controls.id", ondelete="CASCADE"), nullable=False, ) technique_id = Column( UUID(as_uuid=True), ForeignKey("techniques.id", ondelete="CASCADE"), nullable=False, ) # Relationships compliance_control = relationship( "ComplianceControl", back_populates="technique_mappings" ) technique = relationship("Technique") __table_args__ = ( Index('ix_compliance_mappings_control', 'compliance_control_id'), Index('ix_compliance_mappings_technique', 'technique_id'), UniqueConstraint( 'compliance_control_id', 'technique_id', name='uq_control_technique', ), )