Files
Neo-ZQYY/docs/prd/Neo_Specs/review-audit/P5.1-NS3-10.md
Neo 6f8f12314f feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本
包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:03:48 +08:00

4.9 KiB
Raw Blame History

P5.1→NS3 缺失项 #10AI 生成内容的审计日志

简要结论

  • 状态: 已解决
  • 风险等级:🟡
  • biz.ai_conversations + biz.ai_messages 两张表已完整记录"谁在什么时候对哪个客户生成了什么",满足审计日志需求

详细审查

审查范围

  • apps/backend/app/ai/conversation_service.py — 对话持久化服务
  • apps/backend/app/services/chat_service.py — Chat 模块服务
  • docs/database/ddl/zqyy_app__biz.sql — biz schema DDL 基线
  • db/zqyy_app/migrations/2026-03-20__rns14_chat_module_extend.sql — Chat 模块扩展迁移
  • apps/backend/app/ai/apps/app5_tactics.py — 典型 App 调用流程(审计写入示例)

发现

审计信息完整记录

1. biz.ai_conversations 表 — 对话级审计

字段 类型 审计用途
id bigint PK 对话唯一标识
user_id varchar(50) NOT NULL :操作用户 ID系统自动调用时为 'system'
nickname varchar(100) 用户昵称
app_id varchar(30) NOT NULL 什么应用app1_chat / app2_finance / ... / app8_consolidation
site_id bigint NOT NULL 哪个门店
source_page varchar(100) 触发来源页面
source_context jsonb 上下文信息(含 assistant_idmember_id 等 → 对哪个客户
context_type varchar(20) 对话关联类型task/customer/coach/general
context_id varchar(50) 关联 IDtaskId/customerId/coachId
title varchar(200) 对话标题
created_at timestamptz 什么时候

2. biz.ai_messages 表 — 消息级审计

字段 类型 审计用途
id bigint PK 消息唯一标识
conversation_id bigint FK 关联对话
role varchar(10) system / user / assistant
content text NOT NULL 生成了什么:完整的 AI 输入和输出内容
tokens_used integer Token 消耗量
reference_card jsonb 引用卡片数据
created_at timestamptz 消息时间戳

3. 写入时机

所有 8 个 AI 应用在每次调用时都通过 ConversationService 写入完整审计链:

create_conversation(user_id, nickname, app_id, site_id, source_context)
  → add_message(role="system", content=prompt)
  → add_message(role="user", content=user_input)
  → 调用百炼 API
  → add_message(role="assistant", content=ai_output, tokens_used=N)

4. 索引支持审计查询

-- 按用户+门店查询历史对话
CREATE INDEX idx_ai_conv_user_site ON biz.ai_conversations (user_id, site_id, created_at DESC);
-- 按应用+门店查询
CREATE INDEX idx_ai_conv_app_site ON biz.ai_conversations (app_id, site_id, created_at DESC);
-- 按上下文查询(客户/任务/助教维度)
CREATE INDEX idx_ai_conv_context ON biz.ai_conversations (user_id, site_id, context_type, context_id, ...);
-- 按对话查询消息
CREATE INDEX idx_ai_msg_conv ON biz.ai_messages (conversation_id, created_at);

证据

App5 审计写入示例app5_tactics.py L240-268

# 创建对话记录
conversation_id = conv_svc.create_conversation(
    user_id=user_id, nickname=nickname,
    app_id=APP_ID, site_id=site_id,
    source_context={"assistant_id": assistant_id, "member_id": member_id},
)
# 写入 system + user 消息
conv_svc.add_message(conversation_id=conversation_id, role="system", content=...)
conv_svc.add_message(conversation_id=conversation_id, role="user", content=...)
# 调用 AI 后写入 assistant 消息
result, tokens_used = await bailian.chat_json(messages)
conv_svc.add_message(
    conversation_id=conversation_id, role="assistant",
    content=json.dumps(result, ensure_ascii=False),
    tokens_used=tokens_used,
)

DDL 基线确认zqyy_app__biz.sql

CREATE TABLE biz.ai_conversations (
    id bigint ... NOT NULL,
    user_id character varying(50) NOT NULL,
    nickname character varying(100) ...,
    app_id character varying(30) NOT NULL,
    site_id bigint NOT NULL,
    source_page character varying(100),
    source_context jsonb,
    context_type character varying(20),
    context_id character varying(50),
    ...
    created_at timestamp with time zone DEFAULT now() NOT NULL
);

CREATE TABLE biz.ai_messages (
    id bigint ... NOT NULL,
    conversation_id bigint NOT NULL,
    role character varying(10) NOT NULL,
    content text NOT NULL,
    tokens_used integer,
    reference_card jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);

建议

审计日志功能已完整实现,以下为可选增强方向(非必须):

  1. 审计查询 API:当前仅有面向用户的历史对话查询(get_conversations可增加面向管理员的审计查询接口按时间范围、app_id、site_id 筛选)
  2. 数据保留策略:当前无自动清理机制,长期运行后 ai_messages.content 可能占用大量存储,建议制定保留策略