"""TestDetectionResult — tracks which detection rules triggered during a test. When the Blue Team evaluates a test, they mark each associated detection rule as triggered / not triggered / not applicable, along with notes. """ import uuid from sqlalchemy import ( Boolean, Column, DateTime, ForeignKey, Index, Text, UniqueConstraint, ) from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from app.database import Base class TestDetectionResult(Base): """ Per-test, per-rule evaluation result. - ``triggered`` = True: rule detected the attack - ``triggered`` = False: rule did NOT detect the attack - ``triggered`` = None: not yet evaluated """ __tablename__ = "test_detection_results" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) test_id = Column( UUID(as_uuid=True), ForeignKey("tests.id", ondelete="CASCADE"), nullable=False, ) detection_rule_id = Column( UUID(as_uuid=True), ForeignKey("detection_rules.id", ondelete="CASCADE"), nullable=False, ) triggered = Column(Boolean, nullable=True) # None = not evaluated notes = Column(Text, nullable=True) evaluated_by = Column( UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL"), nullable=True, ) evaluated_at = Column(DateTime, nullable=True) # Relationships test = relationship("Test") detection_rule = relationship("DetectionRule") evaluator = relationship("User", foreign_keys=[evaluated_by]) __table_args__ = ( Index('ix_tdr_test', 'test_id'), Index('ix_tdr_rule', 'detection_rule_id'), UniqueConstraint('test_id', 'detection_rule_id', name='uq_tdr_test_rule'), )