"""Push log model (audit trail for SSH commands)""" from sqlalchemy import Column, String, Integer, ForeignKey, Text, Boolean, Index, Enum from sqlalchemy.orm import relationship from app.models.base import BaseModel import enum class PushStatus(str, enum.Enum): """Push execution status""" PENDING = "pending" IN_PROGRESS = "in_progress" SUCCESS = "success" FAILED = "failed" ROLLED_BACK = "rolled_back" class PushLog(BaseModel): """ Audit log for each SSH push attempt. CRITICAL: All push actions must be logged for compliance and rollback. """ __tablename__ = "push_logs" __table_args__ = ( Index("ix_push_logs_device_id", "device_id"), Index("ix_push_logs_config_id", "configuration_id"), ) device_id = Column(Integer, ForeignKey("devices.id"), nullable=False) configuration_id = Column(Integer, ForeignKey("configurations.id"), nullable=False) # Commands pushed (plain text for audit) commands_sent = Column(Text, nullable=False) # Execution status status = Column(Enum(PushStatus), default=PushStatus.PENDING, nullable=False) # Response from device device_output = Column(Text, nullable=True) error_message = Column(Text, nullable=True) # Backup & rollback info pre_push_backup = Column(Text, nullable=True) # running-config before push was_rolled_back = Column(Boolean, default=False, nullable=False) rollback_reason = Column(Text, nullable=True) # Metadata pushed_by = Column(String(255), nullable=True) # username ssh_connection_time_ms = Column(Integer, nullable=True) # Relationships device = relationship("Device", back_populates="push_logs") configuration = relationship("Configuration", back_populates="push_logs") def __repr__(self): return f""