补充安全权限日志与草稿状态约定

This commit is contained in:
talesofzes
2026-06-22 17:30:59 +08:00
parent df0b3fa267
commit a41e2c28d4
19 changed files with 451 additions and 129 deletions
+136
View File
@@ -0,0 +1,136 @@
# 安全权限日志约定
本文件是第一版安全、权限、日志脱敏、回调验签、幂等和访问边界的唯一事实源。涉及这些规则时,代码、接口、测试和 Review 结论应以本文件为准。
本文件不展开完整 RBAC、安全合规体系或审计平台,只卡住最小闭环里 AI 和后端最容易写错的硬规则。
## 1. 核心底线
1. AI 只能生成草稿、追问或回复,不能绕过人工确认直接创建事项、创建提醒或发送通知。
2. 业务权限以平台 `users.role`、启用状态和必要白名单为准;飞书身份只用于登录认证、身份匹配和操作人追溯。
3. 权限必须在 DRF permission class 和 service 层同时校验,不能只靠前端隐藏按钮或飞书卡片按钮。
4. 飞书登录回调、事件回调和卡片回调必须验签;验签失败不得执行业务动作。
5. 通知、飞书事件、卡片点击、草稿转换和提醒调度必须幂等。
6. 密钥、token、完整手机号、完整邮箱、一次性操作 token 和回调验签密钥不得进入普通日志。
7. 权限失败、验签失败、通知失败、回调失败、AI 解析失败、模型失败、未授权机器人访问和调度失败必须可复盘。
## 2. 身份边界
| 身份来源 | 可用于 | 不可用于 |
| --- | --- | --- |
| 平台用户 `users` | 登录态、角色、权限、数据范围 | 自然语言称呼解析 |
| `person_mappings` | 称呼、别名、飞书身份、第一批试用人员映射 | 替代平台登录和角色权限 |
| 飞书 open_id / user_id / union_id | 登录认证、消息接收人、回调操作人追溯 | 直接绕过平台权限 |
| AI 对话记忆表 | 上下文恢复、追问、草稿修订辅助 | 替代正式业务表、权限判断和人工确认 |
同一个真实人员如果可以登录平台,应在 `person_mappings.user_id` 绑定对应 `users.id`。飞书身份同步失败时写入 `failure_records`,不得静默降级成“默认有权限”。
## 3. 角色权限
| 动作 | 老板 | 程经理 | 普通员工 | 管理员 / AI 团队 |
| --- | --- | --- | --- | --- |
| 飞书登录 / 平台登录 | 可用 | 可用 | 可用 | 可用 |
| 飞书机器人私聊 AI 秘书 | 可用 | 不开放 | 不开放 | 仅测试或排查 |
| 确认、取消、补充自己的 AI 草稿 | 可用 | 仅待自己确认的复杂事项 | 不开放 | 仅排查,不代替业务确认 |
| 创建事项 | 可用 | 可用 | 不开放给别人 | 可测试或维护 |
| 创建自己的提醒 | 可用 | 可用 | 可用 | 可用 |
| 给别人创建提醒 | 可用 | 可用 | 不开放 | 可测试或维护 |
| 反馈事项或提醒 | 仅自己相关 | 仅自己相关 | 仅自己作为接收人 | 可测试,不代替业务反馈 |
| 查看失败记录原始信息 | 必要业务摘要 | 必要业务摘要 | 不开放 | 可用 |
| 维护人员映射和提示词版本 | 不开放 | 不开放 | 不开放 | 可用 |
普通员工给别人创建事项或提醒、非接收人反馈、非老板使用机器人入口,都必须拒绝并记录。
## 4. 人工确认边界
1. `task` / `reminder` AI 输出必须先生成可确认草稿。
2. 草稿确认前必须校验发起人、草稿状态、缺失字段、接收人映射和当前有效卡片。
3. `note` / `unknown` / `qa` / `realtime_qa` / `need_more_info` / `unsupported` 不得进入事项、提醒或通知闭环。
4. 复杂事项在老板确认后创建 `tasks.status=pending_manager_confirm` 的事项壳,由程经理补齐接收人、内容并触发通知。
5. 草稿、任务、提醒、通知的状态流转必须走 service 层;非法跳转返回 `state_conflict`
## 5. 飞书安全和幂等
1. 飞书回调必须先验签,再解析和执行业务动作。
2. `feishu_events.event_id` 应尽量唯一;没有稳定 `event_id` 时,用 `operator_open_id + action_value + notification_id + target_id` 生成 `idempotency_key` 并唯一约束。
3. 同一飞书事件只处理一次;重复事件只返回既有处理结果,不重复创建草稿、事项、提醒、反馈或通知。
4. 草稿确认类卡片必须匹配 `ai_drafts.active_card_notification_id`
5. 旧卡片、失效卡片、已取消草稿、已替代草稿、已过期草稿和已转换草稿的回调只记录 `feishu_events`,返回“该卡片已失效,请以最新卡片或平台详情为准”,不得写业务对象。
6. 接收人反馈类卡片重复点击必须幂等;是否覆盖最新反馈状态由 feedback service 明确处理,但每次有效点击都应可追溯。
7. 程经理待确认提醒在飞书里只跳转平台,不通过机器人对话分发事项。
## 6. 通知和操作 token
1. `notifications.idempotency_key` 必须按 `purpose` 生成并设置唯一约束。
2. 草稿确认卡片、程经理确认提醒、事项通知、提醒触发通知和补发通知应使用不同 `purpose`
3. 平台反馈页或一次性操作链接只能保存 token hash,例如 `action_token_hash`,不得保存明文 token。
4. 卡片或操作链接过期时写 `expires_at`,被新卡片替代或业务取消时写 `invalidated_at`
5. `expires_at``invalidated_at` 已生效后,回调不得继续确认、转换、通知或反馈,只能记录事件和提示失效。
## 7. 日志脱敏
普通应用日志、`operation_logs.summary``operation_logs.metadata``failure_records.raw_error` 和列表页摘要不得包含:
1. 阿里百炼 API Key。
2. 飞书 App Secret、tenant access token、user access token。
3. 飞书回调验签密钥。
4. OAuth code 和 OAuth state 的完整值。
5. 平台反馈页一次性操作 token 明文。
6. 完整手机号和完整邮箱。
7. 数据库账号密码和连接串密码。
8. 飞书原始 payload 中的敏感字段。
9. 模型 prompt 中的敏感全文或过长背景库全文。
手机号和邮箱在普通日志中只能脱敏展示。密钥、token、OAuth code/state、一次性操作 token 原文只能存在请求处理内存或安全配置中,不得落普通业务表。
## 8. 访问范围
| 信息 | 普通员工 | 老板 | 程经理 | 管理员 / AI 团队 |
| --- | --- | --- | --- | --- |
| 自己相关事项、提醒、反馈 | 可看摘要 | 可看相关记录 | 可看管理范围 | 可排查 |
| 失败记录列表 | 不可见 | 必要摘要 | 必要摘要 | 可见 |
| `model_call_logs` 原始请求和响应 | 不可见 | 不可见 | 不可见 | 可排查 |
| `feishu_events.raw_payload` | 不可见 | 不可见 | 不可见 | 可排查 |
| 完整手机号、邮箱 | 默认不可见 | 默认脱敏 | 默认脱敏 | 维护页按需可见 |
| 操作 token 明文 | 不可见 | 不可见 | 不可见 | 不可见 |
模型日志和飞书原始 payload 可以为排查保存必要结构,但必须通过接口权限和 Admin 权限限制访问,普通列表页默认只展示摘要。
## 9. 必须写失败记录的情况
1. AI 输出无法解析或不符合 schema。
2. 百炼或模型网关重试后仍失败。
3. PostgreSQL AI 记忆、消息或 BotContext 保存/读取失败。
4. 草稿确认后转换事项或提醒失败。
5. 缺少人员映射且阻断确认。
6. 普通员工越权创建事项或提醒。
7. 非接收人提交反馈。
8. 飞书登录失败、验签失败、事件格式异常或回调处理失败。
9. 飞书通知发送失败或补发失败。
10. 定时提醒触发失败或重复触发被跳过需要留痕。
11. 有问题反馈缺少原因。
如果 AI 解析失败时无法创建最小 `parse_failed` 草稿,`failure_records.target_type` 可以使用 `model_call_log` 并关联对应模型调用日志。
## 10. 必须测试的真实约束
每个 plan 完成前,必须说明新增或修改了哪些测试,以及这些测试覆盖了哪些 spec / contract 约定。第一版至少用测试卡住:
1. 权限:普通员工不能给别人创建事项或提醒。
2. 权限:非接收人不能反馈事项或提醒。
3. AI:AI 输出只能生成草稿,不能绕过人工确认直接执行。
4. AI`note` / `unknown` 不创建事项、提醒或通知。
5. 状态:草稿、事项、提醒不能非法跳转。
6. 飞书:回调必须验签,重复事件和重复点击必须幂等。
7. 飞书:旧卡片或失效卡片只记录事件,不写业务对象。
8. 定时:同一个提醒、同一触发时间、同一接收人、同一渠道不能重复触发通知。
9. 事务:通知失败时不能留下被误判为已通知的业务状态。
10. 日志:密钥、token、完整手机号、完整邮箱和一次性操作 token 不进普通日志。
## 11. 第一版不做
1. 不做复杂组织架构和多级 RBAC。
2. 不做独立审计平台。
3. 不做复杂安全合规体系。
4. 不让 AI 自动操作交易系统、公司历史数据库、后台管理系统或其他外部业务系统。
5. 不把飞书机器人开放为程经理或普通员工通用派活入口。