"""BGP incident model for aggregated routing events.""" from datetime import datetime from sqlalchemy import Column, DateTime, Float, ForeignKey, Index, Integer, JSON, String, Text from app.core.enums import BGPStatus from app.core.time import to_iso8601_utc from app.db.session import Base class BGPIncident(Base): __tablename__ = "bgp_incidents" id = Column(Integer, primary_key=True, index=True) snapshot_id = Column(Integer, ForeignKey("data_snapshots.id"), nullable=True, index=True) task_id = Column(Integer, ForeignKey("collection_tasks.id"), nullable=True, index=True) source = Column(String(100), nullable=False, index=True) incident_key = Column(String(255), nullable=False, index=True) incident_type = Column(String(50), nullable=False, index=True) title = Column(String(255), nullable=False) summary = Column(Text, nullable=False) severity = Column(String(20), nullable=False, index=True) status = Column(String(20), nullable=False, default=BGPStatus.ACTIVE.value, index=True) confidence = Column(Float, nullable=False, default=0.5) started_at = Column(DateTime(timezone=True), nullable=False, default=datetime.utcnow, index=True) ended_at = Column(DateTime(timezone=True), nullable=True) affected_prefixes = Column(JSON, default=list) affected_asns = Column(JSON, default=list) affected_collectors = Column(JSON, default=list) affected_regions = Column(JSON, default=list) related_cables = Column(JSON, default=list) related_ixps = Column(JSON, default=list) evidence_refs = Column(JSON, default=list) created_at = Column(DateTime(timezone=True), nullable=False, default=datetime.utcnow, index=True) __table_args__ = ( Index("idx_bgp_incidents_source_created", "source", "created_at"), Index("idx_bgp_incidents_type_status", "incident_type", "status"), ) def to_dict(self) -> dict: return { "id": self.id, "snapshot_id": self.snapshot_id, "task_id": self.task_id, "source": self.source, "incident_key": self.incident_key, "incident_type": self.incident_type, "title": self.title, "summary": self.summary, "severity": self.severity, "status": self.status, "confidence": self.confidence, "started_at": to_iso8601_utc(self.started_at), "ended_at": to_iso8601_utc(self.ended_at), "affected_prefixes": self.affected_prefixes or [], "affected_asns": self.affected_asns or [], "affected_collectors": self.affected_collectors or [], "affected_regions": self.affected_regions or [], "related_cables": self.related_cables or [], "related_ixps": self.related_ixps or [], "evidence_refs": self.evidence_refs or [], "created_at": to_iso8601_utc(self.created_at), }