feat: add AI suggestion audit trail table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-06 23:12:23 -05:00
parent 4527bfced6
commit cfd6ebff63
3 changed files with 93 additions and 0 deletions

View File

@@ -16,6 +16,7 @@ from app.models.copilot_conversation import CopilotConversation
from app.models.assistant_chat import AssistantChat
from app.models.survey_response import SurveyResponse
from app.models.survey_invite import SurveyInvite
from app.models.ai_suggestion import AISuggestion # noqa: F401
from app.core.config import settings
# this is the Alembic Config object

View File

@@ -0,0 +1,37 @@
"""add ai suggestion table
Revision ID: 052
Revises: 051
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import UUID, JSONB
revision = "052"
down_revision = "051"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.create_table(
"ai_suggestions",
sa.Column("id", UUID(as_uuid=True), primary_key=True),
sa.Column("tree_id", UUID(as_uuid=True), sa.ForeignKey("trees.id", ondelete="CASCADE"), nullable=False),
sa.Column("user_id", UUID(as_uuid=True), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False),
sa.Column("session_id", UUID(as_uuid=True), sa.ForeignKey("ai_chat_sessions.id", ondelete="SET NULL"), nullable=True),
sa.Column("action_type", sa.String(50), nullable=False),
sa.Column("target_node_id", sa.String(255), nullable=True),
sa.Column("changes_json", JSONB, nullable=False, server_default="{}"),
sa.Column("status", sa.String(20), nullable=False, server_default="pending"),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
sa.Column("resolved_at", sa.DateTime(timezone=True), nullable=True),
)
op.create_index("ix_ai_suggestions_tree_id", "ai_suggestions", ["tree_id"])
op.create_index("ix_ai_suggestions_user_id", "ai_suggestions", ["user_id"])
def downgrade() -> None:
op.drop_index("ix_ai_suggestions_user_id", table_name="ai_suggestions")
op.drop_index("ix_ai_suggestions_tree_id", table_name="ai_suggestions")
op.drop_table("ai_suggestions")

View File

@@ -0,0 +1,55 @@
"""AI Suggestion model for tracking AI-applied changes to flows."""
import uuid
from datetime import datetime, timezone
from typing import Optional
from sqlalchemy import DateTime, ForeignKey, String
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
class AISuggestion(Base):
__tablename__ = "ai_suggestions"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
)
tree_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("trees.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
user_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id", ondelete="CASCADE"),
nullable=False,
index=True,
)
session_id: Mapped[Optional[uuid.UUID]] = mapped_column(
UUID(as_uuid=True),
ForeignKey("ai_chat_sessions.id", ondelete="SET NULL"),
nullable=True,
)
action_type: Mapped[str] = mapped_column(
String(50), nullable=False
)
target_node_id: Mapped[Optional[str]] = mapped_column(
String(255), nullable=True
)
changes_json: Mapped[dict] = mapped_column(
JSONB, nullable=False, default=dict
)
status: Mapped[str] = mapped_column(
String(20), nullable=False, default="pending"
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
nullable=False,
)
resolved_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True), nullable=True
)