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

128 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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_id``member_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. 索引支持审计查询**
```sql
-- 按用户+门店查询历史对话
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**
```python
# 创建对话记录
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**
```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` 可能占用大量存储,建议制定保留策略