# 需求文档 ## 简介 本功能为飞书用户提供基于飞书账号身份的安全问答、个人规则、长期记忆、 兴趣偏好和定时推送能力。飞书账号是终端用户权限的唯一来源;内部 API Key 继续用于服务间认证,不得代表或伪造终端用户。 本功能只允许写入平台自身的身份、权限、偏好、订阅、记忆、审计和投递状态。 现有业务 MySQL 必须保持 SELECT-only,不得增加业务数据回写、审批、付款、 绩效定级、交易或其他越权动作。 ## 已确认边界 - 单个飞书应用可以服务一个或多个飞书租户。 - 飞书用户身份使用 `tenant_key + open_id` 唯一确定。 - `union_id` 和飞书 `user_id` 可以作为关联标识,但不得单独作为默认权限主键。 - `chat_id` 只表示会话或群推送目标,不表示用户身份。 - 个人数据默认不共享;公司级规则必须经过管理员权限控制。 - 用户规则和兴趣属于低信任数据,不能覆盖系统安全、只读、权限和审计规则。 - 本阶段不建设终端用户 Web 页面,不同步修改飞书通讯录,也不回写任何业务系统。 ## 需求列表 ### 需求 1:飞书账号身份认证 **用户故事:** 作为飞书用户,我希望系统准确识别我的飞书账号,以便所有问答、 规则和订阅都归属于我本人。 #### 验收条件 1. WHEN 系统收到已经通过飞书验证的 webhook 或长连接消息事件 THEN 系统 SHALL 从事件中提取 `tenant_key` 和发送者 `open_id`,并解析为唯一用户身份。 2. IF 消息事件缺少 `tenant_key`、`open_id` 或未通过飞书来源验证 THEN 系统 SHALL 拒绝执行用户命令,且不得创建任何个人数据。 3. WHEN 一个合法飞书账号首次与机器人交互 THEN 系统 SHALL 为其建立默认普通用户身份, 且不得自动授予管理权限。 4. WHERE 不同租户出现相同 `open_id` THEN 系统 SHALL 将其识别为不同用户。 5. WHEN 系统处理群聊消息 THEN 系统 SHALL 以消息发送者账号作为用户身份,而不是以 `chat_id` 或群成员身份作为用户身份。 6. IF 飞书用户被停用 THEN 系统 SHALL 拒绝其所有受保护命令并记录拒绝审计。 ### 需求 2:基于飞书账号的角色与权限 **用户故事:** 作为管理员,我希望权限绑定到飞书账号,以便普通用户只能操作自己的数据, 而受信任人员才能使用公司级能力。 #### 验收条件 1. WHEN 新飞书用户首次注册 THEN 系统 SHALL 仅授予普通用户角色。 2. WHEN 用户执行命令 THEN 系统 SHALL 根据该飞书身份的有效角色和权限决定是否允许执行。 3. IF 普通用户尝试创建、修改或停用公司级规则 THEN 系统 SHALL 拒绝操作并记录审计。 4. IF 用户尝试访问未授权的公司、项目、财务、风险或审计能力 THEN 系统 SHALL 返回不泄露受保护数据的拒绝响应。 5. WHEN 内部服务管理用户角色或状态 THEN 系统 SHALL 要求有效的内部服务认证, 且角色变更 SHALL 记录操作者、目标飞书用户、变更前后状态和时间。 6. IF 请求正文提供 `actor`、`open_id` 或其他可伪造身份字段 THEN 系统 SHALL 忽略这些字段作为权限依据。 ### 需求 3:个人规则和记忆隔离 **用户故事:** 作为飞书用户,我希望我的规则和历史记忆只影响我自己的回答, 以免其他用户看到或受其影响。 #### 验收条件 1. WHEN 用户创建规则、偏好或 AI 记忆 THEN 系统 SHALL 将记录关联到当前飞书用户所有者。 2. WHEN 系统列出、召回、更新、启停或删除个人规则与记忆 THEN 系统 SHALL 强制按当前用户所有者过滤。 3. IF 用户提交其他用户的数据编号 THEN 系统 SHALL 返回未找到或无权限, 且不得泄露该记录是否存在。 4. WHEN 两个用户保存相同内容 THEN 系统 SHALL 分别保存或去重到各自所有者范围内, 不得复用另一用户的记录。 5. WHEN 用户在群聊中创建个人规则或产生记忆 THEN 系统 SHALL 仍将其仅归属于发送者。 6. WHERE 公司级规则被应用 THEN 系统 SHALL 仅使用已经启用且具有管理员来源的公司规则。 7. WHEN 迁移现有无所有者的规则和记忆 THEN 系统 SHALL 不得把旧数据自动暴露给任意个人; 无法安全归属的数据 SHALL 进入停用或待审状态。 ### 需求 4:个人规则、偏好和兴趣管理 **用户故事:** 作为飞书用户,我希望通过飞书告诉机器人我的规则、表达偏好和兴趣, 并能随时查看或撤销,以便后续交流符合我的要求。 #### 验收条件 1. WHEN 普通用户发送学习规则命令 THEN 系统 SHALL 默认创建个人规则,而不是公司规则。 2. WHEN 有权限的管理员明确发送公司规则命令 THEN 系统 SHALL 创建公司级规则并记录审计。 3. WHEN 用户设置语言、语气、内容详略、关注主题或其他偏好 THEN 系统 SHALL 以结构化个人偏好保存并关联当前用户。 4. WHEN 用户添加或移除兴趣 THEN 系统 SHALL 更新当前用户的兴趣数据, 且现有个人股票自选 SHALL 作为市场兴趣来源之一。 5. WHEN 普通问答中出现语言、语气、详略或内容主题等白名单偏好线索且真实 AI 提供方可用 THEN 系统 SHALL 静默提取并永久保存非敏感偏好;IF 内容涉及密钥、 健康、宗教、政治、性取向、绩效或财务秘密 THEN 系统 SHALL 拒绝保存。 6. WHEN 用户请求查看、启停、修改或删除个人规则与偏好 THEN 系统 SHALL 仅操作当前用户的数据并返回明确结果。 7. IF 用户规则与安全、权限、只读或公司规则冲突 THEN 系统 SHALL 忽略冲突部分并保留审计。 ### 需求 5:个性化 AI 问答 **用户故事:** 作为飞书用户,我希望 AI 根据我的规则、偏好、兴趣和相关记忆回答, 同时不混入其他用户的信息。 #### 验收条件 1. WHEN 用户发起 AI 问答 THEN 系统 SHALL 按当前飞书身份加载公司规则、个人规则、 个人偏好、个人兴趣和当前用户的相关记忆。 2. WHEN 系统组装 AI 上下文 THEN 系统 SHALL 按照“系统安全与只读规则、公司规则、 个人明确规则、当前请求、偏好与兴趣、相关记忆”的优先顺序处理。 3. IF AI 提供方支持会话标识 THEN 系统 SHALL 为不同飞书用户使用隔离的会话标识, 不得复用全局用户会话。 4. IF AI 提供方不可用或仍为占位提供方 THEN 系统 SHALL 返回明确的不可用响应, 不得把占位内容当作真实个性化答案。 5. WHEN 问答来自群聊 THEN 系统 SHALL 回复原会话,但个人规则、偏好和记忆仍只属于发送者。 6. IF 个人规则试图要求调用未授权工具、修改业务数据或绕过安全控制 THEN 系统 SHALL 拒绝执行该要求。 ### 需求 6:个人推送订阅 **用户故事:** 作为飞书用户,我希望按自己的兴趣和时间订阅消息,并能暂停或退订, 以便只收到需要的内容。 #### 验收条件 1. WHEN 用户创建订阅 THEN 系统 SHALL 保存订阅主题、飞书接收身份、计划时间、时区、 安静时段、启用状态和用户同意时间。 2. WHEN 用户未明确创建或同意订阅 THEN 系统 SHALL 不得主动向该用户发送个人推送。 3. WHEN 用户查看订阅 THEN 系统 SHALL 仅返回当前用户的订阅。 4. WHEN 用户暂停、恢复或退订 THEN 系统 SHALL 立即更新当前用户订阅状态并记录审计。 5. IF 用户尝试修改其他用户订阅 THEN 系统 SHALL 拒绝且不泄露目标订阅信息。 6. WHEN 订阅主题支持个人兴趣过滤 THEN 系统 SHALL 使用当前用户明确保存的兴趣生成内容。 7. WHILE 当前时间位于用户安静时段内 THEN 系统 SHALL 延后非紧急推送,不得直接发送。 8. IF 订阅时间、时区、主题或接收目标无效 THEN 系统 SHALL 拒绝创建并返回可操作的错误说明。 9. WHEN 用户以受控中文时间语法创建订阅且解析成功 THEN 系统 SHALL 立即启用订阅, 返回标准化计划、下次执行时间和暂停命令。 10. IF 订阅间隔短于 15 分钟、用户已有 50 个启用订阅或当日投递将超过 96 条 THEN 系统 SHALL 拒绝创建或跳过投递并说明限制。 11. WHEN 普通用户创建订阅 THEN 系统 SHALL 固定绑定其本人 `open_id`; WHEN 管理员在群内创建群订阅 THEN 系统 SHALL 仅绑定当前事件的 `chat_id`, 且 SHALL 拒绝用户手工提供原始 `chat_id`。 ### 需求 7:可靠的个性化定时投递 **用户故事:** 作为订阅用户,我希望消息按时且不重复地送达,并在临时失败后安全重试。 #### 验收条件 1. WHEN 个人订阅到期 THEN 系统 SHALL 通过持久化订阅状态发现任务并生成投递请求, 不得仅依赖进程内临时任务。 2. WHEN 系统发送个人消息 THEN 系统 SHALL 默认使用当前用户的飞书 `open_id` 作为接收目标。 3. WHEN 系统处理同一用户、同一订阅和同一时间窗口 THEN 系统 SHALL 只创建一次有效投递。 4. IF 飞书返回 HTTP 错误、限流响应或非零业务状态码 THEN 系统 SHALL 将投递标记为失败, 不得记录为成功。 5. IF 投递失败属于可重试错误 THEN 系统 SHALL 按受限退避策略重试; 超过最大次数后 SHALL 进入最终失败状态。 6. WHEN 投递成功 THEN 系统 SHALL 保存飞书响应标识、发送时间和最终状态。 7. IF 多个调度器或工作进程同时扫描同一订阅 THEN 系统 SHALL 防止重复生成或重复发送消息。 8. WHILE `READ_ONLY_MODE=true` THEN 系统 SHALL 允许平台自身的订阅与投递状态写入, 但 SHALL 保持旧业务数据库只读。 ### 需求 8:飞书自助命令 **用户故事:** 作为飞书用户,我希望直接通过机器人管理个人规则、偏好和订阅, 无需访问后台页面。 #### 验收条件 1. WHEN 用户请求帮助 THEN 系统 SHALL 返回其当前权限允许使用的命令说明。 2. WHEN 用户管理个人规则 THEN 系统 SHALL 支持创建、查看、修改、启停和删除。 3. WHEN 用户管理偏好或兴趣 THEN 系统 SHALL 支持设置、查看和删除。 4. WHEN 用户管理订阅 THEN 系统 SHALL 支持创建、查看、暂停、恢复和退订。 5. WHEN 管理员执行公司级命令 THEN 系统 SHALL 在执行前验证其飞书账号权限。 6. IF 命令格式错误 THEN 系统 SHALL 返回示例格式,且不得产生部分写入。 7. IF 命令涉及敏感信息、密钥或禁止内容 THEN 系统 SHALL 拒绝保存并给出安全提示。 8. WHEN 管理员通过飞书管理用户角色或状态 THEN 系统 SHALL 只接受当前验证事件中的 结构化 `@用户` 身份,不得接受文本伪造的 `open_id`。 9. IF 操作会停用或降级最后一个有效管理员 THEN 系统 SHALL 拒绝操作。 ### 需求 9:隐私、审计和用户控制 **用户故事:** 作为飞书用户和审计人员,我希望个性化数据受到保护且关键操作可追踪。 #### 验收条件 1. WHEN 系统认证用户、拒绝权限、修改规则、修改偏好、修改订阅或执行投递 THEN 系统 SHALL 记录必要的审计元数据。 2. WHEN 系统记录审计或错误 THEN 系统 SHALL 避免保存访问令牌、密钥和不必要的完整个人问答内容。 3. WHEN 用户请求删除个人画像和记忆 THEN 系统 SHALL 删除或匿名化可删除的个人数据, 停止其订阅,并保留满足审计要求的最小不可逆证据。 4. WHEN 用户请求查看自己的个性化数据 THEN 系统 SHALL 返回其规则、偏好、兴趣和订阅摘要。 5. IF 内部服务查询个人数据 THEN 系统 SHALL 根据服务权限限制数据范围并记录访问审计。 6. WHEN 用户发送“忘记我” THEN 系统 SHALL 返回短时有效的一次性确认码; WHEN 同一用户发送“确认忘记我 <码>”且验证码有效 THEN 系统 SHALL 在一个事务中 删除其个人数据、停用订阅、移除身份映射并将审计主体替换为随机匿名标识。 ### 需求 10:兼容性、迁移与验证 **用户故事:** 作为维护人员,我希望现有固定群推送和内部 API 保持可用, 同时安全升级到飞书用户权限体系。 #### 验收条件 1. WHEN 数据库升级 THEN 系统 SHALL 通过 Alembic 创建身份、权限、偏好、订阅和投递所需结构。 2. WHEN 升级现有数据库 THEN 系统 SHALL 保留已有审计、报表推送和业务只读数据。 3. WHEN 现有固定群定时任务运行 THEN 系统 SHALL 保持原有功能,且不得被误认为个人订阅。 4. WHEN 内部 API 使用 API Key 调用 THEN 系统 SHALL 保持服务级认证, 但不得通过请求参数伪造飞书终端用户权限。 5. WHEN 自动化测试运行 THEN 系统 SHALL 覆盖两个不同飞书用户的数据隔离、 越权拒绝、角色权限、个人问答上下文、订阅生命周期、安静时段、幂等投递、 飞书非零业务码和数据库迁移一致性。 6. WHEN 完整验证运行 THEN Ruff、Python 编译检查、Alembic 元数据一致性测试和全部 pytest 测试 SHALL 通过。