"""Audit log, approval request, chat message, and enterprise info models.""" import uuid from datetime import datetime from sqlalchemy import DateTime, Enum, ForeignKey, Integer, String, Text, func from sqlalchemy.dialects.postgresql import JSON, UUID from sqlalchemy.orm import Mapped, mapped_column, relationship from app.database import Base class AuditLog(Base): """Audit trail for all operations.""" __tablename__ = "audit_logs" id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("users.id")) agent_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("agents.id")) action: Mapped[str] = mapped_column(String(100), nullable=False) details: Mapped[dict] = mapped_column(JSON, default={}) ip_address: Mapped[str | None] = mapped_column(String(50)) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), index=True) class ApprovalRequest(Base): """Approval request for L3 autonomy operations.""" __tablename__ = "approval_requests" id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) agent_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("agents.id"), nullable=False) action_type: Mapped[str] = mapped_column(String(100), nullable=False) details: Mapped[dict] = mapped_column(JSON, default={}) status: Mapped[str] = mapped_column( Enum("pending", "approved", "rejected", name="approval_status_enum"), default="pending", nullable=False, ) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) resolved_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) resolved_by: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("users.id")) class ChatMessage(Base): """Web chat message between user and agent.""" __tablename__ = "chat_messages" id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) agent_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("agents.id"), nullable=False, index=True) user_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=False) role: Mapped[str] = mapped_column( Enum("user", "assistant", "system", "tool_call", name="chat_role_enum"), nullable=False, ) content: Mapped[str] = mapped_column(Text, nullable=False) conversation_id: Mapped[str] = mapped_column(String(200), default="web", nullable=False) # Participant identity (unified User/Agent identity) participant_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("participants.id"), nullable=True) # Model thinking process thinking: Mapped[str | None] = mapped_column(Text, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), index=True) class EnterpriseInfo(Base): """Centralized enterprise information with versioning for sync.""" __tablename__ = "enterprise_info" id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) info_type: Mapped[str] = mapped_column(String(50), nullable=False, unique=True) # org_structure, company_profile, etc. content: Mapped[dict] = mapped_column(JSON, nullable=False) version: Mapped[int] = mapped_column(Integer, default=1, nullable=False) visible_roles: Mapped[list] = mapped_column(JSON, default=[]) # Which agent roles can see this updated_by: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("users.id")) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now() )