Backend: - Add validate_mapping_database_ownership() to verify source/target UUIDs belong to declared environments before persisting mappings (mappings.py) - Add API-key environment scoping to get_mappings (filter) and suggest_mappings_api (enforce) (mappings.py) - Add user_id Column to TaskRecord model + Alembic migration (task.py) - Persist task.user_id on save, restore on load (persistence.py) - Wire current_user.id into migrate_dashboards + backup_dashboards task creation (_action_routes.py) - Fix test_migration_routes.py: module-level patch leak → autouse fixture, SupersetClient→AsyncSupersetClient, AsyncMock for sync_environment/run - Fix 7 Pydantic serializer warnings: 'PENDING'→TaskStatus.PENDING in test_tasks.py + import TaskStatus Frontend: - Deepen isDryRunResult(): validate selection field, risk.items entries (all 5 fields), and diff object uuids individually (ExecutorModel.svelte.ts) Prior work included: task password redaction, resume ownership checks, canonical dry-run DTO alignment, migration UI callback fixes, credential exposure reduction, assistant dry-run await fix.
77 lines
3.2 KiB
Python
77 lines
3.2 KiB
Python
# #region Alembic.AddAgentLifecycleEvents [C:3] [TYPE Module] [SEMANTICS alembic,agent,lifecycle,audit]
|
|
# @ingroup Alembic
|
|
# @BRIEF Add agent_lifecycle_events table for Phase 3 durable agent lifecycle audit.
|
|
# @LAYER Database
|
|
# @RELATION DEPENDS_ON -> [Models.Agent.AgentLifecycleEvent]
|
|
# @INVARIANT table has composite indexes for common query patterns (user+type+created, conv+type+created).
|
|
# @RATIONALE Immutable, indexed events make trace/conversation diagnostics queryable without
|
|
# keeping raw prompts or tool output in application logs.
|
|
# @REJECTED Reusing agent_messages was rejected — message content has a separate retention and
|
|
# privacy contract and cannot represent request/tool lifecycle boundaries safely.
|
|
|
|
"""add agent_lifecycle_events table
|
|
|
|
Revision ID: b2a3c4d5e6f7
|
|
Revises: 7eaf84b7f6be
|
|
Create Date: 2026-07-15 10:00:00.000000
|
|
"""
|
|
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = "b2a3c4d5e6f7"
|
|
down_revision: Union[str, Sequence[str], None] = "7eaf84b7f6be"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"agent_lifecycle_events",
|
|
sa.Column("id", sa.String(), nullable=False),
|
|
sa.Column("trace_id", sa.String(), nullable=False, index=True),
|
|
sa.Column("conversation_id", sa.String(), nullable=False, index=True),
|
|
sa.Column("user_id", sa.String(), nullable=False, index=True),
|
|
sa.Column("environment_id", sa.String(), nullable=True, index=True),
|
|
sa.Column("event_type", sa.String(), nullable=False, index=True),
|
|
sa.Column("tool_name", sa.String(), nullable=True, index=True),
|
|
sa.Column("status", sa.String(), nullable=True, index=True),
|
|
# Store UTC timestamps explicitly; the model normalizes values to UTC
|
|
# before serialization, independent of the database session timezone.
|
|
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column("elapsed_ms", sa.Float(), nullable=True),
|
|
sa.Column("payload", sa.JSON(), nullable=True),
|
|
sa.Column("error_code", sa.String(), nullable=True, index=True),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index(
|
|
"ix_agent_lifecycle_events_user_type_created",
|
|
"agent_lifecycle_events",
|
|
["user_id", "event_type", "created_at"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
"ix_agent_lifecycle_events_conv_type_created",
|
|
"agent_lifecycle_events",
|
|
["conversation_id", "event_type", "created_at"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
"ix_agent_lifecycle_events_created",
|
|
"agent_lifecycle_events",
|
|
["created_at"],
|
|
unique=False,
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_agent_lifecycle_events_created", table_name="agent_lifecycle_events")
|
|
op.drop_index("ix_agent_lifecycle_events_conv_type_created", table_name="agent_lifecycle_events")
|
|
op.drop_index("ix_agent_lifecycle_events_user_type_created", table_name="agent_lifecycle_events")
|
|
op.drop_table("agent_lifecycle_events")
|
|
# #endregion Alembic.AddAgentLifecycleEvents
|