256 lines
11 KiB
Python
256 lines
11 KiB
Python
"""Add agent audit tables
|
|
|
|
Revision ID: 006_add_agent_tables
|
|
Revises: 5fc1cc05d5d0
|
|
Create Date: 2024-01-15 10:00:00.000000
|
|
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = '006_add_agent_tables'
|
|
down_revision = '5fc1cc05d5d0'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# 创建 agent_tasks 表
|
|
op.create_table(
|
|
'agent_tasks',
|
|
sa.Column('id', sa.String(36), primary_key=True),
|
|
sa.Column('project_id', sa.String(36), sa.ForeignKey('projects.id', ondelete='CASCADE'), nullable=False),
|
|
|
|
# 任务基本信息
|
|
sa.Column('name', sa.String(255), nullable=True),
|
|
sa.Column('description', sa.Text(), nullable=True),
|
|
sa.Column('task_type', sa.String(50), default='agent_audit'),
|
|
|
|
# 任务配置
|
|
sa.Column('audit_scope', sa.JSON(), nullable=True),
|
|
sa.Column('target_vulnerabilities', sa.JSON(), nullable=True),
|
|
sa.Column('verification_level', sa.String(50), default='sandbox'),
|
|
|
|
# 分支信息
|
|
sa.Column('branch_name', sa.String(255), nullable=True),
|
|
|
|
# 排除模式
|
|
sa.Column('exclude_patterns', sa.JSON(), nullable=True),
|
|
|
|
# 文件范围
|
|
sa.Column('target_files', sa.JSON(), nullable=True),
|
|
|
|
# LLM 配置
|
|
sa.Column('llm_config', sa.JSON(), nullable=True),
|
|
|
|
# Agent 配置
|
|
sa.Column('agent_config', sa.JSON(), nullable=True),
|
|
sa.Column('max_iterations', sa.Integer(), default=50),
|
|
sa.Column('token_budget', sa.Integer(), default=100000),
|
|
sa.Column('timeout_seconds', sa.Integer(), default=1800),
|
|
|
|
# 状态
|
|
sa.Column('status', sa.String(20), default='pending'),
|
|
sa.Column('current_phase', sa.String(50), nullable=True),
|
|
sa.Column('current_step', sa.String(255), nullable=True),
|
|
sa.Column('error_message', sa.Text(), nullable=True),
|
|
|
|
# 进度统计
|
|
sa.Column('total_files', sa.Integer(), default=0),
|
|
sa.Column('indexed_files', sa.Integer(), default=0),
|
|
sa.Column('analyzed_files', sa.Integer(), default=0),
|
|
sa.Column('total_chunks', sa.Integer(), default=0),
|
|
|
|
# Agent 统计
|
|
sa.Column('total_iterations', sa.Integer(), default=0),
|
|
sa.Column('tool_calls_count', sa.Integer(), default=0),
|
|
sa.Column('tokens_used', sa.Integer(), default=0),
|
|
|
|
# 发现统计
|
|
sa.Column('findings_count', sa.Integer(), default=0),
|
|
sa.Column('verified_count', sa.Integer(), default=0),
|
|
sa.Column('false_positive_count', sa.Integer(), default=0),
|
|
|
|
# 严重程度统计
|
|
sa.Column('critical_count', sa.Integer(), default=0),
|
|
sa.Column('high_count', sa.Integer(), default=0),
|
|
sa.Column('medium_count', sa.Integer(), default=0),
|
|
sa.Column('low_count', sa.Integer(), default=0),
|
|
|
|
# 质量评分
|
|
sa.Column('quality_score', sa.Float(), default=0.0),
|
|
sa.Column('security_score', sa.Float(), default=0.0),
|
|
|
|
# 审计计划
|
|
sa.Column('audit_plan', sa.JSON(), nullable=True),
|
|
|
|
# 时间戳
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), onupdate=sa.func.now()),
|
|
sa.Column('started_at', sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column('completed_at', sa.DateTime(timezone=True), nullable=True),
|
|
|
|
# 创建者
|
|
sa.Column('created_by', sa.String(36), sa.ForeignKey('users.id'), nullable=False),
|
|
)
|
|
|
|
# 创建 agent_tasks 索引
|
|
op.create_index('ix_agent_tasks_project_id', 'agent_tasks', ['project_id'])
|
|
op.create_index('ix_agent_tasks_status', 'agent_tasks', ['status'])
|
|
op.create_index('ix_agent_tasks_created_by', 'agent_tasks', ['created_by'])
|
|
op.create_index('ix_agent_tasks_created_at', 'agent_tasks', ['created_at'])
|
|
|
|
# 创建 agent_events 表
|
|
op.create_table(
|
|
'agent_events',
|
|
sa.Column('id', sa.String(36), primary_key=True),
|
|
sa.Column('task_id', sa.String(36), sa.ForeignKey('agent_tasks.id', ondelete='CASCADE'), nullable=False),
|
|
|
|
# 事件信息
|
|
sa.Column('event_type', sa.String(50), nullable=False),
|
|
sa.Column('phase', sa.String(50), nullable=True),
|
|
|
|
# 事件内容
|
|
sa.Column('message', sa.Text(), nullable=True),
|
|
|
|
# 工具调用相关
|
|
sa.Column('tool_name', sa.String(100), nullable=True),
|
|
sa.Column('tool_input', sa.JSON(), nullable=True),
|
|
sa.Column('tool_output', sa.JSON(), nullable=True),
|
|
sa.Column('tool_duration_ms', sa.Integer(), nullable=True),
|
|
|
|
# 关联的发现
|
|
sa.Column('finding_id', sa.String(36), nullable=True),
|
|
|
|
# Token 消耗
|
|
sa.Column('tokens_used', sa.Integer(), default=0),
|
|
|
|
# 元数据
|
|
sa.Column('metadata', sa.JSON(), nullable=True),
|
|
|
|
# 序号
|
|
sa.Column('sequence', sa.Integer(), default=0),
|
|
|
|
# 时间戳
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
|
|
)
|
|
|
|
# 创建 agent_events 索引
|
|
op.create_index('ix_agent_events_task_id', 'agent_events', ['task_id'])
|
|
op.create_index('ix_agent_events_event_type', 'agent_events', ['event_type'])
|
|
op.create_index('ix_agent_events_sequence', 'agent_events', ['sequence'])
|
|
op.create_index('ix_agent_events_created_at', 'agent_events', ['created_at'])
|
|
|
|
# 创建 agent_findings 表
|
|
op.create_table(
|
|
'agent_findings',
|
|
sa.Column('id', sa.String(36), primary_key=True),
|
|
sa.Column('task_id', sa.String(36), sa.ForeignKey('agent_tasks.id', ondelete='CASCADE'), nullable=False),
|
|
|
|
# 漏洞基本信息
|
|
sa.Column('vulnerability_type', sa.String(100), nullable=False),
|
|
sa.Column('severity', sa.String(20), nullable=False),
|
|
sa.Column('title', sa.String(500), nullable=False),
|
|
sa.Column('description', sa.Text(), nullable=True),
|
|
|
|
# 位置信息
|
|
sa.Column('file_path', sa.String(500), nullable=True),
|
|
sa.Column('line_start', sa.Integer(), nullable=True),
|
|
sa.Column('line_end', sa.Integer(), nullable=True),
|
|
sa.Column('column_start', sa.Integer(), nullable=True),
|
|
sa.Column('column_end', sa.Integer(), nullable=True),
|
|
sa.Column('function_name', sa.String(255), nullable=True),
|
|
sa.Column('class_name', sa.String(255), nullable=True),
|
|
|
|
# 代码片段
|
|
sa.Column('code_snippet', sa.Text(), nullable=True),
|
|
sa.Column('code_context', sa.Text(), nullable=True),
|
|
|
|
# 数据流信息
|
|
sa.Column('source', sa.Text(), nullable=True),
|
|
sa.Column('sink', sa.Text(), nullable=True),
|
|
sa.Column('dataflow_path', sa.JSON(), nullable=True),
|
|
|
|
# 验证信息
|
|
sa.Column('status', sa.String(30), default='new'),
|
|
sa.Column('is_verified', sa.Boolean(), default=False),
|
|
sa.Column('verification_method', sa.Text(), nullable=True),
|
|
sa.Column('verification_result', sa.JSON(), nullable=True),
|
|
sa.Column('verified_at', sa.DateTime(timezone=True), nullable=True),
|
|
|
|
# PoC
|
|
sa.Column('has_poc', sa.Boolean(), default=False),
|
|
sa.Column('poc_code', sa.Text(), nullable=True),
|
|
sa.Column('poc_description', sa.Text(), nullable=True),
|
|
sa.Column('poc_steps', sa.JSON(), nullable=True),
|
|
|
|
# 修复建议
|
|
sa.Column('suggestion', sa.Text(), nullable=True),
|
|
sa.Column('fix_code', sa.Text(), nullable=True),
|
|
sa.Column('fix_description', sa.Text(), nullable=True),
|
|
sa.Column('references', sa.JSON(), nullable=True),
|
|
|
|
# AI 解释
|
|
sa.Column('ai_explanation', sa.Text(), nullable=True),
|
|
sa.Column('ai_confidence', sa.Float(), nullable=True),
|
|
|
|
# XAI
|
|
sa.Column('xai_what', sa.Text(), nullable=True),
|
|
sa.Column('xai_why', sa.Text(), nullable=True),
|
|
sa.Column('xai_how', sa.Text(), nullable=True),
|
|
sa.Column('xai_impact', sa.Text(), nullable=True),
|
|
|
|
# 关联规则
|
|
sa.Column('matched_rule_code', sa.String(100), nullable=True),
|
|
sa.Column('matched_pattern', sa.Text(), nullable=True),
|
|
|
|
# CVSS 评分
|
|
sa.Column('cvss_score', sa.Float(), nullable=True),
|
|
sa.Column('cvss_vector', sa.String(100), nullable=True),
|
|
|
|
# 元数据
|
|
sa.Column('metadata', sa.JSON(), nullable=True),
|
|
sa.Column('tags', sa.JSON(), nullable=True),
|
|
|
|
# 去重标识
|
|
sa.Column('fingerprint', sa.String(64), nullable=True),
|
|
|
|
# 时间戳
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), onupdate=sa.func.now()),
|
|
)
|
|
|
|
# 创建 agent_findings 索引
|
|
op.create_index('ix_agent_findings_task_id', 'agent_findings', ['task_id'])
|
|
op.create_index('ix_agent_findings_vulnerability_type', 'agent_findings', ['vulnerability_type'])
|
|
op.create_index('ix_agent_findings_severity', 'agent_findings', ['severity'])
|
|
op.create_index('ix_agent_findings_file_path', 'agent_findings', ['file_path'])
|
|
op.create_index('ix_agent_findings_status', 'agent_findings', ['status'])
|
|
op.create_index('ix_agent_findings_fingerprint', 'agent_findings', ['fingerprint'])
|
|
|
|
|
|
def downgrade() -> None:
|
|
# 删除索引和表
|
|
op.drop_index('ix_agent_findings_fingerprint', 'agent_findings')
|
|
op.drop_index('ix_agent_findings_status', 'agent_findings')
|
|
op.drop_index('ix_agent_findings_file_path', 'agent_findings')
|
|
op.drop_index('ix_agent_findings_severity', 'agent_findings')
|
|
op.drop_index('ix_agent_findings_vulnerability_type', 'agent_findings')
|
|
op.drop_index('ix_agent_findings_task_id', 'agent_findings')
|
|
op.drop_table('agent_findings')
|
|
|
|
op.drop_index('ix_agent_events_created_at', 'agent_events')
|
|
op.drop_index('ix_agent_events_sequence', 'agent_events')
|
|
op.drop_index('ix_agent_events_event_type', 'agent_events')
|
|
op.drop_index('ix_agent_events_task_id', 'agent_events')
|
|
op.drop_table('agent_events')
|
|
|
|
op.drop_index('ix_agent_tasks_created_at', 'agent_tasks')
|
|
op.drop_index('ix_agent_tasks_created_by', 'agent_tasks')
|
|
op.drop_index('ix_agent_tasks_status', 'agent_tasks')
|
|
op.drop_index('ix_agent_tasks_project_id', 'agent_tasks')
|
|
op.drop_table('agent_tasks')
|
|
|