""" Architecture Scan Models Database models for tracking code quality scans and violations """ from sqlalchemy import Column, Integer, String, Float, DateTime, Text, Boolean, ForeignKey, JSON from sqlalchemy.orm import relationship from sqlalchemy.sql import func from app.database import Base class ArchitectureScan(Base): """Represents a single run of the architecture validator""" __tablename__ = "architecture_scans" id = Column(Integer, primary_key=True, index=True) timestamp = Column(DateTime(timezone=True), server_default=func.now(), nullable=False, index=True) total_files = Column(Integer, default=0) total_violations = Column(Integer, default=0) errors = Column(Integer, default=0) warnings = Column(Integer, default=0) duration_seconds = Column(Float, default=0.0) triggered_by = Column(String(100)) # 'manual', 'scheduled', 'ci/cd' git_commit_hash = Column(String(40)) # Relationship to violations violations = relationship("ArchitectureViolation", back_populates="scan", cascade="all, delete-orphan") def __repr__(self): return f"" class ArchitectureViolation(Base): """Represents a single architectural violation found during a scan""" __tablename__ = "architecture_violations" id = Column(Integer, primary_key=True, index=True) scan_id = Column(Integer, ForeignKey("architecture_scans.id"), nullable=False, index=True) rule_id = Column(String(20), nullable=False, index=True) # e.g., 'API-001' rule_name = Column(String(200), nullable=False) severity = Column(String(10), nullable=False, index=True) # 'error', 'warning', 'info' file_path = Column(String(500), nullable=False, index=True) line_number = Column(Integer, nullable=False) message = Column(Text, nullable=False) context = Column(Text) # Code snippet suggestion = Column(Text) status = Column(String(20), default='open', index=True) # 'open', 'assigned', 'resolved', 'ignored', 'technical_debt' assigned_to = Column(Integer, ForeignKey("users.id")) resolved_at = Column(DateTime(timezone=True)) resolved_by = Column(Integer, ForeignKey("users.id")) resolution_note = Column(Text) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) # Relationships scan = relationship("ArchitectureScan", back_populates="violations") assigned_user = relationship("User", foreign_keys=[assigned_to], backref="assigned_violations") resolver = relationship("User", foreign_keys=[resolved_by], backref="resolved_violations") assignments = relationship("ViolationAssignment", back_populates="violation", cascade="all, delete-orphan") comments = relationship("ViolationComment", back_populates="violation", cascade="all, delete-orphan") def __repr__(self): return f"" class ArchitectureRule(Base): """Architecture rules configuration (from YAML with database overrides)""" __tablename__ = "architecture_rules" id = Column(Integer, primary_key=True, index=True) rule_id = Column(String(20), unique=True, nullable=False, index=True) # e.g., 'API-001' category = Column(String(50), nullable=False) # 'api_endpoint', 'service_layer', etc. name = Column(String(200), nullable=False) description = Column(Text) severity = Column(String(10), nullable=False) # Can override default from YAML enabled = Column(Boolean, default=True, nullable=False) custom_config = Column(JSON) # For rule-specific settings created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) def __repr__(self): return f"" class ViolationAssignment(Base): """Tracks assignment of violations to developers""" __tablename__ = "violation_assignments" id = Column(Integer, primary_key=True, index=True) violation_id = Column(Integer, ForeignKey("architecture_violations.id"), nullable=False, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) assigned_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) assigned_by = Column(Integer, ForeignKey("users.id")) due_date = Column(DateTime(timezone=True)) priority = Column(String(10), default='medium') # 'low', 'medium', 'high', 'critical' # Relationships violation = relationship("ArchitectureViolation", back_populates="assignments") user = relationship("User", foreign_keys=[user_id], backref="violation_assignments") assigner = relationship("User", foreign_keys=[assigned_by], backref="assigned_by_me") def __repr__(self): return f"" class ViolationComment(Base): """Comments on violations for collaboration""" __tablename__ = "violation_comments" id = Column(Integer, primary_key=True, index=True) violation_id = Column(Integer, ForeignKey("architecture_violations.id"), nullable=False, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) comment = Column(Text, nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) # Relationships violation = relationship("ArchitectureViolation", back_populates="comments") user = relationship("User", backref="violation_comments") def __repr__(self): return f""