Files
orion/app/models/architecture_scan.py
Samir Boulahtit 21c13ca39b style: apply black and isort formatting across entire codebase
- Standardize quote style (single to double quotes)
- Reorder and group imports alphabetically
- Fix line breaks and indentation for consistency
- Apply PEP 8 formatting standards

Also updated Makefile to exclude both venv and .venv from code quality checks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 19:30:17 +01:00

171 lines
6.1 KiB
Python

"""
Architecture Scan Models
Database models for tracking code quality scans and violations
"""
from sqlalchemy import (JSON, Boolean, Column, DateTime, Float, ForeignKey,
Integer, String, Text)
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.core.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"<ArchitectureScan(id={self.id}, violations={self.total_violations}, errors={self.errors})>"
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"<ArchitectureViolation(id={self.id}, rule={self.rule_id}, file={self.file_path}:{self.line_number})>"
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"<ArchitectureRule(id={self.rule_id}, name={self.name}, enabled={self.enabled})>"
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"<ViolationAssignment(id={self.id}, violation_id={self.violation_id}, user_id={self.user_id})>"
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"<ViolationComment(id={self.id}, violation_id={self.violation_id}, user_id={self.user_id})>"