mirror of
https://github.com/langgenius/dify.git
synced 2026-07-14 08:57:02 +08:00
docs: add HITL IM docs
This commit is contained in:
281
HITL_PRD_ambiguities.md
Normal file
281
HITL_PRD_ambiguities.md
Normal file
@ -0,0 +1,281 @@
|
||||
# HITL PRD Review
|
||||
|
||||
Verdict: Fail
|
||||
|
||||
这份 PRD 还没有达到可直接进入实现的状态。主要问题不是“功能点不够多”,而是几个关键对象和边界还没有收敛:
|
||||
|
||||
- 现有实现的核心对象是 `HumanInputForm` / `HumanInputDelivery` / `HumanInputFormRecipient`,而 PRD 讨论的是 `Contact` / `Human Roster` / `Recipient` / `HITL task` / `Delivery Record` / `Recipient Resolution Record`。以下评审按 `HITL task == form` 理解。
|
||||
- 当前运行时只有 `webapp` 和 `email` 两类 delivery method;PRD 已经把 IM、审计、URL 鉴权、组织级通讯录、跨 workspace 联系人、通知中心一起拉进来了。
|
||||
- PRD 内部对“谁是 approver、谁能打开链接、哪些变化影响 pending task、dynamic email 要不要反查 member”等规则还存在直接冲突。
|
||||
|
||||
以下结论基于我对当前实现的阅读,重点参考:
|
||||
|
||||
- `api/models/human_input.py`
|
||||
- `api/core/repositories/human_input_repository.py`
|
||||
- `api/core/workflow/human_input_adapter.py`
|
||||
- `api/services/human_input_service.py`
|
||||
- `api/controllers/web/human_input_form.py`
|
||||
- `api/tasks/mail_human_input_delivery_task.py`
|
||||
- `web/app/components/workflow/nodes/human-input/types.ts`
|
||||
- `web/app/components/workflow/nodes/human-input/default.ts`
|
||||
- `web/app/components/workflow/nodes/human-input/components/delivery-method/email-configure-modal.tsx`
|
||||
- `web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/index.tsx`
|
||||
|
||||
## Blocking Issues
|
||||
|
||||
### 1. `HITL task == form` 这个前提需要在 PRD 中显式写清,否则研发实现时仍会歧义
|
||||
|
||||
- PRD 位置:`10.1`、`11.1`、`16.*`、`17.*`
|
||||
- 当前实现:运行时实体是 `HumanInputForm`,子实体是 `HumanInputDelivery` 和 `HumanInputFormRecipient`,表单状态是 `WAITING` / `SUBMITTED` / `TIMEOUT` / `EXPIRED`。
|
||||
- 问题:
|
||||
- 按当前约束,我将 `task` 直接理解为 `form`;但 PRD 正文没有把这个等价关系写死。
|
||||
- `delivery_records`、`recipient_resolution_records`、`allowed_approvers`、`notified_recipients` 也都被当成 task 字段提出,但没有和现有表、现有 token 模型做映射。
|
||||
- 如果这层术语不在 PRD 里显式固定,后面的迁移、API 路由、日志、鉴权仍然容易被不同研发解释成“新增 task 聚合”。
|
||||
- 需要补齐:
|
||||
- 在术语定义处显式写明:`HITL task` 是产品术语,对应实现层的 `HumanInputForm`。
|
||||
- 给出一张对象映射表:`task(form)/delivery/recipient/contact` 各自是什么、谁持久化、谁是运行时快照。
|
||||
|
||||
### 2. PRD 当前写的是“原地改造旧 Human Input 节点”,但你说明实际方案是“引入新节点”
|
||||
|
||||
- PRD 位置:`5.4`、`8.*`、`11.1`
|
||||
- 当前实现:
|
||||
- 节点存储主结构是 `delivery_methods[]`。
|
||||
- Email 配置里包含 `recipients / subject / body / debug_mode`。
|
||||
- 当前支持 `webapp`、`email`,并且 Email 配置里还有 `whole_workspace`。
|
||||
- 问题:
|
||||
- PRD `5.0` 明确写的是“对现有 Human Input 节点进行原地改造”“旧 Human Input 节点升级为 HITL 2 的配置结构”“旧 workflow DSL 需要保持兼容”。
|
||||
- 你现在给出的真实方案是:引入一套新的节点配置模型,只复用表单相关的 `inputs` / `actions` 定义,老代码兼容性不是主要问题。
|
||||
- 这意味着当前 PRD 的节点策略、迁移策略、回滚策略和兼容性表述都需要重写;否则研发会按“原地升级旧节点”去做错误拆分。
|
||||
- 需要补齐:
|
||||
- 在 PRD 中显式写明:这是一个新节点,不是旧 `Human Input` 节点的原地升级。
|
||||
- 明确新节点的 node type、DSL schema、前端入口、后端 runtime path。
|
||||
- 同步清理或重写 `5.0`、`11.3`、`11.4` 里所有建立在“升级旧节点”前提上的描述。
|
||||
|
||||
### 3. URL 鉴权设计和当前实现的安全模型正面冲突
|
||||
|
||||
- PRD 位置:`17.*`
|
||||
- 当前实现:
|
||||
- `api/controllers/web/human_input_form.py` 里 Web 表单接口当前是未鉴权的 token access。
|
||||
- 注释直接写了 `this endpoint is unauthenticated on purpose for now`。
|
||||
- GET/POST 只要拿到 `form_token` 就能访问或提交。
|
||||
- 问题:
|
||||
- PRD 明确说 URL 不能代表审批权限,打开和提交都要校验访问者身份。
|
||||
- 这不只是“小改鉴权逻辑”,而是现有 Web form 交互范式的根本变化。
|
||||
- PRD 没说明哪些 recipient type 还能继续 token-only,哪些必须登录、OTP、Magic Link 或 IM identity。
|
||||
- 需要补齐:
|
||||
- 按 recipient type 给出访问校验矩阵。
|
||||
- 明确“打开页”和“提交表单”两次校验各自依赖什么证据。
|
||||
- 明确历史旧 token 的兼容策略和失效策略。
|
||||
|
||||
### 4. `dynamic email` 的 canonicalization 规则前后冲突
|
||||
|
||||
- PRD 位置:`8.3`、`7.5`、`18.6`
|
||||
- 当前实现:
|
||||
- Email recipient 当前只分 `member` 和 `external`,并按 workspace member / external email 构造 recipient。
|
||||
- 问题:
|
||||
- `8.3` 写的是:动态 Email 不反查 member,只按 Email recipient 处理。
|
||||
- `18.6` 又写:如果 dynamic Email 和已有 workspace member email 相同,应优先匹配已有联系人,以获得更强身份校验。
|
||||
- `7.5` 又强调:如果 Email 能匹配 Dify Account,不允许创建 external contact。
|
||||
- 这三条组合起来,dynamic email 到底是“永远按裸 email”还是“尽可能升级成 account/contact”,现在是冲突的。
|
||||
- 需要补齐:
|
||||
- 为 `dynamic email` 单独定义 resolution pipeline。
|
||||
- 明确它的 canonical key、审计身份、通知行为、鉴权行为是否允许升级成 account/contact。
|
||||
|
||||
### 5. `Current Initiator` 的身份模型没有闭环
|
||||
|
||||
- PRD 位置:`8.5`、`17.3`、`18.6`
|
||||
- 当前实现:
|
||||
- 现有 recipient type 里有 `STANDALONE_WEB_APP`、`CONSOLE`、`BACKSTAGE`、`EMAIL_MEMBER`、`EMAIL_EXTERNAL`。
|
||||
- `HumanInputService` 提交时只记录 `submission_user_id` 或 `submission_end_user_id`。
|
||||
- 问题:
|
||||
- PRD 同时提到 WebApp 发起者、CLI/API 调用方、匿名 WebApp session、明确 caller identity。
|
||||
- 但没有定义 initiator 到底是 `account`、`end_user`、`session`、`API key owner` 还是一个新的 identity union。
|
||||
- 也没有定义它在 allowed approver 去重、审计、URL 鉴权、重复提交判定里用哪个 key。
|
||||
- 需要补齐:
|
||||
- 先定义 initiator identity schema。
|
||||
- 再定义它如何参与 recipient canonicalization 和 submit authorization。
|
||||
|
||||
### 6. 部署形态实际上是两套模型,但 PRD 还没有把这两套模型写清
|
||||
|
||||
- PRD 位置:`4.*`、`6.2`、`6.5`、`14.2`、`18.4`
|
||||
- 问题:
|
||||
- 按你最新给出的前提,部署并不是三套完全独立模型,而是两套:
|
||||
- `CE / EE` 共用一套模型。
|
||||
- `SaaS` 使用另一套模型。
|
||||
- 但当前 PRD 还是把 `CE`、`EE`、`SaaS` 混在同一层叙述,导致阅读者很难判断哪些规则是共模,哪些是 SaaS 特有规则。
|
||||
- 例如:
|
||||
- `4.1` 的 SaaS 凭据作用域是 tenant/workspace 级。
|
||||
- `6.2` 和 `18.4` 的企业版描述更接近 deployment-level / workspace-override 模型。
|
||||
- `6.5` 虽然标注本期不做,但它实际上属于 `CE / EE` 这一套模型的扩展能力,而不应和 SaaS 放在同一层讨论。
|
||||
- 为什么是阻塞:
|
||||
- 这决定了 IM integration 配在哪里、表怎么分 tenant/workspace/deployment、回调 URL 怎么生成、权限由谁持有。
|
||||
- 如果 PRD 不先把“哪条规则属于 `CE/EE`,哪条属于 `SaaS`”标出来,研发实现时仍然会把本来应该分叉的规则揉在一起。
|
||||
- 需要补齐:
|
||||
- 先在 PRD 中显式声明:部署策略只有两套模型,`CE/EE` 一套,`SaaS` 一套。
|
||||
- 给出两张矩阵,或者一张带 `model_family` 列的矩阵:
|
||||
- `CE/EE`:渠道、配置入口、凭据作用域、是否支持 override。
|
||||
- `SaaS`:渠道、安装方式、tenant/workspace 作用域、ISV/自建边界。
|
||||
- 明确本期是否允许“同一部署启用多个 IM 渠道”,并分别说明该结论是否对 `CE/EE` 与 `SaaS` 同时成立。
|
||||
|
||||
### 7. IM 能力矩阵是空表,但大量规则依赖它
|
||||
|
||||
- PRD 位置:`9.2`、`17.3`、`18.5`
|
||||
- 问题:
|
||||
- PRD 频繁依赖“可在 IM 内取身份”“可卡片内审批”“可通讯录同步”“否则 fallback URL”。
|
||||
- 但 `18.5` 的能力矩阵几乎是空的。
|
||||
- 在没有矩阵的情况下,`IM binding`、`callback`、`identity proof`、`fallback auth` 都无从落地。
|
||||
- 需要补齐:
|
||||
- 至少先填完本期声称支持的渠道:Slack、钉钉、飞书/Lark、Teams、企业微信。
|
||||
- 每个渠道要明确:是否能取用户身份、是否能卡片提交、是否只支持链接跳转、是否能拉通讯录。
|
||||
|
||||
### 8. `pending task` 在联系人变化后的行为没有统一规则
|
||||
|
||||
- PRD 位置:`17.2`、`17.4`、`18.2`、`18.9`
|
||||
- 问题:
|
||||
- 一处说提交时要重新校验成员仍在 workspace、IM binding 仍有效。
|
||||
- 一处说历史 task 保留 snapshot,pending task 默认重新校验。
|
||||
- 另一处又提“转为 external contact”“保留旧 IM snapshot”“是否允许旧链接继续审批,需要确认”。
|
||||
- 这会直接影响 submit 判定、通知补发、审计解释。
|
||||
- 需要补齐:
|
||||
- 给出一张变更影响真值表,至少覆盖:
|
||||
- member 离开 workspace
|
||||
- account disabled
|
||||
- external contact 删除
|
||||
- IM binding 修改/删除
|
||||
- recipient email 修改
|
||||
- credential rotation
|
||||
- 每种变化要分别说明:历史 task、pending task、新 task 的行为。
|
||||
|
||||
### 9. Debug 行为定义和现有实现不一致
|
||||
|
||||
- PRD 位置:`8.6`、`10.5`
|
||||
- 当前实现:
|
||||
- Email config 里已经有 `debug_mode`,且是 channel-level 配置。
|
||||
- Debug preview / single-run 路径已经存在。
|
||||
- 问题:
|
||||
- PRD 把它提成 node-level `Only notify me during debug`,但没说明:
|
||||
- 是否覆盖 webapp / email / IM 全部渠道;
|
||||
- 是否仍创建真实 form/task;
|
||||
- audit 和 delivery record 是否记录“原计划对象”与“debug 替换对象”。
|
||||
- 需要补齐:
|
||||
- 明确 debug recipient rewrite 的作用域、日志规则和 snapshot 行为。
|
||||
|
||||
### 10. 审计日志与运行日志边界不清晰
|
||||
|
||||
- PRD 位置:`10.*`、`16.*`
|
||||
- 问题:
|
||||
- `10.*` 关注 Last Run / Debug 可见性。
|
||||
- `16.*` 又要求能回答“谁、什么时候、通过什么身份验证、填了什么、为什么被允许或拒绝”。
|
||||
- 但 `16.2` 的“访问与身份校验信息”又写了“可能不需要审计日志记录”。
|
||||
- 这和审计目标本身冲突。
|
||||
- 需要补齐:
|
||||
- 明确哪些字段属于用户可见运行日志,哪些属于审计日志,哪些只保留数据库不可在 UI 暴露。
|
||||
- 明确敏感字段脱敏规则,否则“记录原始 dynamic email 值”和“最小化暴露”也会冲突。
|
||||
|
||||
### 11. 后台权限矩阵完全缺失
|
||||
|
||||
- PRD 位置:`5.1`、`5.2`、`5.3`、`6.*`、`7.*`、`18.10`
|
||||
- 问题:
|
||||
- 谁能看 Contact Directory。
|
||||
- 谁能看完整 Human Roster。
|
||||
- 谁能添加其他 workspace member。
|
||||
- 谁能添加 external contact。
|
||||
- 谁能配 IM credential。
|
||||
- 谁能改 IM binding / override。
|
||||
- 这些都没有定。
|
||||
- 为什么是阻塞:
|
||||
- 没有权限矩阵,就没法设计 controller、service 和数据查询范围。
|
||||
|
||||
## Non-blocking Issues
|
||||
|
||||
### 1. `8.7 节点预览(不确定)` 仍是占位
|
||||
|
||||
- 这是 UI 细节,不阻塞后端对象建模。
|
||||
- 但它现在混在正式章节里,容易让评审误以为已定稿。
|
||||
|
||||
### 2. `12.3 通知中心` 只给了方向,没有边界
|
||||
|
||||
- 说“可优先考虑提供接口”,但没有明确是否本期内要有 API contract。
|
||||
- 建议要么移到后续专题,要么明确只预留领域对象,不出用户接口。
|
||||
|
||||
### 3. `16` 和 `18.11` 对指标/guardrail 基本没有落地定义
|
||||
|
||||
- 已经意识到 abuse 风险,但没有最小阈值、限流对象、失败告警口径。
|
||||
- 这会让 SaaS 风控落在实现阶段临时补洞。
|
||||
|
||||
### 4. `6.3 IM identity` 章节信息量过低
|
||||
|
||||
- “具体参数待确定”基本等于还没设计。
|
||||
- 如果本期真的要支持多个 IM provider,这一节至少需要一个最小 schema。
|
||||
|
||||
### 5. `10.4` 的节点失败规则没有和 pause/resume 状态机对齐
|
||||
|
||||
- “全部 recipient 都无法通知时节点报错”是产品结论。
|
||||
- 但没有定义它发生在 form/task 创建前、创建后、部分渠道失败但仍有 webapp token 时的处理顺序。
|
||||
|
||||
### 6. `11.3` / `11.4` 迁移章节和“新节点方案”不一致
|
||||
|
||||
- 如果采用新节点方案,现有迁移章节就不能再默认按“旧节点升级到新节点”来写。
|
||||
- 这部分不一定需要复杂迁移设计,但至少要明确:
|
||||
- 旧节点继续存在还是隐藏;
|
||||
- 新旧节点能否并存;
|
||||
- 是否需要任何自动迁移;
|
||||
- 发布后旧 workflow 的编辑与运行策略。
|
||||
|
||||
## Vague Language
|
||||
|
||||
以下表述需要收紧,否则实现时会被不同团队各自解释:
|
||||
|
||||
- `支持为联系人绑定一个 IM 身份`
|
||||
- 问题:是手动输入、搜索选择、同步导入,还是都支持?
|
||||
|
||||
- `默认通过 IM + Email 双渠道触达`
|
||||
- 问题:是所有 recipient 都双发,还是仅“可映射到 contact 且具备两种渠道”的人双发?
|
||||
|
||||
- `若调用方有明确身份,可作为 allowed approver`
|
||||
- 问题:什么叫“明确身份”?API key owner、end_user、session、SSO subject 都算吗?
|
||||
|
||||
- `需要记录额外的审计信息`
|
||||
- 问题:额外到什么程度?字段范围、查询权限、保留周期都没定义。
|
||||
|
||||
- `如果 IM 支持在应用内获取当前用户身份`
|
||||
- 问题:哪些 IM 支持、支持到什么粒度、是否可作为强身份凭据,都没定。
|
||||
|
||||
- `帮助排错`
|
||||
- 问题:需要对谁可见、保留多久、是否脱敏,没有约束。
|
||||
|
||||
## Missing Scenarios
|
||||
|
||||
当前 PRD 对以下场景缺少明确规则:
|
||||
|
||||
- 同一个人同时以 `workspace member`、`dynamic email`、`current initiator` 三种来源命中时如何去重。
|
||||
- 一个 `dynamic email` 同时命中多个联系人,或命中一个 disabled account 时如何处理。
|
||||
- IM 已送达、Email 发送失败,但 Web form 仍可打开时,task/form 是否继续等待。
|
||||
- 用户在打开表单后离开 workspace,再提交时的报错文案和状态变化。
|
||||
- `external contact` 被删除后,已经打开过页面但尚未提交的浏览器会话如何处理。
|
||||
- 文件上传表单在 external recipient 场景下如何鉴权,上传 token 是否绑定 recipient identity。
|
||||
- Email OTP / Magic Link 的重放、防爆破、重试次数、锁定策略。
|
||||
- 部分 recipient 解析成功、部分解析失败时,通知对象列表和 allowed approver 列表谁是审计真相来源。
|
||||
- Debug run 替换通知对象后,是否允许被替换掉的原 recipient 仍通过历史链接提交。
|
||||
- CLI/API 发起但无 end_user identity 时,`Allow Current Initiator to Approve` 是否应自动失效。
|
||||
|
||||
## Recommended Next Step
|
||||
|
||||
建议不要继续往 UI 文案和页面草图细化。先在 PRD 开头补一段“节点策略声明”:这是一个新节点,只复用表单 `inputs` / `actions` 定义,不做旧 `Human Input` 节点的原地升级。然后再冻结下面 5 份规则表:
|
||||
|
||||
1. 对象模型表
|
||||
- `Contact / Roster / Recipient / Task(form) / DeliveryRecord / ResolutionRecord` 的边界和映射。
|
||||
|
||||
2. Recipient resolution + canonicalization 表
|
||||
- 每种来源如何解析、如何去重、最终产生什么 approver identity。
|
||||
|
||||
3. 状态机表
|
||||
- `pending / submitted / timeout / expired / canceled / delivery_failed` 与现有 `HumanInputFormStatus` 的对应关系。
|
||||
|
||||
4. 访问控制矩阵
|
||||
- 打开页与提交时,按 recipient type 和 channel 列出必须满足的身份校验条件。
|
||||
|
||||
5. 部署/渠道能力矩阵
|
||||
- 每个部署形态、每个 IM 渠道的配置入口、凭据作用域、身份能力、卡片能力、fallback 策略。
|
||||
|
||||
在这 5 张表定下来之前,直接开始改节点 UI 或设计数据库,很容易做出一版内部自相矛盾的实现。
|
||||
369
docs/design/human-in-the-loop/hitl-contact-im-domain-model.md
Normal file
369
docs/design/human-in-the-loop/hitl-contact-im-domain-model.md
Normal file
@ -0,0 +1,369 @@
|
||||
# HITL Approval Domain, Contact And IM Domain Model
|
||||
|
||||
## 背景
|
||||
|
||||
HITL 二期需要在 CE、EE、SaaS 三种部署形态下统一处理联系人、Human Roster、IM 绑定、IM 凭据和运行时审批人解析。
|
||||
|
||||
核心张力来自企业边界不同:
|
||||
|
||||
| 形态 | 物理部署 | 真实企业边界 | Workspace 语义 |
|
||||
| --- | --- | --- | --- |
|
||||
| SaaS | 多个企业共用一个 Dify 部署 | 一个 `Tenant` / workspace 通常就是一个 SMB 企业 | 企业本身 |
|
||||
| CE | 一个部署对应一个企业 | deployment | 单 workspace facade |
|
||||
| EE | 一个部署对应一个企业 | deployment | 企业内部门、团队或业务单元 |
|
||||
|
||||
因此不要让运行时直接判断 CE / EE / SaaS。领域层应先抽象出稳定的业务边界,再用策略对象处理部署形态差异。
|
||||
|
||||
## 直接结论
|
||||
|
||||
先引入 `ApprovalDomain` 作为产品层和应用层主抽象。它表示一次 HITL 配置与运行所属的审批域,用来统一回答:
|
||||
|
||||
- 当前 workflow 可以从哪个联系人目录和 Human Roster 选择审批人。
|
||||
- 其他 workspace 的 Dify member 是否在当前审批域内可见。
|
||||
- External contact 由谁管理,workflow editor 是否能创建。
|
||||
- IM identity 和 IM app credential 应如何解析。
|
||||
- 提交时如何校验身份、当前成员状态和 binding 状态。
|
||||
- 审计时按哪个组织边界解释“谁审批了什么”。
|
||||
|
||||
`workspace_id (tenant_id)` 只应作为系统入口 locator:controller、现有 DB 存储、迁移和 adapter 可以使用它;进入应用服务后,应先解析为 `ApprovalDomainContext`,后续领域接口优先传 `ApprovalDomainContext`、`ContactDirectoryId`、`HumanRosterId`、`HITLTaskId` 等业务对象,而不是继续层层传 `workspace_id`。
|
||||
|
||||
当前 SaaS 没有“一个企业多个 workspace”的产品计划,因此不建议现在新建 `approval_domains` 表。`ApprovalDomain` 可以先由 `ApprovalDomainResolver` 从 workspace locator 和部署形态推导出来;如果未来 SaaS 需要一个企业多个 workspace,再将 `ApprovalDomain` 或其背后的企业边界持久化。
|
||||
|
||||
这样保留产品语言的一致性,同时避免把 CE / EE / SaaS 差异泄漏到 Contact、Roster、Recipient、Task 的核心模型中。
|
||||
|
||||
## 领域划分
|
||||
|
||||
| Bounded Context | 职责 | 不负责 |
|
||||
| --- | --- | --- |
|
||||
| Identity Context | 对齐 `Account`、`TenantAccountJoin`、账号状态和 workspace 成员关系 | 发送通知 |
|
||||
| Approval Domain Context | 解析当前审批域、联系人目录、Human Roster、IM 集成策略和授权策略 | 发送通知 |
|
||||
| Contact Directory Context | 管理审批域内可见的 Dify account-backed contact 和 IM identity binding | HITL task 生命周期 |
|
||||
| Roster Context | 管理当前审批域下可选择的联系人集合、external contact、成员离开后的可选择状态 | IM 凭据存储 |
|
||||
| IM Integration Context | 管理 IM provider、app installation、credential owner、IM identity binding、通讯录同步 | 表单提交 |
|
||||
| HITL Runtime Context | 从节点配置解析 recipients,创建 task 快照,发送通知,校验提交人 | 管理联系人目录 |
|
||||
| Audit Context | 记录解析、投递、访问、提交、拒绝和敏感数据处理策略 | 决定业务权限 |
|
||||
|
||||
## 核心对象
|
||||
|
||||
### Approval Domain
|
||||
|
||||
| 对象 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `ApprovalDomain` | Product Concept | 审批域。产品和应用服务讨论“谁可被通知、谁可提交、用哪套集成能力”的主语。 |
|
||||
| `ApprovalDomainContext` | Application Context | 由 resolver 生成的运行时上下文,聚合联系人目录、Human Roster、IM 集成和授权策略。 |
|
||||
| `ContactDirectoryId` | Value Object | 当前审批域可见的联系人目录引用。 |
|
||||
| `HumanRosterId` | Value Object | 当前审批域下 workflow editor 可选择的联系人集合引用。 |
|
||||
| `IMIntegrationPolicy` | Value Object | 当前审批域解析 IM provider、installation、credential chain 和 channel capability 的策略。 |
|
||||
| `RosterPolicy` | Value Object | 当前审批域的 roster 初始化、添加、可选择和成员离开处理规则。 |
|
||||
| `AuthorizationPolicy` | Value Object | 当前审批域打开、提交和 pending task 再校验规则。 |
|
||||
| `AuditPolicy` | Value Object | 当前审批域审计字段、脱敏和保留策略。 |
|
||||
|
||||
`ApprovalDomainContext` 是代码中主要传递的上下文。它可以包含底层 owner / locator,但这些细节不应扩散到普通领域服务。
|
||||
|
||||
推荐形态:
|
||||
|
||||
```text
|
||||
ApprovalDomainContext
|
||||
id
|
||||
contact_directory_id
|
||||
human_roster_id
|
||||
im_integration_policy
|
||||
roster_policy
|
||||
authorization_policy
|
||||
audit_policy
|
||||
```
|
||||
|
||||
内部实现仍然需要知道当前目录或凭据来自 workspace、deployment、ISV application 还是 tenant self-built app。但这些应封装在 resolver、repository adapter 或 policy 内部,避免让业务代码到处传底层 owner / locator。
|
||||
|
||||
当前映射建议:
|
||||
|
||||
| 形态 | `ApprovalDomain` 入口 | Contact Directory owner | Human Roster owner | IM credential policy |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| SaaS | 当前 `Tenant` / workspace | 当前 `Tenant` | 当前 `Tenant` | Slack ISV workspace installation 或 tenant self-built app |
|
||||
| CE | 默认 workspace facade | deployment | 默认 `Tenant` | deployment 或 default workspace facade |
|
||||
| EE | 当前 workspace 的审批域 | deployment | 当前 `Tenant` | 默认 deployment-level,未来可 workspace override |
|
||||
|
||||
### Contact Directory
|
||||
|
||||
| 对象 | 类型 | 聚合边界 | 关键字段 |
|
||||
| --- | --- | --- | --- |
|
||||
| `ContactDirectory` | Aggregate Root | `ApprovalDomain` | `id`、`owner_ref`、`visibility_policy` |
|
||||
| `ContactIdentity` | Entity | `ContactDirectory` | `id`、`directory_id`、`kind`、`account_id`、`external_contact_id`、`normalized_email`、`display_name`、`status` |
|
||||
| `ExternalContact` | Entity | `HumanRoster` | `id`、`roster_id`、`normalized_email`、`display_name`、`status` |
|
||||
| `IMIdentityBinding` | Entity | `ContactIdentity` | `id`、`contact_identity_id`、`provider`、`provider_user_id`、`binding_owner_ref`、`status`、`verified_at` |
|
||||
|
||||
建模原则:
|
||||
|
||||
- 只要能匹配到 Dify `Account`,就必须建模为 account-backed `ContactIdentity`,不能建模为 `ExternalContact`。
|
||||
- 其他 workspace 的 member 仍是 Dify member,只是当前审批域里“不属于当前 roster owner”的 account-backed contact。
|
||||
- `ExternalContact` 只表示不属于 Dify 系统内 `Account` 的外部人员,并且只属于当前 Human Roster。
|
||||
- Workflow editor 不能创建 `ExternalContact`;编辑节点时只能选择已有 roster entry 或输入 one-time email。
|
||||
- 当前产品只允许一个联系人绑定一个 IM 身份,但数据模型不应假设永远只有一个 provider;唯一约束应放在 active binding 的策略上。
|
||||
|
||||
### Human Roster
|
||||
|
||||
| 对象 | 类型 | 聚合边界 | 关键字段 |
|
||||
| --- | --- | --- | --- |
|
||||
| `HumanRoster` | Aggregate Root | `ApprovalDomain` | `id`、`owner_ref`、`policy` |
|
||||
| `RosterEntry` | Entity | `HumanRoster` | `id`、`roster_id`、`contact_identity_id`、`entry_kind`、`status`、`joined_at`、`snapshot` |
|
||||
|
||||
`RosterEntry.id` 是 HITL 节点静态 recipient 应保存的稳定引用。产品和 API 可以称为 `contact_id`,但领域语义上它是“当前 Human Roster 中的可选择联系人”,不是全局人。
|
||||
|
||||
`entry_kind` 是面向当前 Human Roster 的视图:
|
||||
|
||||
| `entry_kind` | 语义 |
|
||||
| --- | --- |
|
||||
| `workspace_member` | `Account` 当前属于该 Human Roster 的 owner workspace |
|
||||
| `dify_member` | `Account` 属于当前审批域的 Contact Directory,但不属于当前 roster owner |
|
||||
| `external_contact` | 当前 Human Roster 下的外部联系人 |
|
||||
|
||||
`status` 至少需要区分:
|
||||
|
||||
| `status` | 是否可被新节点选择 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `active` | 是 | 可通知、可审批 |
|
||||
| `left_workspace` | 否 | 曾是 workspace member,已离开但保留历史引用 |
|
||||
| `account_disabled` | 否 | 账号被禁用或删除 |
|
||||
| `removed` | 否 | 被管理员从 roster 移除 |
|
||||
| `pending_review` | 否 | 需要管理员处理,例如成员离开后选择移除或转 external |
|
||||
|
||||
### IM Integration
|
||||
|
||||
| 对象 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `IMProvider` | Value Object | Slack、DingTalk、Lark、Teams、WeCom、Email |
|
||||
| `IMProviderApplication` | Aggregate Root | IM app registration。SaaS ISV 的 `app_id` / `app_secret` 属于部署者;企业自建 app 属于 workspace 或 enterprise。 |
|
||||
| `IMInstallation` | Aggregate Root | 某个 provider 在某个 owner 下的可用安装。运行时从这里得到可发送能力和 credential handle。 |
|
||||
| `IMCredentialHandle` | Value Object | Secret store 中的引用,不直接暴露 secret。 |
|
||||
| `IMChannelCapability` | Value Object | 是否支持卡片审批、fallback URL、平台身份获取、通讯录同步等。 |
|
||||
|
||||
IM identity 一期通过 directory sync / search 选择 provider user,不支持让管理员直接手动输入 provider user id。这个决定影响产品交互和 provider gateway 能力要求,但不改变 `IMIdentityBinding` 的领域模型。
|
||||
|
||||
凭据解析优先级由 `IMIntegrationPolicy` 给出,运行时只调用 resolver,不直接判断 owner 类型。默认顺序为:
|
||||
|
||||
1. `workspace` / `tenant` scoped installation。
|
||||
2. `enterprise` / `deployment` scoped installation。
|
||||
3. no IM installation,降级到 Email。
|
||||
|
||||
不同形态只影响 installation 的来源:
|
||||
|
||||
| 场景 | `IMProviderApplication` owner | `IMInstallation` owner |
|
||||
| --- | --- | --- |
|
||||
| SaaS Slack ISV | deployment operator | workspace OAuth installation |
|
||||
| SaaS DingTalk self-built | workspace admin | workspace |
|
||||
| CE | deployment operator 或 default workspace admin | deployment 或 workspace facade |
|
||||
| EE | enterprise admin | deployment / enterprise,本期默认 deployment |
|
||||
|
||||
### HITL Runtime
|
||||
|
||||
| 对象 | 类型 | 现有模型映射 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `NotificationPolicy` | Value Object | `HumanInputNodeData` extension | 节点配置中的通知策略。 |
|
||||
| `RecipientSelector` | Value Object | node DSL | 静态 roster contact、one-time email、email variable、current initiator。 |
|
||||
| `ResolvedRecipient` | Value Object | runtime only | 解析后的通知与审批对象,进入 task 前仍可去重。 |
|
||||
| `AllowedApprover` | Value Object | `HumanInputFormRecipient` snapshot extension | 提交权限的 canonical identity。 |
|
||||
| `HITLTask` | Aggregate Root | `HumanInputForm` | 一个等待人工输入的持久化 task。 |
|
||||
| `TaskRecipientSnapshot` | Entity | `HumanInputFormRecipient` | task 创建时的 recipient、contact、email、IM identity、auth requirement 快照。 |
|
||||
| `DeliveryAttempt` | Entity | `HumanInputDelivery` / future delivery record | 每个 recipient 每个 channel 的投递记录。 |
|
||||
| `RecipientResolutionRecord` | Entity | future runtime log | 记录 dynamic email 等解析过程。 |
|
||||
|
||||
`HumanInputFormRecipient` 不应升级为 Contact。它是运行时 task 下的 recipient snapshot / access token holder。
|
||||
|
||||
## 关键不变量
|
||||
|
||||
1. `ExternalContact` 创建前必须用 normalized email 查找可见 `Account`;命中时只能添加 Dify member。
|
||||
2. HITL 节点静态 recipient 只能引用当前 `ApprovalDomainContext.human_roster_id` 下 selectable 的 `RosterEntry`。
|
||||
3. one-time email 和 dynamic email 不写入 Human Roster。
|
||||
4. task 创建后,`TaskRecipientSnapshot` 不可变,用于审计和历史显示。
|
||||
5. 新 task 使用最新 contact、IM binding、credential 和 channel capability。
|
||||
6. pending task 提交时必须重新校验安全敏感状态:account disabled、left workspace、removed external contact、deleted IM binding、IM identity mismatch。
|
||||
7. 同一个 Dify `Account` 只能生成一个 `AllowedApprover`。
|
||||
8. 同一个 normalized email 只能生成一个 email recipient;如果能匹配 roster contact,应优先转成更强身份的 contact recipient。
|
||||
9. IM + Email 双渠道触达是 delivery 策略,不代表两个 approver。
|
||||
10. Secret 不进入 audit、delivery record、task snapshot,只保存 credential handle 和 provider metadata。
|
||||
11. `workspace_id` 是入口 locator,不是领域服务的默认上下文;进入应用服务后应优先传 `ApprovalDomainContext`。
|
||||
|
||||
## 策略接口
|
||||
|
||||
以下接口是领域层与部署形态差异之间的边界。实现可以在 CE / EE / SaaS 中不同,但调用方使用同一组 port。
|
||||
|
||||
```python
|
||||
class ApprovalDomainResolver(Protocol):
|
||||
# Resolves the product-level approval context from a system boundary locator.
|
||||
# workspace_id should normally stop here and not leak into downstream services.
|
||||
def resolve_for_workspace(self, workspace_id: WorkspaceId) -> ApprovalDomainContext: ...
|
||||
# Rebuilds the current approval context for submission, retry, audit, or callback flows.
|
||||
def resolve_for_task(self, task_id: HITLTaskId) -> ApprovalDomainContext: ...
|
||||
|
||||
|
||||
class ContactDirectoryRepository(Protocol):
|
||||
# Persists person identities visible in one approval domain.
|
||||
def get_by_id(self, contact_identity_id: ContactIdentityId) -> ContactIdentity | None: ...
|
||||
# Finds the contact identity backed by a Dify Account inside a contact directory.
|
||||
def find_account_contact(self, directory_id: ContactDirectoryId, account_id: AccountId) -> ContactIdentity | None: ...
|
||||
# Used to prevent creating ExternalContact when the email belongs to a Dify Account.
|
||||
def find_by_normalized_email(self, directory_id: ContactDirectoryId, email: NormalizedEmail) -> ContactIdentity | None: ...
|
||||
def save(self, contact: ContactIdentity) -> None: ...
|
||||
|
||||
|
||||
class HumanRosterRepository(Protocol):
|
||||
# Persists selectable entries used by HITL node configuration.
|
||||
def get_entry(self, roster_id: HumanRosterId, roster_entry_id: RosterEntryId) -> RosterEntry | None: ...
|
||||
# Helps keep one roster row per contact identity within a roster.
|
||||
def find_by_contact_identity(self, roster_id: HumanRosterId, contact_identity_id: ContactIdentityId) -> RosterEntry | None: ...
|
||||
# Returns only entries that can be selected by new HITL nodes.
|
||||
def list_selectable_entries(self, roster_id: HumanRosterId, query: RosterQuery) -> Sequence[RosterEntry]: ...
|
||||
def save_entry(self, entry: RosterEntry) -> None: ...
|
||||
|
||||
|
||||
class AccountDirectoryPort(Protocol):
|
||||
# Read-only adapter over Dify Account and TenantAccountJoin.
|
||||
def get_account(self, account_id: AccountId) -> AccountProfile | None: ...
|
||||
# Used by contact creation, IM sync, import, and recipient canonicalization.
|
||||
def find_account_by_email(self, email: NormalizedEmail) -> AccountProfile | None: ...
|
||||
# Uses the domain policy to choose the underlying TenantAccountJoin query.
|
||||
def list_roster_source_members(self, domain: ApprovalDomainContext) -> Sequence[WorkspaceMemberProfile]: ...
|
||||
# Used at submission time to reject approvers who no longer satisfy domain membership rules.
|
||||
def has_active_membership(self, domain: ApprovalDomainContext, account_id: AccountId) -> bool: ...
|
||||
|
||||
|
||||
class IMCredentialResolver(Protocol):
|
||||
# Resolves the effective IM installation without exposing where credentials came from.
|
||||
def resolve_installation(self, domain: ApprovalDomainContext, provider: IMProvider) -> IMInstallation | None: ...
|
||||
# Returns provider, credential handle, callback metadata, and capability context for sending.
|
||||
def resolve_sender(self, domain: ApprovalDomainContext, provider: IMProvider) -> IMSenderContext | None: ...
|
||||
|
||||
|
||||
class IMBindingRepository(Protocol):
|
||||
# Resolves the effective binding according to the domain's override policy.
|
||||
def get_effective_binding(self, domain: ApprovalDomainContext, contact_identity_id: ContactIdentityId, provider: IMProvider) -> IMIdentityBinding | None: ...
|
||||
# Used by IM card callbacks to map platform user identity back to a Dify contact.
|
||||
def find_by_provider_user(self, domain: ApprovalDomainContext, provider: IMProvider, provider_user_id: str) -> IMIdentityBinding | None: ...
|
||||
def save(self, binding: IMIdentityBinding) -> None: ...
|
||||
|
||||
|
||||
class IMDirectorySyncGateway(Protocol):
|
||||
# Provider-specific gateway. It returns directory data but does not create contacts.
|
||||
def list_members(self, installation: IMInstallation) -> Sequence[IMDirectoryMember]: ...
|
||||
|
||||
|
||||
class RecipientResolver(Protocol):
|
||||
# Converts node selectors into canonical runtime recipients and resolution records.
|
||||
def resolve(self, domain: ApprovalDomainContext, request: RecipientResolutionRequest) -> RecipientResolutionResult: ...
|
||||
|
||||
|
||||
class NotificationPlanner(Protocol):
|
||||
# Chooses IM card, IM fallback URL, Email, or skipped delivery per recipient.
|
||||
def plan(self, domain: ApprovalDomainContext, task: HITLTask, recipients: Sequence[ResolvedRecipient]) -> NotificationPlan: ...
|
||||
|
||||
|
||||
class NotificationDispatcher(Protocol):
|
||||
# Performs side effects and returns durable delivery attempts for audit and Last Run.
|
||||
def dispatch(self, plan: NotificationPlan) -> Sequence[DeliveryAttempt]: ...
|
||||
|
||||
|
||||
class RecipientAuthenticator(Protocol):
|
||||
# Identifies the actor from Dify login, IM platform identity, magic link, or OTP.
|
||||
def authenticate(self, domain: ApprovalDomainContext, request: ApprovalAccessRequest) -> SubmissionIdentity: ...
|
||||
# Checks the authenticated actor against allowed approvers and current safety state.
|
||||
def authorize_submission(self, domain: ApprovalDomainContext, task: HITLTask, identity: SubmissionIdentity) -> ApprovalDecision: ...
|
||||
|
||||
|
||||
class HITLTaskRepository(Protocol):
|
||||
# Persists immutable recipient snapshots when the task is created.
|
||||
def create(self, task: HITLTask) -> HITLTaskId: ...
|
||||
def get(self, task_id: HITLTaskId) -> HITLTask | None: ...
|
||||
# Must be atomic so only one allowed approver can submit a pending task.
|
||||
def mark_submitted(self, task_id: HITLTaskId, submission: SubmissionRecord) -> None: ...
|
||||
|
||||
|
||||
class AuditLogPort(Protocol):
|
||||
# Stores domain audit events without leaking secrets or raw sensitive content.
|
||||
def record(self, event: AuditEvent) -> None: ...
|
||||
|
||||
|
||||
class SecretStore(Protocol):
|
||||
# Stores provider credentials and returns opaque handles for domain records.
|
||||
def put(self, owner: CredentialOwnerRef, secret: SecretPayload) -> IMCredentialHandle: ...
|
||||
# Secret access should be limited to infrastructure code that actually sends requests.
|
||||
def get(self, handle: IMCredentialHandle) -> SecretPayload: ...
|
||||
```
|
||||
|
||||
## 应用服务
|
||||
|
||||
| 服务 | 说明 |
|
||||
| --- | --- |
|
||||
| `ApprovalDomainResolver` | 从 workspace locator 或 task 解析 `ApprovalDomainContext`,隔离 CE / EE / SaaS 拓扑差异。 |
|
||||
| `RosterBootstrapService` | 根据 `ApprovalDomainContext.roster_policy` 初始化和同步 Human Roster。SaaS / CE 通常同步 workspace member;EE 可使用不同 policy,不默认添加企业全量联系人。 |
|
||||
| `ContactDirectoryService` | 创建 account-backed contact、拒绝错误 external contact、管理企业级 IM binding。 |
|
||||
| `HumanRosterService` | 添加 Dify member、添加 external contact、移除或转换 roster entry、计算 selectable 状态。 |
|
||||
| `IMIntegrationService` | 保存 IM app installation、测试连接、解析 callback URL、触发通讯录同步。 |
|
||||
| `IMDirectorySyncService` | 从 provider 通讯录同步成员,优先匹配 IM user id,再按 email 匹配 `Account`,未匹配进入 unmatched list。 |
|
||||
| `RecipientResolutionService` | 将节点配置中的 `RecipientSelector` 解析为 `ResolvedRecipient`,执行 canonicalization 与去重。 |
|
||||
| `HITLTaskApplicationService` | 创建 `HITLTask`、冻结 snapshot、调用 notification planner 和 dispatcher。 |
|
||||
| `SubmissionApplicationService` | 处理 IM card、fallback URL、Email OTP、Dify login 等提交入口,执行 authenticate 和 authorize。 |
|
||||
| `HITLMigrationService` | 迁移旧 email recipient;能匹配 workspace member 则转 contact selector,否则保留 one-time email。 |
|
||||
|
||||
## 主要流程
|
||||
|
||||
### Roster 初始化
|
||||
|
||||
1. 系统边界拿到 `workspace_id` 后调用 `ApprovalDomainResolver.resolve_for_workspace`。
|
||||
2. `RosterBootstrapService` 读取 `domain.roster_policy` 和 `domain.human_roster_id`。
|
||||
3. SaaS / CE:adapter 基于现有 `TenantAccountJoin` 查询 roster source members,为成员创建或更新 `ContactIdentity` 与 `RosterEntry`。
|
||||
4. EE:不导入企业全量联系人;workspace admin 通过 `HumanRosterService.add_dify_member` 添加。
|
||||
5. 成员离开时不物理删除 `RosterEntry`,改为 `left_workspace` 或 `pending_review`。
|
||||
|
||||
### 创建 HITL task
|
||||
|
||||
1. workflow 运行上下文用 `workspace_id` 解析 `ApprovalDomainContext`,后续服务不再直接传 `workspace_id`。
|
||||
2. 从 `HumanInputNodeData.notification_policy` 读取 `RecipientSelector`。
|
||||
3. `RecipientResolutionService.resolve(domain, request)` 解析 roster entry、one-time email、dynamic email、current initiator。
|
||||
4. 对解析结果做 canonicalization,合并同一 approver 的多渠道 endpoint。
|
||||
5. `IMCredentialResolver` 与 `IMBindingRepository` 基于 `domain.im_integration_policy` 为每个 contact 解析 IM endpoint。
|
||||
6. 创建 `HITLTask` 和 immutable `TaskRecipientSnapshot`。
|
||||
7. `NotificationPlanner` 按能力矩阵选择 IM card、IM fallback URL 和 Email。
|
||||
8. `NotificationDispatcher` 发送并写入 `DeliveryAttempt`。
|
||||
9. 解析、跳过和失败原因进入 `RecipientResolutionRecord` 与 audit log。
|
||||
|
||||
### 提交 HITL task
|
||||
|
||||
1. 打开 URL 或 IM card callback 时先定位 `HITLTask`,但 URL 本身不代表审批权限。
|
||||
2. `ApprovalDomainResolver.resolve_for_task` 恢复当前审批域上下文。
|
||||
3. `RecipientAuthenticator.authenticate(domain, request)` 基于 Dify login、IM platform identity、Magic link 或 Email OTP 识别提交人。
|
||||
4. `authorize_submission(domain, task, identity)` 用 `AllowedApprover` 和当前安全状态重新校验。
|
||||
5. 已提交、超时、取消、账号禁用、成员离开、external contact 删除、IM binding 删除、IM identity mismatch 均拒绝提交。
|
||||
6. 成功提交后只允许一次状态转移到 `submitted`。
|
||||
|
||||
## 与现有模型映射
|
||||
|
||||
| 现有对象 | 建议领域语义 |
|
||||
| --- | --- |
|
||||
| `Account` | account-backed `ContactIdentity` 的身份来源。 |
|
||||
| `Tenant` | 系统入口 locator 和现有存储 owner;应用服务入口用它解析 `ApprovalDomainContext`。 |
|
||||
| `TenantAccountJoin` | membership 数据源,用于 resolver / adapter 推导 roster source members 和提交时成员状态。 |
|
||||
| `HumanInputNodeData` | 继续承载表单 schema;新增 `NotificationPolicy`,不要把 Contact 逻辑塞进旧 `EmailRecipients`。 |
|
||||
| `HumanInputForm` | `HITLTask` 的持久化实现;应能恢复或重建 task 所属 `ApprovalDomainContext`。 |
|
||||
| `HumanInputDelivery` | delivery method / delivery batch。后续需要补足 per recipient per channel record。 |
|
||||
| `HumanInputFormRecipient` | `TaskRecipientSnapshot` 和 access token holder。它不是 Contact。 |
|
||||
|
||||
## 分阶段落地建议
|
||||
|
||||
1. 先实现 `ApprovalDomainResolver` 和 `ApprovalDomainContext`,把 `workspace_id` 限制在系统入口和 adapter 内。
|
||||
2. 增加 `ContactDirectory`、`ContactIdentity`、`HumanRoster`、`RosterEntry`,让节点配置保存 roster-scoped contact reference。
|
||||
3. 扩展 HITL node config,引入 `NotificationPolicy` 和 `RecipientSelector`,兼容旧 `EmailRecipients`。
|
||||
4. 实现 `RecipientResolutionService.resolve(domain, request)`,把旧 email member / external email 迁移到新 recipient model。
|
||||
5. 在 `HumanInputFormRecipient` payload 中增加 snapshot 结构,保留旧 payload 兼容读取。
|
||||
6. 引入 `IMIntegrationService`、`IMCredentialResolver`、`IMBindingRepository` 和 directory sync / search,所有解析均基于 `ApprovalDomainContext`。
|
||||
7. 补齐 per recipient per channel delivery record、resolution record 和 audit event。
|
||||
|
||||
## 已确认决策与剩余风险
|
||||
|
||||
以下产品规则已经确认,不影响核心抽象,只影响 policy、权限矩阵或交互实现:
|
||||
|
||||
1. Workflow editor 禁止创建 `ExternalContact`,仅允许输入 one-time email。
|
||||
2. Pending task 在 external contact 删除或 IM binding 删除后拒绝提交。
|
||||
3. IM identity 一期通过 directory sync / search 选择 provider user。
|
||||
4. SaaS dynamic email、Magic link、OTP、单 task recipient 数量和每日发送量属于 guardrail 配置,不影响 Contact / Roster / Recipient 抽象。
|
||||
|
||||
剩余会影响抽象演进的问题只有一个:SaaS 未来是否会出现“一个企业多个 workspace”。当前没有这个计划,所以 `ApprovalDomain` 暂不需要独立持久化;但领域层仍通过 `ApprovalDomainContext` 隔离拓扑细节,避免未来从 `tenant_id` 迁移到独立企业 ID 时扩散到 Contact、Roster、IM 和 HITL Runtime。
|
||||
589
hitl_phase2_backend_linear_task_list.md
Normal file
589
hitl_phase2_backend_linear_task_list.md
Normal file
@ -0,0 +1,589 @@
|
||||
# HITL Phase 2 后端 Linear 任务清单
|
||||
|
||||
目标:生成后续可同步到 Linear 的后端 issue 列表;本文件只写入本地,不写入 Linear。
|
||||
|
||||
## 信息来源
|
||||
|
||||
| 来源 | 读取结果 |
|
||||
|-|-|
|
||||
| PRD | [HITL:IM 通知与 Contact PRD](https://langgenius.feishu.cn/wiki/GMFdwe40Oi2rC9klP2HcNjnHnwd),最新读取到 `revision_id = 1959`,读取时间 2026-07-10。 |
|
||||
| Linear Project | [HITL IM 支持](https://linear.app/dify/project/hitl-im-支持-cd5c0fe0752d),项目 ID `882439e3-f6f5-4474-9fee-255e11e16c51`,团队 `WTA`。 |
|
||||
| Linear 里程碑 | `冻结产品文档` 2026-07-10;`确定前后端交互协议及 DSL schema` 2026-07-14;`连调` 2026-07-22;`测试` 2026-07-27。 |
|
||||
| 现有 Linear issue | `WTA-1255 HITL IM 集成接口及 DSL 设计` 仍为待办;旧 IM 表单消息探索任务大多已取消;`WTA-735 为 Graphon 的 HITL 抽象一套接口` 已完成。 |
|
||||
| 后端代码基线 | 已有 `human-input` 节点、`HumanInputForm`、`HumanInputDelivery`、`HumanInputFormRecipient`、Email delivery、form token、file upload token、暂停恢复、多 surface 表单提交。Phase 2 应扩展现有模型和运行时,不重复建设基础 HITL。 |
|
||||
|
||||
## 拆分原则
|
||||
|
||||
1. 只包含后端工作,不包含前端、QA 明细和纯产品任务。
|
||||
2. 保留 `WTA-1255` 作为已有契约任务,建议更新描述和验收标准,不再新建重复契约 issue。
|
||||
3. 按 PRD 里程碑和 Linear 现有 milestone 对齐;后端实现类任务归入 `连调`,不放进 `确定前后端交互协议及 DSL schema`。
|
||||
4. `导入导出 / DSL ID-Email 转换` 已被 PRD 移出本期,不放入本期后端任务。
|
||||
5. 任务描述以 Linear issue 可直接复制为目标;依赖字段使用本文件临时编号,真正导入 Linear 后再替换为 Linear issue id。
|
||||
|
||||
## 里程碑归属口径
|
||||
|
||||
| Linear 里程碑 | 后端任务归属 |
|
||||
|-|-|
|
||||
| 冻结产品文档 | 只放 PRD / scope / blocker 收敛任务,不放数据模型设计或代码实现。 |
|
||||
| 确定前后端交互协议及 DSL schema | 只放前后端解耦所需的 DSL schema、API contract、错误码、mock fixture、provider contract。 |
|
||||
| 连调 | 放后端数据模型、migration、Contact / IM / HITL runtime 实现、provider adapter、审计、Last Run 和安全鉴权等实现任务。 |
|
||||
| 测试 | 放后端测试支持、migration dry run、provider sandbox 证据、安全回归和 ready-to-test 交付物。 |
|
||||
|
||||
## 依赖梳理口径
|
||||
|
||||
| 任务类型 | 依赖原则 |
|
||||
|-|-|
|
||||
| PRD / scope 收敛 | 不依赖实现任务,用来冻结本期边界和阻塞项。 |
|
||||
| DSL / API / mock 契约 | 只依赖 PRD / scope 和高层 DSL 决策,不依赖数据库设计、migration 或 runtime 实现。完成后前端可以基于 mock 并行开发。 |
|
||||
| 数据模型 / migration | 依赖 PRD / scope 和 DSL 决策,属于后端实现前置任务,挂 `连调` milestone。 |
|
||||
| Runtime / provider / 安全实现 | 依赖数据模型、API contract 和对应基础能力,按可并行方向拆分。 |
|
||||
| 测试准入 | 依赖核心实现和 provider adapter,输出 dry run、sandbox、安全回归和 ready-to-test 证据。 |
|
||||
|
||||
## 建议同步策略
|
||||
|
||||
| 本地编号 | Linear 操作 | 说明 |
|
||||
|-|-|-|
|
||||
| BE-HITL-001 | 更新现有 `WTA-1255` | 保留已有契约 issue,补齐 DSL、API、错误码、mock、provider contract 的验收口径。 |
|
||||
| 其他任务 | 新建 issue | 新建在项目 `HITL IM 支持`,团队 `WTA`,按对应 milestone 挂载。 |
|
||||
|
||||
## 任务总览
|
||||
|
||||
| 本地编号 | 标题 | Linear 操作 | 里程碑 | 优先级 | 截止日期 | 依赖 |
|
||||
|-|-|-|-|-|-|-|
|
||||
| BE-HITL-001 | HITL IM 集成接口及 DSL 设计 | 更新 `WTA-1255` | 确定前后端交互协议及 DSL schema | 高 | 2026-07-14 | - |
|
||||
| BE-HITL-002 | 确认后端范围与 PRD 决策回写差异 | 新建 | 冻结产品文档 | 高 | 2026-07-10 | - |
|
||||
| BE-HITL-003 | 设计 Contact / IM / HITL 数据模型与迁移方案 | 新建 | 连调 | 高 | 2026-07-14 | BE-HITL-001、BE-HITL-002 |
|
||||
| BE-HITL-004 | 定义后端 API contract、错误码和 mock fixture | 新建 | 确定前后端交互协议及 DSL schema | 高 | 2026-07-14 | BE-HITL-001、BE-HITL-002 |
|
||||
| BE-HITL-005 | 实现 Organization / Approval Domain 解析策略 | 新建 | 连调 | 高 | 2026-07-17 | BE-HITL-003 |
|
||||
| BE-HITL-006 | 实现 Contact Directory / Workspace Contact migration | 新建 | 连调 | 高 | 2026-07-18 | BE-HITL-003、BE-HITL-005 |
|
||||
| BE-HITL-007 | 实现 Contact / External Contact 管理 API | 新建 | 连调 | 高 | 2026-07-19 | BE-HITL-006 |
|
||||
| BE-HITL-008 | 实现 IM Binding 与 Workspace IM override 数据层 | 新建 | 连调 | 高 | 2026-07-19 | BE-HITL-003、BE-HITL-006 |
|
||||
| BE-HITL-009 | 实现 IM Integration credential 与连接状态机 | 新建 | 连调 | 高 | 2026-07-19 | BE-HITL-003、BE-HITL-005 |
|
||||
| BE-HITL-010 | 实现 IM 通讯录同步与 unmatched list | 新建 | 连调 | 高 | 2026-07-20 | BE-HITL-008、BE-HITL-009 |
|
||||
| BE-HITL-011 | 扩展 HITL 节点 Notification Policy 与兼容 adapter | 新建 | 连调 | 高 | 2026-07-18 | BE-HITL-001、BE-HITL-004 |
|
||||
| BE-HITL-012 | 实现 recipient resolver v2 与 Contact-centric 去重 | 新建 | 连调 | 高 | 2026-07-19 | BE-HITL-006、BE-HITL-008、BE-HITL-011 |
|
||||
| BE-HITL-013 | 扩展 HITL task snapshot、allowed approver 与 resolution records | 新建 | 连调 | 高 | 2026-07-20 | BE-HITL-012 |
|
||||
| BE-HITL-014 | 实现 Request Message Template 与 Email always-on 发送策略 | 新建 | 连调 | 高 | 2026-07-20 | BE-HITL-011、BE-HITL-013 |
|
||||
| BE-HITL-015 | 实现 Email OTP 与 Web 独立页鉴权后端 | 新建 | 连调 | 高 | 2026-07-20 | BE-HITL-013、BE-HITL-014 |
|
||||
| BE-HITL-016 | 实现提交时动态授权与原子提交 | 新建 | 连调 | 高 | 2026-07-20 | BE-HITL-013、BE-HITL-015 |
|
||||
| BE-HITL-017 | | 新建 | 连调 | 中 | 2026-07-21 | BE-HITL-016 |
|
||||
| BE-HITL-018 | 实现 delivery records 状态机与投递失败规则 | 新建 | 连调 | 高 | 2026-07-20 | BE-HITL-013、BE-HITL-014 |
|
||||
| BE-HITL-019 | 实现审计数据落库与脱敏边界 | 新建 | 连调 | 高 | 2026-07-21 | BE-HITL-013、BE-HITL-016、BE-HITL-018 |
|
||||
| BE-HITL-020 | 实现 Last Run / Debug 后端日志投影 | 新建 | 连调 | 中 | 2026-07-21 | BE-HITL-012、BE-HITL-018、BE-HITL-019 |
|
||||
| BE-HITL-021 | 实现节点级错误、warning 和 timeout / expired 分流 | 新建 | 连调 | 高 | 2026-07-21 | BE-HITL-012、BE-HITL-016、BE-HITL-018 |
|
||||
| BE-HITL-022 | 实现 IM provider runtime、callback 与身份校验框架 | 新建 | 连调 | 高 | 2026-07-20 | BE-HITL-009、BE-HITL-013、BE-HITL-016 |
|
||||
| BE-HITL-023 | 实现 Slack 后端 adapter | 新建 | 连调 | 高 | 2026-07-22 | BE-HITL-010、BE-HITL-022 |
|
||||
| BE-HITL-024 | 实现钉钉后端 adapter | 新建 | 连调 | 高 | 2026-07-22 | BE-HITL-010、BE-HITL-022 |
|
||||
| BE-HITL-025 | 实现飞书 / Lark 后端 adapter | 新建 | 连调 | 高 | 2026-07-22 | BE-HITL-010、BE-HITL-022 |
|
||||
| BE-HITL-026 | 实现 Microsoft Teams 后端 adapter | 新建 | 连调 | 高 | 2026-07-22 | BE-HITL-010、BE-HITL-022 |
|
||||
| BE-HITL-027 | 实现企业微信后端 adapter 与 Web fallback | 新建 | 连调 | 中 | 2026-07-22 | BE-HITL-010、BE-HITL-022 |
|
||||
| BE-HITL-028 | 实现旧 Email recipient 与 SaaS / CE Contact 初始化迁移 | 新建 | 测试 | 高 | 2026-07-24 | BE-HITL-006、BE-HITL-012、BE-HITL-013 |
|
||||
| BE-HITL-029 | 实现 SaaS abuse guardrails 后端基础能力 | 新建 | 测试 | 高 | 2026-07-24 | BE-HITL-014、BE-HITL-015、BE-HITL-018 |
|
||||
| BE-HITL-030 | 实现审批人是 member 的通知中心后端接口 | 新建 | 测试 | 中 | 2026-07-25 | BE-HITL-013、BE-HITL-016 |
|
||||
| BE-HITL-031 | 后端联调支持与测试证据包 | 新建 | 测试 | 高 | 2026-07-27 | BE-HITL-018、BE-HITL-019、BE-HITL-023、BE-HITL-024、BE-HITL-025、BE-HITL-026、BE-HITL-027、BE-HITL-028、BE-HITL-029 |
|
||||
|
||||
## Issue 明细
|
||||
|
||||
### BE-HITL-001:HITL IM 集成接口及 DSL 设计
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 更新现有 `WTA-1255` |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `确定前后端交互协议及 DSL schema` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-14 |
|
||||
| 标签 | backend、contract、dsl、api |
|
||||
| 描述 | 基于 PRD revision 1959 冻结后端 DSL、API contract、recipient selector、Notification Policy、provider contract、错误码、feature flag 和兼容策略。需要明确旧 `human-input` / 现有 Email delivery / WebApp delivery 如何兼容,避免 Phase 2 重建一套基础 HITL。 |
|
||||
| 验收标准 | 1. DSL 覆盖 static Contact、one-time Email、dynamic Email、current initiator、debug only notify me、Request Message Template、Notification Policy。<br>2. API contract 覆盖 Contact、IM Integration、IM Binding、Workspace IM override、OTP、Last Run、delivery records。<br>3. 错误码覆盖 dynamic Email 解析异常、无可通知对象、OTP 失败、权限失败、task 已完成或过期。<br>4. 明确旧 published workflow 不自动改写,新旧运行路径分流策略清楚。 |
|
||||
|
||||
### BE-HITL-002:确认后端范围与 PRD 决策回写差异
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `冻结产品文档` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-10 |
|
||||
| 标签 | backend、prd、scope |
|
||||
| 描述 | 对 PRD revision 1959 做后端实现范围确认,标出已进入本期、已移出本期、仍需产品或安全确认但不阻塞实现的事项。 |
|
||||
| 验收标准 | 1. 明确 Workspace IM override 本期做,但不覆盖 IM Integration credential。<br>2. 明确导入导出 / DSL ID-Email 转换移出本期。<br>3. 明确 Web 独立页审批按审批主体鉴权,不再按统一 OTP 或 Magic Link。<br>4. 明确 form/task status 复用 `WAITING / SUBMITTED / TIMEOUT / EXPIRED`。<br>5. 输出后端 scope note,可贴到 `WTA-1255` 或项目文档。 |
|
||||
|
||||
### BE-HITL-003:设计 Contact / IM / HITL 数据模型与迁移方案
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-14 |
|
||||
| 标签 | backend、database、migration |
|
||||
| 依赖 | BE-HITL-001、BE-HITL-002 |
|
||||
| 描述 | 设计 Contact Directory、Workspace Contact、External Contact、IM Binding、Workspace IM override、IM Integration credential、recipient snapshot、delivery record、resolution record、audit record 的后端数据模型。需要复用现有 `HumanInputForm`、`HumanInputDelivery`、`HumanInputFormRecipient`,只做必要扩展。 |
|
||||
| 验收标准 | 1. 表结构、唯一约束、索引、状态枚举和 owner scope 明确。<br>2. CE / SaaS 当前 workspace 即 Organization,EE deployment 为 Organization 的映射清楚。<br>3. Contact 类型覆盖 workspace member、Organization contact、External contact。<br>4. `HumanInputFormRecipient` 明确作为 task recipient snapshot,不被误建模为 Contact。<br>5. migration dry run 与 rollback 方案明确。 |
|
||||
|
||||
### BE-HITL-004:定义后端 API contract、错误码和 mock fixture
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `确定前后端交互协议及 DSL schema` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-14 |
|
||||
| 标签 | backend、api、contract、mock |
|
||||
| 依赖 | BE-HITL-001、BE-HITL-002 |
|
||||
| 描述 | 输出供前端并行开发使用的后端 API contract、response shape、error code、mock response 和 fixture。范围包括 Contact、IM Integration、IM Binding、Workspace override、recipient resolution preview、OTP、Last Run、provider status。 |
|
||||
| 验收标准 | 1. 前端无需等待真实实现即可基于 mock 开发。<br>2. mock 字段与后续真实 API 保持一致。<br>3. provider connection status 六态可表达:Not configured、Configured、Connected、Permission issue、Callback error、Connection error。<br>4. API 明确权限失败、资源不存在、不可选择、不可提交、OTP 失败、provider 失败的稳定错误码。 |
|
||||
|
||||
### BE-HITL-005:实现 Organization / Approval Domain 解析策略
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-17 |
|
||||
| 标签 | backend、domain、organization |
|
||||
| 依赖 | BE-HITL-003 |
|
||||
| 描述 | 实现从 `tenant_id / workspace_id` 到当前 Organization / Contact scope / IM credential scope 的解析策略。代码内部可保留审批域 resolver 边界,但对外使用 PRD 的 Organization / Contact 口径。 |
|
||||
| 验收标准 | 1. CE / SaaS 使用当前 workspace 作为 Organization。<br>2. EE 使用 deployment 级 Organization,并能解析当前 workspace 的 Contact scope。<br>3. 后续 Contact、IM Integration、recipient resolver 和提交鉴权不直接散落判断部署形态。<br>4. 单测覆盖 CE / SaaS / EE 策略分支。 |
|
||||
|
||||
### BE-HITL-006:实现 Contact Directory / Workspace Contact migration
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-18 |
|
||||
| 标签 | backend、contact、migration |
|
||||
| 依赖 | BE-HITL-003、BE-HITL-005 |
|
||||
| 描述 | 实现 Contact Directory 和 Workspace Contact 的持久化与初始化迁移。SaaS / CE workspace members 自动进入 Contact;EE 支持从 Organization Contact 添加到 workspace Contact。 |
|
||||
| 验收标准 | 1. workspace member 新增后可进入 Contact。<br>2. CE / SaaS 成员移除后从新配置不可选择,历史引用可解释。<br>3. EE 支持 Organization contact 语义,不把其他 workspace 的 Dify member 建成 external contact。<br>4. normalized email 使用完整 email lower-case 后完全相等。<br>5. migration 可重复执行,索引和唯一约束能防止重复联系人。 |
|
||||
|
||||
### BE-HITL-007:实现 Contact / External Contact 管理 API
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-19 |
|
||||
| 标签 | backend、api、contact、rbac |
|
||||
| 依赖 | BE-HITL-006 |
|
||||
| 描述 | 实现 Contact 列表、搜索、添加 Dify member、添加 External contact、删除 External contact、状态查询等 API。预留 `Manage contacts` 能力边界。 |
|
||||
| 验收标准 | 1. 添加 External contact 前必须先按 normalized email 查找可见 Dify Account / Contact,命中时不能创建 external contact。<br>2. workflow editor 不能通过节点配置直接创建 External contact。<br>3. 普通 member 不获得完整 Contact 管理权限。<br>4. 删除 External contact 后新配置不可选择,历史 workflow 和历史 task snapshot 可读。 |
|
||||
|
||||
### BE-HITL-008:实现 IM Binding 与 Workspace IM override 数据层
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-19 |
|
||||
| 标签 | backend、im、binding |
|
||||
| 依赖 | BE-HITL-003、BE-HITL-006 |
|
||||
| 描述 | 实现 Organization 全局 IM identity、Workspace IM override 的持久化、查询和解析优先级。Workspace override 只影响当前 workspace 内联系人 IM 身份 / 通知行为,不覆盖 provider credential。 |
|
||||
| 验收标准 | 1. 运行时优先级为 workspace override > Organization IM identity > Email。<br>2. 同一个联系人在不同 workspace 可有不同 override。<br>3. pending task 提交时必须按当前 IM Binding 动态授权。<br>4. 删除或修改 binding 不破坏历史 snapshot,但会影响 pending task 提交资格。 |
|
||||
|
||||
### BE-HITL-009:实现 IM Integration credential 与连接状态机
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-19 |
|
||||
| 标签 | backend、im、credential、security |
|
||||
| 依赖 | BE-HITL-003、BE-HITL-005 |
|
||||
| 描述 | 实现 IM Integration credential 存储、脱敏读取、test connection、connection status 和 reason。凭据归属 Organization,secret 不进入响应、日志、delivery record 或 audit。 |
|
||||
| 验收标准 | 1. 支持 Not configured、Configured、Connected、Permission issue、Callback error、Connection error。<br>2. 保存凭据后进入 Configured,test connection 成功后进入 Connected。<br>3. 权限不足、callback 校验失败、凭据错误、provider 不可达能写入可排查 reason。<br>4. credential 轮换记录操作日志,旧回调失败可定位。 |
|
||||
|
||||
### BE-HITL-010:实现 IM 通讯录同步与 unmatched list
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-20 |
|
||||
| 标签 | backend、im、sync、contact |
|
||||
| 依赖 | BE-HITL-008、BE-HITL-009 |
|
||||
| 描述 | 实现 IM directory sync 服务:从 provider 拉成员,优先按 provider user id 匹配已有 IM Binding,其次按 Email 匹配 Dify Account;未匹配进入 unmatched list,不自动创建 external contact。 |
|
||||
| 验收标准 | 1. sync 结果包含 matched、created / updated bindings、unmatched、skipped、failed。<br>2. 未匹配 IM 成员不自动创建 external contact。<br>3. 能匹配 Dify Account 的对象不落为 external contact。<br>4. sync 失败可写入 provider status reason 和 audit / operation log。 |
|
||||
|
||||
### BE-HITL-011:扩展 HITL 节点 Notification Policy 与兼容 adapter
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-18 |
|
||||
| 标签 | backend、dsl、workflow |
|
||||
| 依赖 | BE-HITL-001、BE-HITL-004 |
|
||||
| 描述 | 扩展现有 `HumanInputNodeData` / adapter,支持 Notification Policy、Notified recipients、dynamic Email、one-time Email、current initiator、debug only notify me、Request Message Template,同时保持旧 `delivery_methods` 兼容读取。 |
|
||||
| 验收标准 | 1. 新 DSL 可被保存、发布、执行。<br>2. 旧 published workflow 的 `human-input` 不被自动改写。<br>3. 旧 Email / WebApp delivery 继续兼容。<br>4. 新旧 schema adapter 有单测覆盖。 |
|
||||
|
||||
### BE-HITL-012:实现 recipient resolver v2 与 Contact-centric 去重
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-19 |
|
||||
| 标签 | backend、resolver、contact |
|
||||
| 依赖 | BE-HITL-006、BE-HITL-008、BE-HITL-011 |
|
||||
| 描述 | 实现 recipient resolver v2,解析 static Contact、one-time Email、dynamic Email、current initiator、debug override,并以 Contact 为中心归并 allowed approver。 |
|
||||
| 验收标准 | 1. dynamic Email 只支持单个合法 email,不支持数组 / object / number / boolean。<br>2. dynamic Email 命中 Contact 时升级为 Contact recipient;未命中时按 one-time Email。<br>3. 同一个 Dify Account 只生成一个 allowed approver。<br>4. 同一个 normalized email 去重。<br>5. current initiator 与 notified recipients 命中同一人时合并。<br>6. 解析异常覆盖 variable_missing、variable_empty、unsupported_type、invalid_email、duplicated_email、matched_contact_unavailable、recipient_no_available_channel。 |
|
||||
|
||||
### BE-HITL-013:扩展 HITL task snapshot、allowed approver 与 resolution records
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-20 |
|
||||
| 标签 | backend、runtime、database |
|
||||
| 依赖 | BE-HITL-012 |
|
||||
| 描述 | 扩展现有 `HumanInputForm` / `HumanInputFormRecipient` 作为 HITL task 和 recipient snapshot 的持久化实现,记录 allowed approvers、matched sources、recipient snapshot、auth requirement 和 recipient resolution records。 |
|
||||
| 验收标准 | 1. task 创建时冻结 recipient snapshot,用于审计和历史展示。<br>2. snapshot 不作为提交授权的唯一依据。<br>3. resolution record 可用于 Last Run 展示 raw value、status、error code、resolved recipient type。<br>4. 兼容现有 form token 和 recipient token。 |
|
||||
|
||||
### BE-HITL-014:实现 Request Message Template 与 Email always-on 发送策略
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-20 |
|
||||
| 标签 | backend、email、notification |
|
||||
| 依赖 | BE-HITL-011、BE-HITL-013 |
|
||||
| 描述 | 将现有 Email delivery 升级为通用 Request Message Template 语义。对于有 IM binding 且 Email 可用的 recipient,默认并行创建 IM 与 Email delivery attempt;Email 本期不可关闭。 |
|
||||
| 验收标准 | 1. Email 内容包含足够任务上下文:app、workflow、node / request title、message、有效期、短 task reference。<br>2. 有 IM binding 时仍创建 Email delivery attempt。<br>3. 无 IM binding 时 Email 可单独触达。<br>4. Email 发送失败写入 delivery status 和 reason。 |
|
||||
|
||||
### BE-HITL-015:实现 Email OTP 与 Web 独立页鉴权后端
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-20 |
|
||||
| 标签 | backend、security、otp |
|
||||
| 依赖 | BE-HITL-013、BE-HITL-014 |
|
||||
| 描述 | 实现 Web 独立审批页的后端鉴权:Dify Account / workspace member / Organization contact 走 Dify 登录;无 Dify Account 的 External contact、one-time Email、未命中 Contact 的 dynamic Email 走 Email OTP。 |
|
||||
| 验收标准 | 1. OTP 支持发送、重发、校验、过期、次数限制和稳定错误码。<br>2. Email token 只用于定位 task / recipient,不单独代表审批权限。<br>3. 打开页面和提交表单都校验 task 状态、过期时间、allowed approver。<br>4. Magic Link 不作为本期方案。 |
|
||||
|
||||
### BE-HITL-016:实现提交时动态授权与原子提交
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-20 |
|
||||
| 标签 | backend、security、concurrency |
|
||||
| 依赖 | BE-HITL-013、BE-HITL-015 |
|
||||
| 描述 | 重构提交路径,提交时按当前 Dify identity、Contact 状态、IM Binding 状态和 allowed approver 动态授权,并将提交更新改为 first-writer-wins 原子更新。 |
|
||||
| 验收标准 | 1. 成员离开 workspace、Account disabled、External contact 删除、IM Binding 删除或 mismatch 时拒绝 pending task 提交。<br>2. 同一 task 并发提交只有一个成功,其余返回已完成。<br>3. `WAITING -> SUBMITTED` 原子化;`TIMEOUT / EXPIRED / SUBMITTED` 不可再提交。<br>4. 单测覆盖 race、身份不匹配、旧 binding 失效、task 已过期。 |
|
||||
|
||||
### BE-HITL-017:补齐文件访问授权与 HITL task 绑定校验
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 中 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-21 |
|
||||
| 标签 | backend、file、security |
|
||||
| 依赖 | BE-HITL-016 |
|
||||
| 描述 | 在现有 HITL standalone upload token 基础上补齐审批页文件预览 / 下载授权:不能只依赖 URL token,必须同时校验 task 可访问、访问者身份已验证、访问者命中 allowed approver、文件属于该 HITL task。 |
|
||||
| 验收标准 | 1. 文件访问在 task submitted / timeout / expired / revoked 后失效或受限。<br>2. 跨 task / 跨 tenant 文件不可访问。<br>3. 失败原因可区分 task expired、not assigned to you、file unavailable。<br>4. 不改变现有 WebApp / Service API 文件上传模型。 |
|
||||
|
||||
### BE-HITL-018:实现 delivery records 状态机与投递失败规则
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-20 |
|
||||
| 标签 | backend、delivery、runtime |
|
||||
| 依赖 | BE-HITL-013、BE-HITL-014 |
|
||||
| 描述 | 补齐 per recipient / per channel delivery record。每个 recipient 每个渠道记录 pending、sent、failed、skipped、provider message id、error code、error message、sent_at。 |
|
||||
| 验收标准 | 1. IM + Email 双发时生成两个 delivery attempt,但只对应同一个 allowed approver。<br>2. delivery_failed 不进入 `HumanInputFormStatus`。<br>3. 全部渠道失败且没有可继续等待入口时,节点失败并记录原因。<br>4. 部分失败时 task 继续等待,Last Run 可展示未通知对象和失败原因。 |
|
||||
|
||||
### BE-HITL-019:实现审计数据落库与脱敏边界
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-21 |
|
||||
| 标签 | backend、audit、security |
|
||||
| 依赖 | BE-HITL-013、BE-HITL-016、BE-HITL-018 |
|
||||
| 描述 | 本期不提供审计 UI,但后端必须保留审计相关数据,使管理员可通过数据库查询回答通知对象、投递渠道、身份校验、提交人、提交结果和拒绝原因。 |
|
||||
| 验收标准 | 1. 记录 task 所属 workspace、app、workflow、workflow run、node。<br>2. 记录运行时通知对象、recipient snapshot、channels、delivery result。<br>3. 记录提交人身份类型、提交渠道、是否为 allowed approver、提交时间和结果。<br>4. 非指定人提交、身份校验失败、成员退出、账号禁用、task 已提交或过期等拒绝事件有记录。<br>5. secret 不入库;Email / IM 正文不完整进入审计;表单敏感内容按策略脱敏或摘要。 |
|
||||
|
||||
### BE-HITL-020:实现 Last Run / Debug 后端日志投影
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 中 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-21 |
|
||||
| 标签 | backend、last-run、debug |
|
||||
| 依赖 | BE-HITL-012、BE-HITL-018、BE-HITL-019 |
|
||||
| 描述 | 为前端 Last Run / Debug 提供后端数据投影,展示 resolved recipients、dynamic email raw value、delivery channel、sent / failed / skipped、failure reason、submitted_by、submitted_at。 |
|
||||
| 验收标准 | 1. Last Run API 可展示 recipient resolution records 和 delivery records。<br>2. Debug 变量池没有值时,后端支持手动变量值进入 resolver。<br>3. raw dynamic value 的可见范围与脱敏策略一致。<br>4. 输出结构稳定,可供前端联调。 |
|
||||
|
||||
### BE-HITL-021:实现节点级错误、warning 和 timeout / expired 分流
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-21 |
|
||||
| 标签 | backend、runtime、workflow |
|
||||
| 依赖 | BE-HITL-012、BE-HITL-016、BE-HITL-018 |
|
||||
| 描述 | 按 PRD 固化节点执行失败、partial warning、timeout、global expired 的后端行为。form/task status 固定为 WAITING、SUBMITTED、TIMEOUT、EXPIRED。 |
|
||||
| 验收标准 | 1. notified recipients 为空且 current initiator 不可用时,节点直接失败,不创建等待 task。<br>2. 全部 recipient 无法通知时节点失败。<br>3. 部分 recipient 可通知时 task 继续等待,并记录未通知对象。<br>4. 节点 timeout 进入 timeout handle;global expired 中止 workflow run,不进入 timeout handle。 |
|
||||
|
||||
### BE-HITL-022:实现 IM provider runtime、callback 与身份校验框架
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-20 |
|
||||
| 标签 | backend、provider、im、security |
|
||||
| 依赖 | BE-HITL-009、BE-HITL-013、BE-HITL-016 |
|
||||
| 描述 | 实现统一 IM provider runtime:credential resolver、capability matrix、message rendering、callback signature / replay protection、IM identity extraction、card submit、Web fallback URL。 |
|
||||
| 验收标准 | 1. Provider adapter 具备统一接口:test connection、sync members、send request、verify callback、extract identity、handle submit。<br>2. 支持卡片内审批的 provider 走 IM identity -> IM Binding -> Contact -> allowed approver。<br>3. 不支持卡片内审批时发送 request message + Web 审批页 URL,Web 页面按审批主体鉴权。<br>4. callback 失败写入 delivery / audit reason,secret 不进日志。 |
|
||||
|
||||
### BE-HITL-023:实现 Slack 后端 adapter
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-22 |
|
||||
| 标签 | backend、provider、slack |
|
||||
| 依赖 | BE-HITL-010、BE-HITL-022 |
|
||||
| 描述 | 实现 Slack 后端 adapter,覆盖 SaaS Slack ISV / OAuth 和 EE 企业自建 App 的 credential、通讯录同步、消息发送、身份校验、卡片提交、Email 双发记录。 |
|
||||
| 验收标准 | 1. OAuth / self-built credential 可 test connection。<br>2. sync 可建立或更新 IM Binding。<br>3. Slack card submit 可通过 IM identity 动态授权。<br>4. 失败写入 delivery status、provider reason 和 audit。 |
|
||||
|
||||
### BE-HITL-024:实现钉钉后端 adapter
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-22 |
|
||||
| 标签 | backend、provider、dingtalk |
|
||||
| 依赖 | BE-HITL-010、BE-HITL-022 |
|
||||
| 描述 | 实现钉钉后端 adapter,覆盖 SaaS / EE 企业自建应用 credential、通讯录同步、消息发送、callback 校验、用户身份映射和 Web fallback。 |
|
||||
| 验收标准 | 1. 租户自建应用 credential 可配置并 test connection。<br>2. 通讯录同步不自动创建 external contact。<br>3. 卡片内审批或 fallback URL 均能记录 delivery / audit。<br>4. 权限缺失和 callback error 可定位到 connection status reason。 |
|
||||
|
||||
### BE-HITL-025:实现飞书 / Lark 后端 adapter
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-22 |
|
||||
| 标签 | backend、provider、lark |
|
||||
| 依赖 | BE-HITL-010、BE-HITL-022 |
|
||||
| 描述 | 实现飞书 / Lark EE 企业自建 App adapter,覆盖 credential、通讯录同步、卡片通知、身份校验、提交回调和失败记录。 |
|
||||
| 验收标准 | 1. 企业自建 App 可 test connection。<br>2. 卡片提交按 IM identity 动态授权。<br>3. fallback URL 不被当作 IM 身份链路,按 Web 独立页鉴权。<br>4. sandbox E2E 记录可进入后端测试证据包。 |
|
||||
|
||||
### BE-HITL-026:实现 Microsoft Teams 后端 adapter
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-22 |
|
||||
| 标签 | backend、provider、teams |
|
||||
| 依赖 | BE-HITL-010、BE-HITL-022 |
|
||||
| 描述 | 实现 Microsoft Teams EE 企业自建 Teams App adapter,覆盖 credential、成员同步、Adaptive Card 或 fallback message、身份校验、提交回调和 delivery record。 |
|
||||
| 验收标准 | 1. Teams App credential 可 test connection。<br>2. Adaptive Card 支持的表单路径可提交;不支持时走 Web fallback。<br>3. 身份校验失败、权限不足、callback error 均有稳定 reason。<br>4. sandbox E2E 记录可进入后端测试证据包。 |
|
||||
|
||||
### BE-HITL-027:实现企业微信后端 adapter 与 Web fallback
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `连调` |
|
||||
| 优先级 | 中 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-22 |
|
||||
| 标签 | backend、provider、wecom |
|
||||
| 依赖 | BE-HITL-010、BE-HITL-022 |
|
||||
| 描述 | 实现企业微信 EE 企业自建应用 adapter。PRD 标注企业微信卡片内审批能力有限,本期以后端通知 + Web 审批页 fallback 为硬门禁,卡片内完整审批不作为必交。 |
|
||||
| 验收标准 | 1. 企业微信 credential 可 test connection。<br>2. 可发送 request message + Web approval URL。<br>3. Web fallback 按审批主体鉴权,不依赖企业微信身份 fallback。<br>4. 卡片能力限制在 provider capability 中明确表达。 |
|
||||
|
||||
### BE-HITL-028:实现旧 Email recipient 与 SaaS / CE Contact 初始化迁移
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `测试` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-24 |
|
||||
| 标签 | backend、migration、compatibility |
|
||||
| 依赖 | BE-HITL-006、BE-HITL-012、BE-HITL-013 |
|
||||
| 描述 | 实现旧 Email recipient 迁移和 SaaS / CE Contact 初始化迁移。本期不做导入导出 / DSL ID-Email 转换。 |
|
||||
| 验收标准 | 1. 旧 Email recipient 匹配当前 workspace member 时迁移为 member / Contact recipient。<br>2. 匹配到 Dify Account 但不属于当前 workspace 时,不自动创建 external contact。<br>3. 无法匹配 Dify Account 时保留 one-time Email。<br>4. 不自动改写已发布 workflow;运行中 task 使用创建时 snapshot。<br>5. dry run、rollback 和重复执行有记录。 |
|
||||
|
||||
### BE-HITL-029:实现 SaaS abuse guardrails 后端基础能力
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `测试` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-24 |
|
||||
| 标签 | backend、saas、security、rate-limit |
|
||||
| 依赖 | BE-HITL-014、BE-HITL-015、BE-HITL-018 |
|
||||
| 描述 | PRD 将具体阈值交给 SaaS 团队确认;后端需要先提供可配置的基础 guardrail 能力,覆盖 OTP、dynamic Email、单 task 收件人数、发送量和发送日志。 |
|
||||
| 验收标准 | 1. OTP 重试、重发、校验失败可限流。<br>2. dynamic Email 发送和单 task recipient 数量有可配置上限入口。<br>3. 发送日志足以支持 abuse 排查。<br>4. 阈值未最终确认时可使用保守默认值或 feature flag,不阻塞后续调整。 |
|
||||
|
||||
### BE-HITL-030:实现审批人是 member 的通知中心后端接口
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `测试` |
|
||||
| 优先级 | 中 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-25 |
|
||||
| 标签 | backend、api、notification-center |
|
||||
| 依赖 | BE-HITL-013、BE-HITL-016 |
|
||||
| 描述 | 按 PRD Milestone 4 提供“审批人是 member”的最小通知中心后端接口:查询待处理 HITL task、查看 task 状态、提交 task。完整站内通知中心和 CLI 待办能力后续专题讨论。 |
|
||||
| 验收标准 | 1. 只覆盖 Dify member / workspace member 审批人。<br>2. 查询结果只返回当前登录用户可审批 task。<br>3. 提交仍复用动态授权和原子提交逻辑。<br>4. 不扩展完整 CLI 待办能力。 |
|
||||
|
||||
### BE-HITL-031:后端联调支持与测试证据包
|
||||
|
||||
| 字段 | 内容 |
|
||||
|-|-|
|
||||
| Linear 操作 | 新建 |
|
||||
| 团队 | `WTA` |
|
||||
| 项目 | `HITL IM 支持` |
|
||||
| 里程碑 | `测试` |
|
||||
| 优先级 | 高 |
|
||||
| 状态 | 待办 |
|
||||
| 截止日期 | 2026-07-27 |
|
||||
| 标签 | backend、test、release |
|
||||
| 依赖 | BE-HITL-018、BE-HITL-019、BE-HITL-023、BE-HITL-024、BE-HITL-025、BE-HITL-026、BE-HITL-027、BE-HITL-028、BE-HITL-029 |
|
||||
| 描述 | 整理后端联调环境、provider sandbox、migration dry run、单测 / 集成测试结果、安全回归记录和已知限制,供 2026-07-27 测试 milestone 接手。 |
|
||||
| 验收标准 | 1. 后端 API contract 与前端联调范围一致。<br>2. 每个纳入范围的 provider 有 sandbox E2E 或明确降级 / out-of-scope 结论。<br>3. migration dry run 和 rollback 记录齐备。<br>4. P0/P1 后端缺陷为 0 或有明确 no-go。<br>5. 测试证据可贴入 PR 描述或 Linear 项目文档。 |
|
||||
|
||||
## 不进入本次后端 Linear 清单的事项
|
||||
|
||||
| 事项 | 原因 |
|
||||
|-|-|
|
||||
| 前端 Contact / IM Integration / HITL 节点配置 / Last Run UI | 用户本次要求只包含后端工作。 |
|
||||
| QA 具体执行用例 | QA 可以单独维护测试明细;本清单只保留后端测试支持与证据包。 |
|
||||
| 导入导出 / DSL ID-Email 转换 | PRD revision 1959 明确移出本期 Milestone 4。 |
|
||||
| 完整站内通知中心和 CLI 待办能力 | PRD 仅建议优先考虑 member 通知中心接口,完整能力后续专题讨论。 |
|
||||
| SaaS 除 Slack 外的其他 IM ISV / Marketplace 接入 | PRD 非目标;本期 SaaS 仅 Slack ISV / OAuth 与钉钉企业自建应用。 |
|
||||
378
hitl_phase2_decisions.md
Normal file
378
hitl_phase2_decisions.md
Normal file
@ -0,0 +1,378 @@
|
||||
# HITL Phase 2 Decisions
|
||||
|
||||
## Decision 1: Email Matching
|
||||
|
||||
决策日期:2026-07-09
|
||||
|
||||
适用范围:
|
||||
|
||||
- `external contact` 创建时的 Dify Account 匹配
|
||||
- 旧 Email recipient 迁移
|
||||
- `dynamic Email` 与现有联系人匹配
|
||||
- `Recipient canonicalization` / Email recipient 去重
|
||||
|
||||
决策:
|
||||
|
||||
- 本期将 `normalized email` 定义为:对完整 email 字符串执行 `str.lower()` 后得到的结果。
|
||||
- 比较规则为:两个 email 在分别执行 `str.lower()` 后,结果完全相等,则视为同一个 email identity。
|
||||
|
||||
示意:
|
||||
|
||||
```text
|
||||
normalized_email = email.str.lower()
|
||||
same_email = left.str.lower() == right.str.lower()
|
||||
```
|
||||
|
||||
本期明确不做:
|
||||
|
||||
- 不做 `+tag` 消解
|
||||
- 不做 `.` 折叠
|
||||
- 不做 provider-specific 规则
|
||||
- 不做 domain / local-part 分段差异化处理
|
||||
|
||||
例子:
|
||||
|
||||
- `Alice@Example.com` 和 `alice@example.com`:视为相同
|
||||
- `alice+ops@example.com` 和 `alice@example.com`:视为不同
|
||||
- `alice.smith@example.com` 和 `alicesmith@example.com`:视为不同
|
||||
|
||||
影响说明:
|
||||
|
||||
- 这是一条最小规则,目标是先让 `external contact` 判定、旧数据迁移、recipient 去重和 `dynamic Email` 匹配行为一致。
|
||||
- 该规则不试图表达邮箱协议或特定 provider 的全部语义,只定义本期产品比较规则。
|
||||
|
||||
待回写 PRD 的章节:
|
||||
|
||||
- §7.5 外部联系人
|
||||
- §11.3 旧数据迁移
|
||||
- §18.6 Recipient canonicalization 与去重
|
||||
- §18.7 Sync、导入导出与迁移一致性
|
||||
|
||||
---
|
||||
|
||||
## Decision 2: IM Card Approval vs Web App Approval Auth
|
||||
|
||||
决策日期:2026-07-09
|
||||
|
||||
适用范围:
|
||||
|
||||
- IM 卡片内审批
|
||||
- IM 通知后跳转到 Web App 独立页面审批
|
||||
- external contact / one-time Email / dynamic Email 的 Web App 审批入口
|
||||
- PRD 中 `IM identity`、`IM fallback URL`、`Email OTP` 的关系定义
|
||||
|
||||
决策:
|
||||
|
||||
- `IM 卡片内审批` 与 `Web App 独立页面审批` 是两条不同的鉴权链路。
|
||||
- `IM 卡片内审批`:通过 IM 平台身份识别用户,再映射到 Dify contact / IM binding,提交时按 IM 身份链路鉴权。
|
||||
- `Web App 独立页面审批`:不依赖 IM 平台身份,统一走 OTP 作为验证手段。
|
||||
- 因此,`Web App 独立页面审批` 不应再被表述为 “IM 身份获取失败后的 fallback 鉴权”,而应被表述为一条独立的审批入口与鉴权规则。
|
||||
|
||||
本期明确不做:
|
||||
|
||||
- 不把 `Web App 独立页面审批` 建模为 IM 身份 fallback
|
||||
- 不要求 Web App 打开页复用 IM provider identity
|
||||
- 不在这条决策里同时保留 `Magic Link 或 OTP` 的双方案表述
|
||||
|
||||
影响说明:
|
||||
|
||||
- IM provider 能力矩阵中的 “可获取平台身份(鉴权)” 应只描述 IM 卡片内审批或 IM 原生交互场景,不应外溢到 Web App 独立页面审批。
|
||||
- PRD 中涉及 `IM fallback URL` 的文案需要收敛,避免把 “独立 Web 页面审批” 与 “IM 身份 fallback” 混写。
|
||||
- external contact / one-time Email / dynamic Email 的 Web 页面审批规则应统一引用 OTP。
|
||||
|
||||
待回写 PRD 的章节:
|
||||
|
||||
- §17 URL 鉴权与访问控制
|
||||
- §17.3 不同对象的鉴权方式
|
||||
- §17.5 不同场景的策略
|
||||
- §18.5 IM 渠道能力矩阵
|
||||
|
||||
---
|
||||
|
||||
## Decision 3: Default Dual-Channel Delivery
|
||||
|
||||
决策日期:2026-07-09
|
||||
|
||||
适用范围:
|
||||
|
||||
- §9.1 默认双渠道触达
|
||||
- §9.2 IM 通知
|
||||
- §18.5 IM 渠道能力矩阵
|
||||
- HITL task 运行时通知派发语义
|
||||
|
||||
决策:
|
||||
|
||||
- 对于具有 IM binding 且 Email 可用的 recipient,本期默认并行发送 IM 与 Email。
|
||||
- 这里的“并行发送”指两个渠道都被创建为当前 task 的 delivery attempt;不会等待某一侧成功或失败后再决定是否发送另一侧。
|
||||
- provider 能力只影响 IM 侧的投递形态:
|
||||
- 支持卡片内审批:发送 IM 卡片。
|
||||
- 不支持卡片内审批但支持 IM 通知:发送 IM 消息 + fallback URL。
|
||||
- Email 在本期仍然是必发渠道;不会因为 IM 已发送、IM 成功、IM 失败或 provider 能力差异而被跳过。
|
||||
- 多渠道触达不改变审批主体语义:同一个 recipient 仍只对应一个 `allowed approver`,IM 与 Email 只是同一审批对象的多个 delivery channel。
|
||||
|
||||
本期明确不做:
|
||||
|
||||
- 不做“先 IM,后 Email”的串行降级。
|
||||
- 不做“只有 IM 失败才发 Email”的条件发送。
|
||||
- 不做按 provider 能力关闭 Email 双发。
|
||||
- 不做按用户、workspace 或 provider 配置通知优先级。
|
||||
|
||||
影响说明:
|
||||
|
||||
- 这条规则消除了“默认双渠道触达”在运行时语义上的歧义,避免实现层把它理解为串行降级或 provider 决定是否发 Email。
|
||||
- `provider capability` 只负责决定 IM 通知长什么样,不负责决定 Email 是否发送。
|
||||
|
||||
待回写 PRD 的章节:
|
||||
|
||||
- §9.1 默认双渠道触达
|
||||
- §9.2 IM 通知
|
||||
- §18.5 IM 渠道能力矩阵
|
||||
|
||||
---
|
||||
|
||||
## Decision 4: Dynamic Authorization at Submit Time
|
||||
|
||||
决策日期:2026-07-09
|
||||
|
||||
适用范围:
|
||||
|
||||
- pending HITL task 的最终提交资格判定
|
||||
- IM 绑定联系人通过 IM 卡片或其他 IM 身份链路提交
|
||||
- 提交时 `Dify identity -> IM Binding -> valid contact` 的再校验规则
|
||||
- 联系人、IM binding、contact 记录在 task 创建后发生变化时的提交行为
|
||||
|
||||
决策:
|
||||
|
||||
- 本期采用 `动态授权`。
|
||||
- HITL task 是否允许提交,始终以 `提交当时` 的 Dify 身份与 IM Binding 状态为准,而不是只依赖 task 创建时 snapshot。
|
||||
- 对于需要按 IM 身份提交的链路,系统在提交时必须使用当前的 `im_user_id` 去查找当前有效的 IM Binding。
|
||||
- 如果提交当时找不到 `im_user_id` 对应的 binding,则不允许提交。
|
||||
- 如果能找到 binding,但该 binding 已经无法继续提交,例如已经没有有效的 contact 记录,则不允许提交。
|
||||
- 历史 snapshot 仍然用于审计、展示和问题排查,但不单独构成提交授权。
|
||||
|
||||
本期明确不做:
|
||||
|
||||
- 不采用 “task 创建时拿到链接就永久可提” 的快照授权模型
|
||||
- 不允许旧 binding 在提交时绕过当前 binding / contact 状态继续提交
|
||||
- 不把历史 snapshot 当作提交权限本身
|
||||
|
||||
影响说明:
|
||||
|
||||
- 这条规则把 pending task 的提交资格收敛为“实时安全状态判定”,会直接影响成员离开 workspace、IM binding 删除/替换、contact 失效后的提交结果。
|
||||
- PRD 中凡是写到 “pending task 默认建议重新校验” 的地方,都应升级为明确规则,而不是保留为建议。
|
||||
- 提交校验应区分“审计快照保留”和“实时提交授权”两件事:前者保留历史,后者只看当前有效身份链路。
|
||||
|
||||
待回写 PRD 的章节:
|
||||
|
||||
- §17.2 基本原则
|
||||
- §17.3 不同对象的鉴权方式
|
||||
- §17.4 打开页面与提交表单的校验
|
||||
- §18.2 联系人生命周期
|
||||
- §18.9 变更影响矩阵
|
||||
|
||||
---
|
||||
|
||||
## Decision 5: Import/Export and ID-Email Conversion Out of Scope
|
||||
|
||||
决策日期:2026-07-09
|
||||
|
||||
适用范围:
|
||||
|
||||
- §11.2 导入导出
|
||||
- §15 Milestone 4 中的 “DSL 导入导出 ID / Email 转换”
|
||||
- 任何将联系人 ID、external contact、one-time Email、dynamic Email 在环境之间导入、导出、转换的实现范围判断
|
||||
|
||||
决策:
|
||||
|
||||
- `导入导出 / DSL ID-Email 转换` 不作为本期目标。
|
||||
- 本期只保留与现网兼容直接相关的:
|
||||
- 旧 Email recipient 到新模型的迁移
|
||||
- SaaS / CE 初始化迁移
|
||||
- 不应把跨环境导入、导出、ID 映射恢复、Email 转换恢复视为本期交付范围。
|
||||
|
||||
本期明确不做:
|
||||
|
||||
- 不做 DSL 导出时的联系人快照映射规则
|
||||
- 不做 DSL 导入时的联系人恢复、ID 匹配、Email 回填
|
||||
- 不做 external contact / one-time Email / dynamic Email 的跨环境转换策略
|
||||
- 不把 `Milestone 4` 中的 `DSL 导入导出 ID / Email 转换` 视为当前版本目标
|
||||
|
||||
影响说明:
|
||||
|
||||
- 当前缺的不是范围决策,而是 PRD 回写一致性。
|
||||
- §11.2 已经整体划掉,因此 Milestone 4 中对应条目应删除、后移,或显式标注为后续阶段。
|
||||
- 评审文档里不应再把这个问题列为“待产品回答的 blocker”,而应标记为“已决策但 PRD 未回写一致”。
|
||||
|
||||
待回写 PRD 的章节:
|
||||
|
||||
- §11.2 导入导出
|
||||
- §15 Milestone 4
|
||||
|
||||
---
|
||||
|
||||
## Decision 6: Allowed Approver Is Contact-Centric and Fixed at Delivery Time
|
||||
|
||||
决策日期:2026-07-09
|
||||
|
||||
适用范围:
|
||||
|
||||
- `allowed approver` 的产品语义
|
||||
- 通知发送 / Email 发送时的审批主体确定与记录
|
||||
- `Contact`、`Dify Account`、`External Contact` 在审批时的关系
|
||||
- Member Contact / External Contact 的提交鉴权方式
|
||||
|
||||
决策:
|
||||
|
||||
- `allowed approver` 在发送通知 / Email 时确定,并作为 task 运行时记录的一部分保留下来。
|
||||
- 从产品语义上,审批主体以 `Contact` 为中心,而不是以单纯的 `email`、`session` 或裸 `account_id` 为中心。
|
||||
- 系统向每个 `Contact` 发送通知;该 `Contact` 在运行时对应一个被记录的 `allowed approver`。
|
||||
- 如果 `Contact` 关联了 `Dify Account`,则它属于 `Workspace Member Contact` 或 `Org-wide Member Contact`:
|
||||
- 审批时需要登录 Dify;
|
||||
- 或者在 IM 链路中,先用 IM user identity resolve 到对应的 `Dify Account`,再按该账号完成审批。
|
||||
- 如果 `Contact` 没有关联 `Dify Account`,则它属于 `External Contact`:
|
||||
- 审批时只能通过独立表单页提交;
|
||||
- 提交表单时必须使用 `Email OTP` 证明对该邮箱的控制权。
|
||||
- `IM` 与 `Email` 是 delivery channel,不改变审批主体本身;同一个 `Contact` 即使双渠道触达,也仍然只对应一个审批主体。
|
||||
- `Current initiator` 仍然是单独的 allowlist 来源;本决策只澄清“由通知发送产生的 allowed approver”的主体语义。
|
||||
|
||||
本期明确不做:
|
||||
|
||||
- 不把 `allowed approver` 建模为“谁拿到链接谁都能批”
|
||||
- 不把 `allowed approver` 简化为裸 `email` identity
|
||||
- 不把 `IM` 与 `Email` 视为两个独立审批主体
|
||||
|
||||
影响说明:
|
||||
|
||||
- 这条决策收敛了 `allowed approver` 的主体粒度:通知目标先落到 `Contact`,审批时再根据该 `Contact` 是否关联 `Dify Account` 决定鉴权链路。
|
||||
- 它会直接影响 recipient resolution、allowed approver 持久化、审计、去重以及提交鉴权。
|
||||
- PRD 中如果继续只写“任意一个 allowed approver 成功提交”而不解释 allowed approver 的记录时机和主体粒度,读者仍会误解成账号级或邮箱级概念。
|
||||
|
||||
待回写 PRD 的章节:
|
||||
|
||||
- §8.5 Allow Current Initiator to Approve
|
||||
- §9.4 提交规则
|
||||
- §10.1 HITL Task
|
||||
- §16.2 需要记录的信息
|
||||
- §17.3 不同对象的鉴权方式
|
||||
- §18.6 Recipient canonicalization 与去重
|
||||
|
||||
---
|
||||
|
||||
## Decision 7: Task Accessibility Follows Existing HumanInputFormStatus
|
||||
|
||||
决策日期:2026-07-09
|
||||
|
||||
适用范围:
|
||||
|
||||
- `task 是否可访问`
|
||||
- `task 是否可提交`
|
||||
- Web App 独立页面打开与提交
|
||||
- §10.1 HITL Task
|
||||
- §17.4 打开页面与提交表单的校验
|
||||
|
||||
决策:
|
||||
|
||||
- 本期 `task 可访问状态` 直接复用现有 `HumanInputFormStatus` 语义,不再额外发明一套页面状态。
|
||||
- 只有 `WAITING` 状态的 form/task 允许继续打开和提交。
|
||||
- `SUBMITTED`、`TIMEOUT`、`EXPIRED` 均视为不可访问 / 不可提交状态。
|
||||
- 即使 form.status 仍为 `WAITING`,只要已经超过节点级 `expiration_time`,也应视为不可访问 / 不可提交。
|
||||
- 即使 form.status 仍为 `WAITING`,只要已经超过全局超时 deadline,也应视为不可访问 / 不可提交。
|
||||
- `task 不存在` 与 `task 不可访问` 是两类不同结果:
|
||||
- 不存在:`not found`
|
||||
- 已提交 / 已超时 / 已过期 / 已过 deadline:`expired/submitted`
|
||||
|
||||
示意:
|
||||
|
||||
```text
|
||||
accessible = (
|
||||
status == WAITING
|
||||
and now < expiration_time
|
||||
and now < global_deadline
|
||||
and not submitted
|
||||
)
|
||||
```
|
||||
|
||||
本期明确不做:
|
||||
|
||||
- 不新增独立于 `HumanInputFormStatus` 之外的“可访问状态枚举”
|
||||
- 不把 `canceled`、`delivery_failed` 直接当作现有页面访问状态使用
|
||||
- 不允许 `WAITING` 但已过节点/全局 deadline 的 form 继续打开或提交
|
||||
|
||||
影响说明:
|
||||
|
||||
- 这条决策解决的是 `§17.4` 中“task 是否仍处于可访问状态”的落地语义。
|
||||
- 它不解决 `§10.1` 中更大的状态机冲突;`canceled`、`delivery_failed` 是否进入本期、以及如何映射到现有实现,仍然需要单独收敛。
|
||||
- 在现有代码里,这条规则已经存在于 `HumanInputService.ensure_form_active()` 和 `HumanInputFileUploadService._ensure_form_model_active()` 中,PRD 只需要回写一致。
|
||||
|
||||
待回写 PRD 的章节:
|
||||
|
||||
- §10.1 HITL Task
|
||||
- §17.4 打开页面与提交表单的校验
|
||||
|
||||
---
|
||||
|
||||
## Decision 8: Task State Machine Follows Existing HumanInputFormStatus
|
||||
|
||||
决策日期:2026-07-09
|
||||
|
||||
适用范围:
|
||||
|
||||
- HITL form/task 状态机
|
||||
- §10.1 HITL Task
|
||||
- 节点级 timeout 与全局 expired 的分层
|
||||
- `canceled` / `delivery_failed` 在本期中的归属
|
||||
|
||||
决策:
|
||||
|
||||
- 本期 form/task 状态机直接复用现有 `HumanInputFormStatus`,状态集合固定为:
|
||||
- `WAITING`
|
||||
- `SUBMITTED`
|
||||
- `TIMEOUT`
|
||||
- `EXPIRED`
|
||||
- 允许的核心转移为:
|
||||
- `WAITING -> SUBMITTED`
|
||||
- `WAITING -> TIMEOUT`
|
||||
- `WAITING -> EXPIRED`
|
||||
- `TIMEOUT` 表示节点级超时:
|
||||
- human input 节点沿 timeout 语义恢复;
|
||||
- 在 agent ask-human 语义中映射为 `timeout` 结果。
|
||||
- `EXPIRED` 表示全局超时:
|
||||
- workflow run 视为全局截止;
|
||||
- 该 form 不允许继续 resume。
|
||||
- `SUBMITTED` 表示已有 recipient 成功提交;进入终态。
|
||||
- 本期不把 `canceled` 纳入现有 form 状态机。
|
||||
- 本期不把 `delivery_failed` 纳入现有 form 状态机。
|
||||
- 如果产品仍需要 `canceled` 或 `delivery_failed`,它们只能作为:
|
||||
- workflow run / node outcome
|
||||
- 或 delivery / error reason
|
||||
进行建模,而不是新增为当前 `HumanInputFormStatus`。
|
||||
|
||||
示意:
|
||||
|
||||
```text
|
||||
WAITING -> SUBMITTED
|
||||
WAITING -> TIMEOUT
|
||||
WAITING -> EXPIRED
|
||||
```
|
||||
|
||||
本期明确不做:
|
||||
|
||||
- 不新增 `CANCELED` form 状态
|
||||
- 不新增 `DELIVERY_FAILED` form 状态
|
||||
- 不保留一套与 `HumanInputFormStatus` 平行的 task/form 状态枚举
|
||||
|
||||
影响说明:
|
||||
|
||||
- 这条决策把“form/task 的状态机”和“workflow run 的失败结果”拆开了。
|
||||
- 它解决的是 `§10.1` 中 form 状态与转移的落地语义。
|
||||
- 它不替产品决定是否需要 `canceled`、`delivery_failed` 这两个概念;只限定它们不应直接进入当前 form 状态机。
|
||||
- 现有代码已经体现这条规则:
|
||||
- `mark_submitted()` 只会把 form 置为 `SUBMITTED`
|
||||
- `mark_timeout()` 只允许 `TIMEOUT / EXPIRED`
|
||||
- `ask_human_resume` 中 `WAITING` 重新 pause,`TIMEOUT` 映射 `timeout`,`EXPIRED` 不可 resume
|
||||
|
||||
待回写 PRD 的章节:
|
||||
|
||||
- §10.1 HITL Task
|
||||
- §10.4 节点报错规则
|
||||
- §18.9 变更影响矩阵
|
||||
156
hitl_phase2_linear_task_list.md
Normal file
156
hitl_phase2_linear_task_list.md
Normal file
@ -0,0 +1,156 @@
|
||||
# HITL Phase 2 Linear 任务清单
|
||||
|
||||
目标:2026-07-31 达到 PR ready to merge,不要求 SaaS 生产上线。
|
||||
来源排期:[hitl_phase2_schedule_plan.md](hitl_phase2_schedule_plan.md)
|
||||
QA 明细:[hitl_phase2_qa_task_list.md](hitl_phase2_qa_task_list.md)
|
||||
|
||||
## 使用口径
|
||||
|
||||
这个文件按“后续导入 Linear”的口径编写:每一行尽量对应一个 Linear issue。字段使用中文,但语义贴近 Linear:`任务编号`、`标题`、`团队`、`标签`、`优先级`、`状态`、`开始日期`、`截止日期`、`依赖`、`描述`、`验收标准`。
|
||||
|
||||
核心排期原则:
|
||||
|
||||
1. 先在 2026-07-10 至 2026-07-13 冻结前后端契约、API schema、mock fixture 和 provider contract,前端不能等后端全部实现完才开始。
|
||||
2. 2026-07-13 起,后端实现领域模型和 runtime,前端基于契约和 mock 并行开发 Human Roster、Contact Directory、节点配置、审批页和 Last Run。
|
||||
3. 2026-07-15 起,provider 后端 adapter 和 provider 前端配置 / 状态 UI 并行推进。
|
||||
4. 2026-07-22 至 2026-07-26 作为前后端真实接口联调、provider UI 收敛和前端 RC handoff 窗口。
|
||||
5. Linear 里只保留一个大的 QA 任务;具体测试拆分维护在 [hitl_phase2_qa_task_list.md](hitl_phase2_qa_task_list.md),QA 同事从 2026-07-27 进场。
|
||||
|
||||
## 当前代码基线
|
||||
|
||||
| 能力 | 当前状态 | Phase 2 处理 |
|
||||
|-|-|-|
|
||||
| Human Input 节点 DSL | 已有 `human-input` 节点,包含 form content、inputs、actions、timeout、delivery_methods。 | 保持旧 published DSL 兼容;Phase 2 新 schema 需要明确 node version / adapter / rollback。 |
|
||||
| 表单持久化 | 已有 `HumanInputForm`、`HumanInputDelivery`、`HumanInputFormRecipient`。 | 优先做 schema delta,不重复建设同义 task / delivery / recipient 表;如新增 task 表,必须给出桥接关系。 |
|
||||
| WebApp / Console / Service API / OpenAPI 表单提交 | 已有 token 获取、提交、暂停恢复和 surface 隔离。 | 增加 OTP、actor 校验、原子提交、audit,不重做基础 endpoint。 |
|
||||
| Email delivery | 已有 Email 配置、test send、Celery 发送、URL placeholder、feature gate。 | 增加 OTP、发送日志、投递状态、失败原因、限流和 secret redaction。 |
|
||||
| 文件上传 | 已有表单 upload token 和文件归属校验。 | 纳入安全回归,不作为 Phase 2 主路径新增项。 |
|
||||
| Provider | 后端没有 HITL provider adapter;前端 Slack / Teams 只是占位。 | Provider framework、provider adapter 和 provider 配置 UI 都是新增任务。 |
|
||||
| Human Roster | 现有 Agent Roster 与 Phase 2 Human Roster 语义不同,Human tab 禁用。 | 新增 Human Roster / Contact Directory / IM Binding 模型、API 和 UI。 |
|
||||
|
||||
## 里程碑
|
||||
|
||||
| 里程碑 | 日期 | 目标 |
|
||||
|-|-|-|
|
||||
| M1 范围冻结 | 2026-07-10 | 冻结节点策略、身份规则、OTP、RBAC、provider gate。 |
|
||||
| M2 契约冻结 | 2026-07-13 | 冻结 schema、API contract、mock fixture、provider contract,解除前端开发阻塞。 |
|
||||
| M3 Core alpha | 2026-07-18 | 后端 Email-only / Roster / resolver / OTP / 原子提交闭环,前端核心页面可基于 mock 跑通。 |
|
||||
| M4 前端主路径可联调 | 2026-07-21 | Human Roster、Contact Directory、节点配置、审批页、Last Run 前端主路径完成。 |
|
||||
| M5 Provider readiness | 2026-07-24 | Provider 后端和前端配置入口完成 gate 判定。 |
|
||||
| M6 前端 RC handoff | 2026-07-26 | 前后端真实接口联调、provider UI 收敛、前端 smoke 和 QA handoff 包完成。 |
|
||||
| M7 QA entry | 2026-07-27 | QA 接收可测环境、前端 RC build、provider sandbox 和测试矩阵。 |
|
||||
| M8 Merge readiness | 2026-07-31 | 测试证据、文档、回滚、安全、CI、review 全部 ready。 |
|
||||
|
||||
## Linear 任务
|
||||
|
||||
### M1 范围冻结
|
||||
|
||||
| 任务编号 | 标题 | 团队 | 标签 | 优先级 | 状态 | 开始日期 | 截止日期 | 依赖 | 描述 | 验收标准 |
|
||||
|-|-|-|-|-|-|-|-|-|-|-|
|
||||
| HITL-P2-001 | 冻结 Phase 2 节点兼容策略 | 后端、前端、工作流 | 决策、兼容性 | P0 | 待办 | 2026-07-10 | 2026-07-10 | - | 明确新逻辑节点、DSL version、导入导出、执行分流和回滚策略。 | 旧 `human-input` published workflow 不自动改写;旧运行路径可继续恢复;新 DSL 的执行入口明确。 |
|
||||
| HITL-P2-002 | 冻结现有表模型复用边界 | 后端、数据库 | 决策、迁移 | P0 | 待办 | 2026-07-10 | 2026-07-10 | HITL-P2-001 | 确认 `human_input_forms`、`human_input_form_deliveries`、`human_input_form_recipients` 是否作为 Phase 2 基表继续扩展。 | 若新增 task 表,必须列出与现有 form / delivery / recipient 的映射和迁移桥接;不能出现两套状态源。 |
|
||||
| HITL-P2-003 | 冻结身份与审批 actor 规则 | 后端、安全 | 决策、安全 | P0 | 待办 | 2026-07-10 | 2026-07-10 | HITL-P2-001 | 明确 WebApp、Service API、OpenAPI、Console、CLI、anonymous session、IM callback 的提交身份规则。 | `submitted_by`、allowed approver、anonymous session 边界和 current initiator 规则写入决策记录。 |
|
||||
| HITL-P2-004 | 冻结 Email OTP 与 fallback 鉴权规则 | 后端、前端、安全 | 决策、安全、OTP | P0 | 待办 | 2026-07-10 | 2026-07-10 | HITL-P2-003 | 明确 Email / fallback URL 沿用现有 token 定位表单,提交时如何二次校验。 | External、one-time、dynamic Email 提交必须校验 OTP;成员或 IM 提交是否需要 OTP 有明确裁决。 |
|
||||
| HITL-P2-005 | 冻结 Organization / RBAC 默认矩阵 | 后端、前端、安全、企业版、SaaS | 决策、RBAC | P0 | 待办 | 2026-07-10 | 2026-07-10 | - | 明确 EE / CE deployment 与 SaaS workspace 的 Organization 映射和默认权限矩阵。 | workspace admin 管 Human Roster;enterprise admin 管 EE Contact Directory 和 IM Integration;普通 member 权限边界明确。 |
|
||||
| HITL-P2-006 | 冻结 provider 首发 gate 与降级策略 | Provider、安全、发布 | 决策、Provider | P0 | 待办 | 2026-07-10 | 2026-07-10 | HITL-P2-004、HITL-P2-005 | 定义 Slack、钉钉、飞书 / Lark、Teams、企业微信的首发准入和 fallback 策略。 | 每个 provider 的 sync、send、identity verify、callback、Web fallback、delivery status 最小门禁明确;企业微信允许通知 + Web fallback。 |
|
||||
|
||||
### M2 契约冻结与前端解耦
|
||||
|
||||
| 任务编号 | 标题 | 团队 | 标签 | 优先级 | 状态 | 开始日期 | 截止日期 | 依赖 | 描述 | 验收标准 |
|
||||
|-|-|-|-|-|-|-|-|-|-|-|
|
||||
| HITL-P2-007 | 设计 Contact Directory / Human Roster / IM Binding 模型 | 后端、数据库 | 模型、Roster、IM | P0 | 待办 | 2026-07-10 | 2026-07-13 | HITL-P2-005 | 定义 workspace member、Dify account、external contact、Organization-scoped IM identity 的领域模型。 | 字段、唯一约束、索引、状态枚举、历史 snapshot 读取策略明确。 |
|
||||
| HITL-P2-008 | 设计 HITL task schema delta | 后端、数据库、工作流 | 模型、迁移 | P0 | 待办 | 2026-07-10 | 2026-07-13 | HITL-P2-002、HITL-P2-007 | 明确现有 form/delivery/recipient 字段哪些复用、哪些新增。 | 覆盖 recipient snapshot、delivery status、resolution、audit、provider callback metadata。 |
|
||||
| HITL-P2-009 | 定义 recipient resolver v2 契约 | 后端、前端、工作流 | API 契约、Resolver | P0 | 待办 | 2026-07-10 | 2026-07-13 | HITL-P2-003、HITL-P2-007、HITL-P2-008 | 定义前端保存的 recipient 配置 schema 和后端解析输出 schema。 | static contact、external contact、one-time Email、dynamic Email、current initiator、debug only notify me 的输入、输出、去重和错误语义明确。 |
|
||||
| HITL-P2-010 | 定义 Email OTP API 契约 | 后端、前端、安全 | API 契约、OTP | P0 | 待办 | 2026-07-10 | 2026-07-13 | HITL-P2-004、HITL-P2-008 | 定义 OTP 发送、重发、校验、错误码、rate limit 和前端状态机。 | 前端可基于 mock 开发;错误码覆盖过期、次数超限、email 不匹配、form 已完成。 |
|
||||
| HITL-P2-011 | 定义 delivery / audit / Last Run API 契约 | 后端、前端、工作流 | API 契约、Last Run、审计 | P0 | 待办 | 2026-07-10 | 2026-07-13 | HITL-P2-008 | 定义 Last Run 展示所需的数据结构和审计事件字段。 | resolved recipients、变量值、投递状态、失败原因、submitted_by、submitted_at、channel 字段明确。 |
|
||||
| HITL-P2-012 | 定义 Provider adapter contract | 后端、Provider、前端 | API 契约、Provider | P0 | 待办 | 2026-07-10 | 2026-07-13 | HITL-P2-006、HITL-P2-007、HITL-P2-008 | 定义 credential、test connection、Organization sync、send message、identity verify、callback、fallback URL、secret redaction 的接口。 | 后端 adapter 和前端 provider 配置 UI 可并行开发;mock provider schema 明确。 |
|
||||
| HITL-P2-013 | 输出前端 mock fixture 与接口 stub | 前端、后端 | 前端、Mock、API 契约 | P0 | 待办 | 2026-07-11 | 2026-07-13 | HITL-P2-009、HITL-P2-010、HITL-P2-011、HITL-P2-012 | 为前端提供 Human Roster、Contact Directory、recipient selector、OTP、Last Run、provider 配置的 mock 数据。 | 前端可以不等待真实后端完成即开始主路径开发;mock fixture 与 API 契约字段一致。 |
|
||||
| HITL-P2-014 | 定义 migration dry run 与回滚方案 | 后端、数据库、发布 | 迁移、回滚 | P0 | 待办 | 2026-07-10 | 2026-07-13 | HITL-P2-008 | 明确 schema migration、backfill、dry run、rollback 和运行中 task snapshot 策略。 | 旧 workflow 不失效;运行中 form/task 使用创建时 snapshot;migration 可 dry run、可回滚、可重复执行。 |
|
||||
|
||||
### M3 后端核心开发
|
||||
|
||||
| 任务编号 | 标题 | 团队 | 标签 | 优先级 | 状态 | 开始日期 | 截止日期 | 依赖 | 描述 | 验收标准 |
|
||||
|-|-|-|-|-|-|-|-|-|-|-|
|
||||
| HITL-P2-015 | 实现 Contact Directory / Human Roster / IM Binding migration | 后端、数据库 | 迁移、Roster、IM | P0 | 待办 | 2026-07-13 | 2026-07-16 | HITL-P2-007、HITL-P2-014 | 新增或扩展 Contact、Roster、IM Binding 相关表结构。 | 新表、索引、唯一约束和回滚脚本完成;Organization scope 不泄露跨 workspace / deployment 数据。 |
|
||||
| HITL-P2-016 | 实现 Human Roster API | 后端、安全 | API、Roster、RBAC | P0 | 待办 | 2026-07-13 | 2026-07-17 | HITL-P2-015 | 实现 Human Roster 初始化、列表、搜索、external contact 管理和禁用状态过滤。 | workspace admin 可管理;普通 member 不可浏览完整 Roster;成员离开后不可新选。 |
|
||||
| HITL-P2-017 | 实现 Contact Directory 与 IM Integration 管理 API | 后端、安全、Provider | API、IM、RBAC | P0 | 待办 | 2026-07-13 | 2026-07-17 | HITL-P2-015、HITL-P2-012 | 实现 provider credential、test connection、sync trigger、IM binding 状态查询 API。 | enterprise admin 可操作;secret 不出响应和日志;前端可接真实接口。 |
|
||||
| HITL-P2-018 | 实现 recipient resolver v2 | 后端、工作流 | Resolver、运行时 | P0 | 待办 | 2026-07-13 | 2026-07-18 | HITL-P2-009、HITL-P2-016 | 实现各类 recipient 配置解析、去重、snapshot 和错误处理。 | dynamic Email 不反查 Account / Contact;current initiator 解析符合决策;输出 durable snapshot。 |
|
||||
| HITL-P2-019 | 接入 Phase 2 节点执行分流 | 后端、工作流 | DSL、兼容性、运行时 | P0 | 待办 | 2026-07-14 | 2026-07-18 | HITL-P2-001、HITL-P2-008、HITL-P2-018 | 按 node version / schema 将新节点路由到 v2 resolver 和新 delivery pipeline。 | 旧 `human-input` 行为不变;新 DSL 走 v2 path;导入旧 DSL 可兼容。 |
|
||||
| HITL-P2-020 | 实现 Email OTP 后端能力 | 后端、安全 | OTP、Email、安全 | P0 | 待办 | 2026-07-13 | 2026-07-18 | HITL-P2-010、HITL-P2-018 | 实现 OTP 生成、发送、重发、校验、过期和次数限制。 | External、one-time、dynamic Email 提交必须带有效 OTP;错误码稳定。 |
|
||||
| HITL-P2-021 | 实现原子 first-writer-wins 提交 | 后端、数据库、安全 | 并发、提交 | P0 | 待办 | 2026-07-14 | 2026-07-18 | HITL-P2-008、HITL-P2-020 | 修复现有提交路径不是原子更新的问题。 | 同一 task/form 并发提交只有一个成功;失败方返回已完成状态;单测覆盖 race。 |
|
||||
| HITL-P2-022 | 扩展 delivery record 状态机 | 后端、工作流、Provider | Delivery、状态机 | P0 | 待办 | 2026-07-14 | 2026-07-18 | HITL-P2-008、HITL-P2-012 | 记录 pending/sent/failed/submitted、provider message id、failure reason、sent_at、submitted_by、channel。 | 现有 Email delivery 写入状态;provider 可复用同一状态机。 |
|
||||
| HITL-P2-023 | 实现 audit record 写入与脱敏 | 后端、安全 | 审计、脱敏 | P0 | 待办 | 2026-07-15 | 2026-07-18 | HITL-P2-011、HITL-P2-020、HITL-P2-021、HITL-P2-022 | 记录提交、拒绝、校验失败、投递失败等审计事件。 | 能回答谁在什么时候、通过什么身份、用什么 channel 提交或被拒绝;审计不记录完整敏感正文和 secret。 |
|
||||
| HITL-P2-024 | 实现 Email 必发与最小发送 guardrails | 后端、SaaS、安全 | Email、限流、风控 | P0 | 待办 | 2026-07-15 | 2026-07-18 | HITL-P2-020、HITL-P2-022 | 实现 IM + Email 双发策略、dynamic Email 发送记录和最小限流。 | 有 IM binding 时 IM + Email 双发;无 IM binding 时 Email;发送失败原因可见。 |
|
||||
|
||||
### M4 前端核心开发
|
||||
|
||||
| 任务编号 | 标题 | 团队 | 标签 | 优先级 | 状态 | 开始日期 | 截止日期 | 依赖 | 描述 | 验收标准 |
|
||||
|-|-|-|-|-|-|-|-|-|-|-|
|
||||
| HITL-P2-025 | 实现 Human Roster 前端页面 | 前端 | 前端、Roster、RBAC | P0 | 待办 | 2026-07-13 | 2026-07-19 | HITL-P2-013、HITL-P2-016 | 启用 Roster 的 Human tab,接入 mock 后再切真实 API。 | workspace admin 可管理 Human Roster;成员离开/禁用状态可见且不可新选;普通 member 受限。 |
|
||||
| HITL-P2-026 | 实现 Contact Directory / IM Integration 前端页面 | 前端、企业版、Provider | 前端、IM、Provider | P0 | 待办 | 2026-07-13 | 2026-07-20 | HITL-P2-013、HITL-P2-017 | 实现 credential 表单、test connection、sync trigger、IM binding 状态和错误态。 | secret 输入不可回显;provider 不可用态可见;mock 和真实 API 字段兼容。 |
|
||||
| HITL-P2-027 | 实现 HITL 节点 recipient selector v2 | 前端、工作流 | 前端、节点配置、Resolver | P0 | 待办 | 2026-07-13 | 2026-07-20 | HITL-P2-009、HITL-P2-013 | 重做节点收件人选择器,支持新 recipient schema。 | 支持 static contact、external contact、one-time Email、dynamic Email variable chip、current initiator、debug only notify me;保存和回显正确。 |
|
||||
| HITL-P2-028 | 实现 Notification Policy 配置 UI | 前端、工作流、Provider | 前端、通知策略 | P0 | 待办 | 2026-07-14 | 2026-07-20 | HITL-P2-012、HITL-P2-013、HITL-P2-027 | 实现 Email 必发、IM + Email 双发、fallback 行为和 provider 不可用错误态配置。 | 旧 WebApp / Email 配置兼容显示;新 schema 可保存、回显、导入导出。 |
|
||||
| HITL-P2-029 | 实现 Web approval OTP 前端 | 前端、安全 | 前端、OTP、审批页 | P0 | 待办 | 2026-07-13 | 2026-07-20 | HITL-P2-010、HITL-P2-013 | 在独立审批页实现 OTP 输入、重发、错误态和提交状态机。 | 支持过期、次数超限、已提交、无权限、提交中、提交成功;移动端可用。 |
|
||||
| HITL-P2-030 | 实现 Last Run delivery / resolution 展示 | 前端、工作流 | 前端、Last Run | P1 | 待办 | 2026-07-14 | 2026-07-21 | HITL-P2-011、HITL-P2-013 | 在 Last Run 中展示 resolved recipients、投递状态、失败原因和提交人。 | 信息可读且不泄露敏感字段;空态和失败态明确。 |
|
||||
| HITL-P2-031 | 实现前端 i18n、空态、错误态和基础可访问性 | 前端 | 前端、i18n、可访问性 | P1 | 待办 | 2026-07-17 | 2026-07-21 | HITL-P2-025、HITL-P2-026、HITL-P2-027、HITL-P2-029、HITL-P2-030 | 补齐新增页面和组件的文案、空态、错误态、loading、disabled 和键盘可用性。 | 用户可见文案走 `web/i18n/en-US/`;关键按钮、输入框、错误提示在桌面和移动端不遮挡。 |
|
||||
| HITL-P2-032 | 前端核心路径 mock smoke | 前端 | 前端、Mock、Smoke | P1 | 待办 | 2026-07-19 | 2026-07-21 | HITL-P2-025、HITL-P2-026、HITL-P2-027、HITL-P2-028、HITL-P2-029、HITL-P2-030 | 使用 mock fixture 跑通主要前端路径,提前暴露 UI 和状态机问题。 | Human Roster、Contact Directory、节点配置、审批页、Last Run 均可在 mock 数据下完成 smoke。 |
|
||||
|
||||
### M5 Provider 后端与前端并行开发
|
||||
|
||||
| 任务编号 | 标题 | 团队 | 标签 | 优先级 | 状态 | 开始日期 | 截止日期 | 依赖 | 描述 | 验收标准 |
|
||||
|-|-|-|-|-|-|-|-|-|-|-|
|
||||
| HITL-P2-033 | 实现 provider adapter runtime 与 mock provider | 后端、Provider | Provider、运行时 | P0 | 待办 | 2026-07-15 | 2026-07-19 | HITL-P2-012、HITL-P2-022、HITL-P2-024 | 实现 provider runtime 基类、mock provider 和 pipeline 单测。 | mock provider 覆盖 credential、sync、send、identity verify、callback、fallback。 |
|
||||
| HITL-P2-034 | 实现 provider credential 与 callback 安全框架 | 后端、Provider、安全 | Provider、安全、Callback | P0 | 待办 | 2026-07-15 | 2026-07-20 | HITL-P2-017、HITL-P2-033 | 实现 credential 加密/脱敏、callback signature、state、replay 保护。 | 失败写入 delivery status 和 audit;secret 不进日志。 |
|
||||
| HITL-P2-035 | 实现 Slack 后端 adapter | Provider、后端 | Slack、Provider | P0 | 待办 | 2026-07-16 | 2026-07-22 | HITL-P2-033、HITL-P2-034 | 实现 Slack EE 自建应用与 SaaS OAuth 的 sync、send、verify、callback。 | 两条部署形态 sandbox E2E 通过;delivery status 和 audit 完整。 |
|
||||
| HITL-P2-036 | 实现 Slack 前端配置与状态 UI | 前端、Provider | Slack、前端、Provider | P1 | 待办 | 2026-07-18 | 2026-07-23 | HITL-P2-026、HITL-P2-028、HITL-P2-035 | 实现 Slack credential / OAuth 状态、test connection、sync 状态和 fallback 文案。 | Slack 配置入口可用;错误态可定位;未配置时节点给出清晰提示。 |
|
||||
| HITL-P2-037 | 实现钉钉后端 adapter | Provider、后端 | 钉钉、Provider | P0 | 待办 | 2026-07-16 | 2026-07-22 | HITL-P2-033、HITL-P2-034 | 实现 EE 与 SaaS 企业自建应用的 sync、send、callback、identity mapping。 | SaaS 租户接入路径可跑通;Web fallback 和 delivery record 完整。 |
|
||||
| HITL-P2-038 | 实现钉钉前端配置与状态 UI | 前端、Provider | 钉钉、前端、Provider | P1 | 待办 | 2026-07-18 | 2026-07-23 | HITL-P2-026、HITL-P2-028、HITL-P2-037 | 实现钉钉 credential、test connection、sync 状态、租户配置提示和 fallback 状态。 | 配置步骤与文档一致;错误态和权限不足提示明确。 |
|
||||
| HITL-P2-039 | 实现飞书 / Lark 后端 adapter | Provider、后端 | 飞书、Lark、Provider | P0 | 待办 | 2026-07-16 | 2026-07-22 | HITL-P2-033、HITL-P2-034 | 实现 EE 自建应用 sync、卡片通知、身份校验、提交回调。 | sandbox E2E 通过;失败回调写入 delivery status。 |
|
||||
| HITL-P2-040 | 实现飞书 / Lark 前端配置与状态 UI | 前端、Provider | 飞书、Lark、前端 | P1 | 待办 | 2026-07-18 | 2026-07-23 | HITL-P2-026、HITL-P2-028、HITL-P2-039 | 实现飞书 / Lark credential、test connection、sync 状态和 fallback 状态。 | 配置入口、错误态、同步结果展示可用。 |
|
||||
| HITL-P2-041 | 实现 Microsoft Teams 后端 adapter | Provider、后端 | Teams、Provider | P0 | 待办 | 2026-07-17 | 2026-07-23 | HITL-P2-033、HITL-P2-034 | 实现 Teams App、Adaptive Card 或 fallback message、identity verify、submit callback。 | Teams sandbox E2E 通过;fallback URL 可安全提交。 |
|
||||
| HITL-P2-042 | 实现 Microsoft Teams 前端配置与状态 UI | 前端、Provider | Teams、前端 | P1 | 待办 | 2026-07-19 | 2026-07-24 | HITL-P2-026、HITL-P2-028、HITL-P2-041 | 实现 Teams credential、test connection、sync 状态和 fallback 状态。 | Teams 配置入口可用;Adaptive Card / fallback 差异展示清楚。 |
|
||||
| HITL-P2-043 | 实现企业微信后端 adapter | Provider、后端 | 企业微信、Provider | P0 | 待办 | 2026-07-17 | 2026-07-23 | HITL-P2-033、HITL-P2-034 | 实现企业微信 sync、通知、身份校验和 Web fallback。 | 通知 + Web 审批页 E2E 通过;卡片内完整审批不作为硬门禁。 |
|
||||
| HITL-P2-044 | 实现企业微信前端配置与状态 UI | 前端、Provider | 企业微信、前端 | P1 | 待办 | 2026-07-19 | 2026-07-24 | HITL-P2-026、HITL-P2-028、HITL-P2-043 | 实现企业微信 credential、test connection、sync 状态、有限交互说明和 fallback 状态。 | UI 清楚表达企业微信能力边界;fallback 路径可见。 |
|
||||
| HITL-P2-045 | Provider readiness gate | Provider、后端、前端、发布 | Provider、Gate、发布 | P0 | 待办 | 2026-07-24 | 2026-07-24 | HITL-P2-035、HITL-P2-036、HITL-P2-037、HITL-P2-038、HITL-P2-039、HITL-P2-040、HITL-P2-041、HITL-P2-042、HITL-P2-043、HITL-P2-044 | 对每个 provider 做 go / fallback / out of scope 判定。 | 未通过 gate 的 provider 从 7.31 ready-to-merge 范围移出或在 UI 中降级;结论同步给 QA 和文档。 |
|
||||
|
||||
### M6 前后端联调与前端 RC handoff
|
||||
|
||||
| 任务编号 | 标题 | 团队 | 标签 | 优先级 | 状态 | 开始日期 | 截止日期 | 依赖 | 描述 | 验收标准 |
|
||||
|-|-|-|-|-|-|-|-|-|-|-|
|
||||
| HITL-P2-046 | Human Roster / Contact Directory 前后端真实接口联调 | 前端、后端 | 联调、Roster、IM | P0 | 待办 | 2026-07-22 | 2026-07-25 | HITL-P2-016、HITL-P2-017、HITL-P2-025、HITL-P2-026 | 将前端 mock 切到真实 API,处理分页、权限、错误码和空态。 | Roster、Contact Directory、IM Integration 主路径在真实环境可用。 |
|
||||
| HITL-P2-047 | HITL 节点配置与 runtime 前后端联调 | 前端、后端、工作流 | 联调、节点配置、运行时 | P0 | 待办 | 2026-07-22 | 2026-07-25 | HITL-P2-018、HITL-P2-019、HITL-P2-027、HITL-P2-028 | 将节点 recipient selector 和 Notification Policy 接入真实保存、发布、运行流程。 | 新 DSL 保存、回显、导入、发布、运行一致;旧 DSL 不回归。 |
|
||||
| HITL-P2-048 | Web approval OTP 与提交链路联调 | 前端、后端、安全 | 联调、OTP、审批页 | P0 | 待办 | 2026-07-22 | 2026-07-25 | HITL-P2-020、HITL-P2-021、HITL-P2-029 | 将审批页 OTP、提交、重复提交、过期、错误态接入真实 API。 | Email / fallback 表单在真实环境可安全打开和提交;并发提交只有一个成功。 |
|
||||
| HITL-P2-049 | Last Run / delivery / audit 联调 | 前端、后端、工作流 | 联调、Last Run、审计 | P1 | 待办 | 2026-07-23 | 2026-07-25 | HITL-P2-022、HITL-P2-023、HITL-P2-030 | 将 Last Run 展示接入真实 delivery / audit 数据。 | resolved recipients、投递状态、失败原因、submitted_by、submitted_at、channel 展示准确且脱敏。 |
|
||||
| HITL-P2-050 | Provider 配置 UI 与真实 adapter 联调 | 前端、Provider、后端 | 联调、Provider | P0 | 待办 | 2026-07-24 | 2026-07-26 | HITL-P2-045 | 按 gate 结论收敛 provider 配置入口、不可用态、fallback 文案、图标、test connection 和 sync 状态。 | 通过 gate 的 provider UI 可用;未通过 gate 的 provider 隐藏或降级;QA 不会拿到半成品入口。 |
|
||||
| HITL-P2-051 | 前端 RC 自测与质量门禁 | 前端 | 前端、Smoke、i18n | P0 | 待办 | 2026-07-25 | 2026-07-26 | HITL-P2-046、HITL-P2-047、HITL-P2-048、HITL-P2-049、HITL-P2-050 | 完成前端 smoke、移动端审批页检查、i18n key 检查、loading / empty / error / disabled 状态检查。 | 输出可测 build;`pnpm lint:fix` / `pnpm type-check` 或等价 CI 结果可追溯;关键页面截图或录屏齐备。 |
|
||||
| HITL-P2-052 | 前端 QA handoff 包 | 前端、QA、发布 | QA、Handoff | P0 | 待办 | 2026-07-26 | 2026-07-26 | HITL-P2-051 | 汇总前端可测范围、feature flag、配置步骤、已知限制、smoke checklist 和关键路径说明。 | QA 可在 2026-07-27 直接接手;handoff 包包含 build、账号/权限要求、provider UI 状态和已知问题。 |
|
||||
|
||||
### M7 QA 与发布准备
|
||||
|
||||
| 任务编号 | 标题 | 团队 | 标签 | 优先级 | 状态 | 开始日期 | 截止日期 | 依赖 | 描述 | 验收标准 |
|
||||
|-|-|-|-|-|-|-|-|-|-|-|
|
||||
| HITL-P2-053 | QA 进场与验收执行统筹 | QA、后端、前端、Provider、安全、发布 | QA、验收 | P0 | 待办 | 2026-07-27 | 2026-07-31 | HITL-P2-024、HITL-P2-045、HITL-P2-052 | QA 同事按 [hitl_phase2_qa_task_list.md](hitl_phase2_qa_task_list.md) 执行测试矩阵,P0/P1 缺陷进入每日 triage。 | 2026-07-28 前形成 RC1 结论;2026-07-31 前补齐测试证据包;P0/P1 为 0 或明确 no-go。 |
|
||||
| HITL-P2-054 | 完成配置与运维文档 | 文档、Provider、前端、发布 | 文档、运维 | P1 | 待办 | 2026-07-29 | 2026-07-31 | HITL-P2-045、HITL-P2-052、HITL-P2-053 | 完成 provider 配置、SaaS 钉钉自建应用、callback URL、credential 权限、前端 feature flag / 已知限制、migration、回滚文档。 | 文档可由 QA 按步骤复现;已知限制和 fallback 范围清楚。 |
|
||||
| HITL-P2-055 | 完成 PR 测试证据包 | QA、发布 | QA、发布 | P0 | 待办 | 2026-07-29 | 2026-07-31 | HITL-P2-053 | 汇总 CI、单测、集成测试、provider sandbox、migration dry run、安全测试结果。 | 证据集中到 PR 描述或附件;每个 ready-to-merge 范围内 provider 都有记录。 |
|
||||
| HITL-P2-056 | 完成 merge readiness review | 发布、后端、前端、安全、Provider | 发布、Review | P0 | 待办 | 2026-07-31 | 2026-07-31 | HITL-P2-054、HITL-P2-055 | 做最终 ready-to-merge review,确认测试、文档、迁移、回滚、安全和配置均就绪。 | 无 P0/P1;CI 通过;回滚方案明确;未通过 gate 的 provider 已移出 scope 或降级。 |
|
||||
|
||||
## Stretch / 非阻塞任务
|
||||
|
||||
| 任务编号 | 标题 | 团队 | 标签 | 优先级 | 状态 | 开始日期 | 截止日期 | 依赖 | 描述 | 验收标准 |
|
||||
|-|-|-|-|-|-|-|-|-|-|-|
|
||||
| HITL-P2-S1 | workspace 级 email service 配置 | 后端、前端、SaaS | Stretch、Email | P3 | 待办 | 2026-07-24 | 2026-07-31 | HITL-P2-024 | 支持 workspace 级 email service 配置,第一期只支持 Resend。 | 仅在 P0 安全和 provider gate 完成后推进;不阻塞 2026-07-31 merge readiness。 |
|
||||
| HITL-P2-S2 | 企业微信卡片内完整审批 | Provider、前端、后端 | Stretch、企业微信 | P3 | 待办 | 2026-07-24 | 2026-07-31 | HITL-P2-043、HITL-P2-044 | 尝试支持企业微信卡片内完整审批。 | 不作为首发硬门禁;通知 + Web fallback 已通过即可进入 ready-to-merge scope。 |
|
||||
| HITL-P2-S3 | Provider 自助诊断增强 | Provider、前端 | Stretch、诊断 | P3 | 待办 | 2026-07-24 | 2026-07-31 | HITL-P2-045 | 在 credential test 基础上增加权限缺失、callback URL、sync scope 的诊断提示。 | 不阻塞 merge;作为后续体验增强。 |
|
||||
|
||||
## Go / No-go Gate
|
||||
|
||||
| 日期 | Gate | Go 条件 | No-go 条件 |
|
||||
|-|-|-|-|
|
||||
| 2026-07-13 | 契约冻结 | schema、API contract、mock fixture、provider contract、migration 方案均冻结,前端可以并行开发。 | 前端仍缺 mock / API contract,或后端模型复用边界不清。 |
|
||||
| 2026-07-18 | Core alpha | 后端 Email-only HITL、Roster、resolver、OTP、原子提交闭环;前端核心页面 mock 主路径跑通。 | 核心模型、OTP、first-writer-wins 或前端主路径仍不可演示。 |
|
||||
| 2026-07-21 | 前端主路径可联调 | Human Roster、Contact Directory、节点配置、Web approval OTP、Last Run 前端主路径完成。 | 前端仍缺关键页面或状态机,无法接真实 API。 |
|
||||
| 2026-07-24 | Provider readiness | 纳入首发的 provider 至少完成 sync、send、identity verify、submit/fallback,前端配置入口具备可联调形态。 | 任一 provider 无法同步、发送或校验提交身份,且没有可接受 fallback。 |
|
||||
| 2026-07-26 | Frontend RC handoff | 前端完成真实接口联调、provider UI 收敛、自测、i18n / type-check 和 QA handoff 包。 | 前端仍缺可测 build、关键页面未联通、provider 降级态不明确、i18n / type-check 未过。 |
|
||||
| 2026-07-27 | QA entry | QA 同事进场,测试矩阵、环境、账号、provider sandbox、前端 RC build、缺陷 triage 节奏就绪。 | 仍缺可测环境、前端 RC build、关键 provider sandbox、测试账号或 RC 范围。 |
|
||||
| 2026-07-28 | RC1 | P0/P1 清零;migration dry run、RBAC、安全和核心集成测试通过。 | 存在数据丢失、越权提交、旧 workflow 失效、审计关键字段缺失风险。 |
|
||||
| 2026-07-31 | Merge readiness | CI、code review、测试证据、迁移说明、配置文档、监控建议、回滚方案、最小限流和发送日志均就绪。 | provider 大面积失败、SaaS abuse guardrail 未生效、审计缺关键字段,或仍有未关闭 P0/P1。 |
|
||||
118
hitl_phase2_qa_task_list.md
Normal file
118
hitl_phase2_qa_task_list.md
Normal file
@ -0,0 +1,118 @@
|
||||
# HITL Phase 2 QA 明细任务
|
||||
|
||||
目标:为 QA 同事提供执行明细;这些条目不逐条提交到 Linear。Linear 只保留 [hitl_phase2_linear_task_list.md](hitl_phase2_linear_task_list.md) 中的 `HITL-P2-053 — QA 进场与验收执行统筹` 一个大 QA 任务。
|
||||
|
||||
## QA 进场口径
|
||||
|
||||
| 项目 | 内容 |
|
||||
|-|-|
|
||||
| 进场日期 | 2026-07-27 |
|
||||
| 目标 | 2026-07-28 给出 RC1 结论,2026-07-31 前完成 ready-to-merge 测试证据包。 |
|
||||
| 输入物 | 可测环境、前端 RC build、前端 QA handoff 包、provider sandbox、测试账号、测试 workspace、migration dry run 环境、PR / branch、配置文档草稿。 |
|
||||
| 输出物 | 测试矩阵执行结果、P0/P1 缺陷列表、provider gate 结论、migration dry run 记录、安全回归记录、最终测试证据包。 |
|
||||
|
||||
## 进场前置条件
|
||||
|
||||
| # | 检查项 | 负责人 | 验收标准 |
|
||||
|-|-|-|-|
|
||||
| Q0.1 | 确认 RC scope | Product / Backend / Frontend / Provider | 明确哪些 provider 纳入 2026-07-31 ready-to-merge,哪些降级到 fallback,哪些移出范围。 |
|
||||
| Q0.2 | 准备测试环境 | Backend / DevOps | 环境包含最新 migration、前端 RC build、Celery、mail、provider callback URL、feature flags 和基础 seed data。 |
|
||||
| Q0.3 | 准备测试账号与权限 | Backend / QA | 至少覆盖普通 member、workspace admin、enterprise admin、Service API token、anonymous WebApp session。 |
|
||||
| Q0.4 | 准备 provider sandbox | Provider owners | 每个纳入范围的 provider 都有 credential、通讯录测试数据、可回调 URL 和失败注入方式。 |
|
||||
| Q0.5 | 准备缺陷 triage 节奏 | QA / Release | P0/P1 每日同步;blocker 有 owner、复现步骤、期望修复日期。 |
|
||||
| Q0.6 | 准备前端 QA handoff 包 | Frontend | 2026-07-26 前提供可测 build、feature flag / 配置说明、前端 smoke checklist、已知限制、关键页面截图或录屏。 |
|
||||
|
||||
## 测试执行矩阵
|
||||
|
||||
### 1. HITL 核心运行时
|
||||
|
||||
| # | 测试域 | 覆盖范围 | 验收标准 |
|
||||
|-|-|-|-|
|
||||
| Q1.1 | Email-only HITL | Email delivery、表单打开、OTP、提交、workflow resume、Last Run 展示。 | 一条 Email-only 工作流可端到端完成;提交后 downstream outputs 正确。 |
|
||||
| Q1.2 | WebApp HITL | WebApp delivery、Service API / OpenAPI surface、token 权限隔离。 | 只有允许 surface 可以拿到可提交 token;内部 console token 不被公开接口提交。 |
|
||||
| Q1.3 | Current initiator | WebApp、Service API、CLI / non-interactive initiator。 | current initiator snapshot 正确;anonymous WebApp session 只在原会话有效。 |
|
||||
| Q1.4 | Dynamic Email | 变量解析、发送、OTP、审计、日志。 | 不反查 Account / Contact;审计记录变量值、发送结果和提交校验结果。 |
|
||||
| Q1.5 | One-time Email | 节点配置、发送、OTP、提交。 | 不写入 Contact;重复提交只有一个成功。 |
|
||||
| Q1.6 | Debug only notify me | Debug mode、收件人覆盖、生产配置不受影响。 | Debug 只通知当前操作者;published run 使用真实配置。 |
|
||||
| Q1.7 | Form file inputs | 单文件、多文件、upload token、过期、租户归属。 | 文件上传只能绑定当前 form / recipient,跨租户文件不可提交。 |
|
||||
|
||||
### 2. 安全与滥用防护
|
||||
|
||||
| # | 测试域 | 覆盖范围 | 验收标准 |
|
||||
|-|-|-|-|
|
||||
| Q2.1 | OTP required | External、one-time、dynamic Email、fallback URL。 | 无 OTP、错误 OTP、过期 OTP、email 不匹配均不能提交。 |
|
||||
| Q2.2 | OTP retry limit | 重试次数、重发频率、过期后重发。 | 达到限制后返回稳定错误码,并写入 audit / rate limit 记录。 |
|
||||
| Q2.3 | Link forwarding | 收件人 A 将链接转发给 B。 | B 无法在没有匹配 OTP / identity 的情况下提交。 |
|
||||
| Q2.4 | Concurrent submit | 同一 task/form 多人或多请求同时提交。 | 只有一个 first-writer 成功,其余返回已完成状态。 |
|
||||
| Q2.5 | Rate limit | 表单打开、表单提交、OTP、dynamic Email 发送。 | 超限返回明确错误;不会继续发送邮件或写入成功提交。 |
|
||||
| Q2.6 | Secret redaction | Provider credential、Email body、IM body、日志和审计。 | secret 不进日志;消息正文不完整进入审计。 |
|
||||
| Q2.7 | Cross-tenant isolation | Roster、Contact Directory、IM Binding、form token、upload token。 | 不同 workspace / Organization / deployment 间不可越权读写。 |
|
||||
|
||||
### 3. Human Roster 与 Contact Directory
|
||||
|
||||
| # | 测试域 | 覆盖范围 | 验收标准 |
|
||||
|-|-|-|-|
|
||||
| Q3.1 | Roster initialization | workspace member 初始化、新成员进入、离职成员状态。 | 可新选成员只包含有效成员;历史 snapshot 仍可读。 |
|
||||
| Q3.2 | External contact | 创建、去重、禁用、搜索、权限。 | workspace admin 可管理;普通 member 不可浏览完整 Roster。 |
|
||||
| Q3.3 | Contact Directory | Organization-scoped contact、IM identity、同步结果。 | enterprise admin 可查看;SaaS workspace 不串数据。 |
|
||||
| Q3.4 | IM Binding | provider user id、email、Dify account/contact 映射。 | 绑定变更不影响运行中 task snapshot。 |
|
||||
|
||||
### 4. Provider 端到端测试
|
||||
|
||||
| # | Provider | 覆盖范围 | 验收标准 |
|
||||
|-|-|-|-|
|
||||
| Q4.1 | Slack | EE 自建应用、SaaS OAuth、sync、send、identity verify、submit、Email 双发。 | 两条部署形态 E2E 通过,delivery status 和 audit 完整。 |
|
||||
| Q4.2 | 钉钉 | EE / SaaS 企业自建应用、sync、send、callback、Web fallback。 | SaaS 租户接入文档可按步骤跑通。 |
|
||||
| Q4.3 | 飞书 / Lark | EE 自建应用、sync、卡片通知、身份校验、提交。 | sandbox E2E 通过;失败回调写入 delivery status。 |
|
||||
| Q4.4 | Microsoft Teams | Teams App、Adaptive Card 或 fallback、identity verify、submit。 | sandbox E2E 通过;fallback URL 可安全提交。 |
|
||||
| Q4.5 | 企业微信 | sync、通知、身份校验、Web fallback。 | 通知 + Web 审批页 E2E 通过;卡片内完整审批不是硬门禁。 |
|
||||
| Q4.6 | Provider failure | credential 错误、权限不足、rate limit、callback signature 错误。 | 失败原因可见;不会误标为 sent/submitted。 |
|
||||
|
||||
### 5. 迁移与兼容性
|
||||
|
||||
| # | 测试域 | 覆盖范围 | 验收标准 |
|
||||
|-|-|-|-|
|
||||
| Q5.1 | Existing published workflow | 旧 `human-input` DSL、旧 Email recipient、旧 WebApp token。 | 不自动改写;已发布 workflow 仍可执行和恢复。 |
|
||||
| Q5.2 | Running pause state | migration 前已有 waiting form/task。 | 使用创建时 snapshot;配置变更不影响运行中 task。 |
|
||||
| Q5.3 | Migration dry run | schema migration、seed / backfill、rollback。 | dry run 可重复执行;回滚步骤可复现。 |
|
||||
| Q5.4 | Import / export | workflow DSL 导入导出、版本分流。 | 旧 DSL 导入不丢字段;新 DSL 能正确落到 v2 path。 |
|
||||
|
||||
### 6. 前端回归
|
||||
|
||||
| # | 测试域 | 覆盖范围 | 验收标准 |
|
||||
|-|-|-|-|
|
||||
| Q6.1 | HITL node config | recipient selector、dynamic Email chip、one-time Email、current initiator、debug only notify me。 | 保存、回显、复制、导入、发布后配置一致。 |
|
||||
| Q6.2 | Human Roster UI | Human tab、权限、搜索、添加 external contact、状态展示。 | workspace admin 可操作;普通 member 受限。 |
|
||||
| Q6.3 | Contact Directory / IM UI | credential、test connection、sync、binding 状态、错误态。 | secret 不回显;失败提示可定位。 |
|
||||
| Q6.4 | Web approval page | OTP 输入、重发、过期、已提交、无权限、移动端。 | 状态文案清晰;不能出现表单内容遮挡或按钮不可点击。 |
|
||||
| Q6.5 | Last Run view | delivery、resolution、submitted_by、failure reason。 | 信息可读且不泄露敏感字段。 |
|
||||
|
||||
## 日期安排
|
||||
|
||||
| 日期 | QA 重点 | 输出物 |
|
||||
|-|-|-|
|
||||
| 2026-07-27 | 进场、环境核验、smoke、核心 HITL / OTP / Roster 首轮。 | 环境可测结论、P0 blocker、首轮 smoke 结果。 |
|
||||
| 2026-07-28 | RC1:核心 runtime、安全、migration、前端主路径、provider gate 回归。 | RC1 go / no-go、P0/P1 清单、provider 纳入范围。 |
|
||||
| 2026-07-29 | Provider sandbox E2E、安全与 abuse hardening 回归、migration dry run 复验。 | Provider E2E 记录、安全回归记录、migration 记录。 |
|
||||
| 2026-07-30 | 缺陷修复回归、文档步骤验收、测试证据整理。 | 测试证据包草稿、剩余风险列表。 |
|
||||
| 2026-07-31 | 最终验证、merge readiness review 支持。 | 最终 QA sign-off 或 no-go 理由。 |
|
||||
|
||||
## 缺陷分级
|
||||
|
||||
| 等级 | 定义 | Merge gate |
|
||||
|-|-|-|
|
||||
| P0 | 数据丢失、越权提交、跨租户泄露、旧 workflow 大面积失效、provider callback 可被伪造。 | 必须关闭。 |
|
||||
| P1 | 核心路径不可用、OTP / Email / provider 某一首发路径不可闭环、migration dry run 不可回滚。 | 必须关闭或从 scope 移出。 |
|
||||
| P2 | 单个非首发 provider 体验问题、可绕过的 UI 缺陷、非关键日志缺字段。 | 可带已知限制进入 review。 |
|
||||
| P3 | 文案、样式、诊断增强、非阻塞易用性问题。 | 不阻塞。 |
|
||||
|
||||
## QA 退出标准
|
||||
|
||||
| 标准 | 所需证据 |
|
||||
|-|-|
|
||||
| 核心运行时验收 | Email-only、WebApp、current initiator、dynamic Email、one-time Email、debug only notify me、并发提交测试记录。 |
|
||||
| 安全验收 | OTP、rate limit、cross-tenant、secret redaction、audit 测试记录。 |
|
||||
| Provider 验收 | 纳入 scope 的每个 provider sandbox E2E 记录和失败场景记录。 |
|
||||
| 迁移验收 | dry run、rollback、旧 DSL / running pause state 兼容记录。 |
|
||||
| 前端验收 | 节点配置、Roster、Contact Directory、Web approval、Last Run 展示截图或录屏。 |
|
||||
| 发布验收 | P0/P1 为 0;P2/P3 有 owner、风险说明和后续处理计划。 |
|
||||
113
hitl_phase2_schedule_plan.md
Normal file
113
hitl_phase2_schedule_plan.md
Normal file
@ -0,0 +1,113 @@
|
||||
# HITL Phase 2 Schedule Plan
|
||||
|
||||
来源 PRD:<https://langgenius.feishu.cn/wiki/GMFdwe40Oi2rC9klP2HcNjnHnwd>
|
||||
读取版本:revision 1389
|
||||
生成日期:2026-07-09
|
||||
目标交付窗口:2026-07-31(PR ready to merge,不要求 SaaS 生产上线)
|
||||
|
||||
## 排期结论
|
||||
|
||||
7 月底目标调整为代码合并准备就绪,可以按“通用 HITL/Roster/Email 能力先闭环,IM provider adapter 并行接入”的方式推进。关键约束是:2026-07-10 必须冻结 PRD 中仍未定稿的安全、身份、RBAC、provider 能力矩阵和新旧节点策略;2026-07-24 必须完成 provider readiness gate,否则 2026-07-31 只能将已通过 gate 的渠道纳入 ready-to-merge 范围。
|
||||
|
||||
## 首发范围
|
||||
|
||||
| 部署形态 | 首发 provider | 首发定义 |
|
||||
|-|-|-|
|
||||
| EE | Slack、飞书 / Lark、Microsoft Teams、钉钉、企业微信 | 管理后台可配置 provider credential;可发送 HITL 通知;可完成身份校验与提交;支持卡片审批的 provider 优先卡片内提交,不支持时走 Web 审批页 fallback。 |
|
||||
| SaaS | Slack ISV / OAuth、钉钉企业自建应用 | Slack 走 OAuth 安装;钉钉由 tenant / workspace 配置企业自建应用凭据;均接入统一 HITL task、delivery record、审计和 Email 双发链路。 |
|
||||
|
||||
本排期默认 CE 只复用通用 Human Roster、Email、HITL task 和迁移能力,不作为 provider 首发验收门禁。
|
||||
|
||||
## 核心假设
|
||||
|
||||
| 假设 | 说明 |
|
||||
|-|-|
|
||||
| Email 必发 | 与 PRD 保持一致:有 IM binding 时发送 IM + Email;无 IM binding 时发送 Email。 |
|
||||
| EE 单部署选择一个 IM provider | PRD 中“企业版一期只支持配置一个 IM 渠道”按“每个 EE deployment 同时启用一个 provider”理解;首发清单表示支持的可选 provider 集合。 |
|
||||
| IM identity 通过手动 IM 同步建立 | 首发需要支持管理员手动触发 IM 同步;同步 scope 是 Organization。EE / CE 中一个部署对应一个 Organization,SaaS 中一个 workspace 对应一个 Organization。 |
|
||||
| Email recipient 提交时使用 Email OTP | Email 发送的 Web Form URL 沿用现有 token,不新增额外 token;External / one-time / dynamic Email 在提交表单时必须包含 Email OTP。 |
|
||||
| 企业微信允许降级形态 | PRD 标注企业微信卡片能力有限,首发可按通知 + Web 审批页 fallback 验收,除非产品明确要求企业微信卡片内完整审批。 |
|
||||
|
||||
## 已定决策与待确认项
|
||||
|
||||
| 决策项 | 状态 / 截止日期 | 影响范围 | 排期处理 |
|
||||
|-|-|-|-|
|
||||
| 新节点还是原 Human Input 原地改造 | 已确定 | DSL、迁移、回滚、前端入口、后端 runtime path | 使用新节点和新 DSL 定义;保留旧节点代码和逻辑不变;Workflow 执行时根据 DSL 中的 node version 选择实现。 |
|
||||
| External / one-time / dynamic Email 鉴权方式 | 已确定 | Email 审批页、OTP、风控、审计 | 使用 Email OTP;现有 Email Web Form URL token 继续用于定位表单,提交表单时必须携带 OTP。 |
|
||||
| Dynamic Email 是否反查 Account / Contact | 已确定 | recipient resolution、去重、审计、allowed approver | 不反查 Account / Contact,只发送邮件;审计记录变量值、校验结果和邮件投递结果。 |
|
||||
| Current initiator identity schema | 已确定 | WebApp、Service API、CLI、匿名 session、去重、审计 | WebApp、Service API 和 CLI 都有身份,均可作为 current initiator;匿名 WebApp session 仅在原会话内有效。 |
|
||||
| RBAC 权限矩阵 | 已确定 | Contact Directory、Human Roster、IM credential、IM binding | 默认 workspace admin 管理 Human Roster;enterprise admin 管理 EE Contact Directory 与 IM Integration。 |
|
||||
| Provider 能力矩阵 | 已确定 | 卡片审批、fallback URL、IM 身份校验、通讯录同步 | 所有首发 provider 都支持通讯录同步;除企业微信外,其余 provider 基本可映射 Dify HITL 表单页。企业微信按有限交互或 Web fallback 验收。 |
|
||||
| SaaS abuse guardrails | 已确定 | dynamic Email、发送量、OTP、租户限流、发送日志 | 首发做最小限流和日志记录;有时间则追加 workspace 级 email service 配置,第一期只支持 Resend。 |
|
||||
|
||||
## 主排期计划表
|
||||
|
||||
| 阶段 | 日期 | 负责方向 | 工作内容 | 交付物 / 验收门禁 |
|
||||
|-|-|-|-|-|
|
||||
| 范围冻结 | 2026-07-10 | Product、Backend、Frontend、Security、SaaS | 冻结首发范围、节点策略、Email 鉴权、RBAC、provider 首发定义、provider 能力矩阵。 | PRD delta / decision log 完成;所有 blocker 有 owner 和默认裁决。 |
|
||||
| 架构与 schema | 2026-07-10 至 2026-07-13 | Backend、Architecture | 确认 Contact、Human Roster、IM Binding、Recipient snapshot、HITL task、Delivery Record、Recipient Resolution Record、Audit Record 的表结构与服务边界。 | Migration 草案、领域对象映射、状态机和回滚策略通过评审。 |
|
||||
| 契约与 mock handoff | 2026-07-10 至 2026-07-13 | Backend、Frontend、Provider owners | 输出 DSL / DTO / API shape / error code / feature flag / permission matrix / provider mock contract,使前端可不等待后端完整实现就开始开发。 | Human Roster、Contact Directory、IM Integration、recipient selector、OTP、Last Run、provider 状态的 mock response 和接口契约齐备。 |
|
||||
| 后端核心开发 | 2026-07-13 至 2026-07-18 | Backend | 实现 Roster CRUD、external contact 校验、recipient resolver、dedupe、HITL task 持久化、delivery record、request message template、Email delivery、OTP 和原子提交。 | 单测覆盖 resolver / lifecycle / task transition / 并发提交;Email-only HITL 可端到端运行。 |
|
||||
| 前端核心开发 | 2026-07-13 至 2026-07-21 | Frontend | 基于 contract / mock 并行实现 Human Roster、Contact Directory / IM Integration、HITL 节点 Notification Policy、recipient selector、dynamic Email chip、one-time Email、debug only notify me、Web approval OTP、Last Run delivery 展示。 | 前端核心页面和状态先以 mock 跑通;节点配置可保存、回显、调试;关键 i18n key、空态、错误态和权限态齐备。 |
|
||||
| Web approval 与鉴权 | 2026-07-14 至 2026-07-18 | Backend、Frontend、Security | 实现独立审批页、打开页校验、提交二次校验、Email OTP、重复提交处理、错误态文案。 | 外部联系人 / one-time Email / dynamic Email 可安全打开和提交;转发链接不能在无 OTP 时越权提交。 |
|
||||
| Provider framework | 2026-07-14 至 2026-07-19 | Backend、Provider owners | 抽象 provider adapter、credential model、Organization-scoped IM sync、callback / request URL、test connection、message payload、identity verification、fallback URL。 | Provider contract 冻结;mock provider 和手动同步流程测试通过;Secret 不进入日志。 |
|
||||
| Provider 后端 adapter | 2026-07-15 至 2026-07-23 | Provider owners、Backend | 并行实现 Slack、钉钉、飞书 / Lark、Teams、企业微信后端接入与通讯录同步。 | 每个 provider 至少完成 credential 保存、Organization-scoped sync、test connection、发送通知、回调 / 提交、失败记录。 |
|
||||
| Provider 前端配置与状态 UI | 2026-07-18 至 2026-07-24 | Frontend、Provider owners | 并行实现各 provider credential 配置入口、test connection、sync status、provider availability、fallback 文案和错误态。 | 通过 gate 的 provider UI 可用;未通过 gate 的 provider 可隐藏或降级;配置步骤与文档一致。 |
|
||||
| 前后端 API 联调 | 2026-07-22 至 2026-07-25 | Frontend、Backend、Provider owners | 将前端 mock 替换为真实 API;接入真实 RBAC、feature flag、provider availability、test connection、sync status、OTP 和 Last Run 数据。 | Roster、Contact Directory、节点配置、OTP 页面、Last Run、provider 管理 UI 均可在联调环境跑通。 |
|
||||
| 日志与审计 | 2026-07-18 至 2026-07-23 | Backend、Frontend | 实现 Last Run delivery 展示、recipient resolution 展示、失败原因、submitted_by、审计数据落库。 | 能回答“通知给谁、是否送达、谁提交、为何允许或拒绝”。 |
|
||||
| 迁移与兼容 | 2026-07-20 至 2026-07-26 | Backend、Frontend | SaaS / CE workspace member 初始化到 Roster;旧 Email recipient 兼容读取;运行中 task snapshot 不受配置变更影响;输出 dry run 和回滚证据供 QA 进场使用。 | migration dry run 通过;旧 workflow 不失效;回滚路径明确;证据可交给 QA。 |
|
||||
| 功能冻结 | 2026-07-24 | All | 停止新增功能,只接受 P0/P1 缺陷、安全问题和 provider 兼容修复。 | Provider readiness gate 完成;未通过 provider 从 7 月底 ready-to-merge 范围移出或降级到 fallback。 |
|
||||
| 前端 RC 稳定与 QA handoff | 2026-07-25 至 2026-07-26 | Frontend、Backend、Provider owners | 收敛 provider 配置入口、fallback 状态、HITL 节点配置、Roster、Contact Directory、Web approval OTP、Last Run 展示;完成前端 smoke、i18n、type-check、已知限制和可测 build。 | 2026-07-26 前交付前端 RC build、feature flag / 配置说明、smoke checklist、关键页面截图或录屏,QA 可在 2026-07-27 接手。 |
|
||||
| 集成 QA | 2026-07-27 至 2026-07-28 | QA、Backend、Frontend、Provider owners | 覆盖 Roster、Email、Web approval、各 provider、debug、migration、RBAC、异常状态、并发提交。 | RC1 缺陷清零到可接受阈值;所有 P0/P1 关闭。 |
|
||||
| 安全与 abuse hardening | 2026-07-24 至 2026-07-29 | Security、SaaS、Backend | Email OTP 有效期、重试次数、提交校验、最小限流、发送日志、发送人数限制、dynamic Email 限制、secret redaction、审计敏感字段处理;有时间则补 workspace 级 Resend email service 配置。 | Security sign-off;SaaS guardrail 生效;敏感信息不出日志;Resend 配置不作为 7.31 merge 硬门禁。 |
|
||||
| Merge readiness | 2026-07-29 至 2026-07-30 | Backend、Frontend、Docs、Product、Security | PR 描述、配置文档、provider 配置指南、迁移说明、回滚方案、监控告警建议、已知限制说明。 | Ready-to-merge review 通过;后续灰度、发布和回滚责任人明确。 |
|
||||
| Final PR hardening | 2026-07-30 至 2026-07-31 | Backend、Frontend、QA、Provider owners | 处理最后一轮 code review、补齐测试证据、确认 CI、provider sandbox E2E、migration dry run 和安全准入。 | 2026-07-31 达到 PR ready to merge;SaaS 生产上线另行排期。 |
|
||||
|
||||
## Provider 并行排期
|
||||
|
||||
| Provider | 部署形态 | 日期 | 必须完成 | Provider gate |
|
||||
|-|-|-|-|-|
|
||||
| Slack | EE 企业自建应用;SaaS ISV / OAuth | 2026-07-15 至 2026-07-21 | EE 自建应用 credential、SaaS OAuth 安装、Organization-scoped sync、发送 HITL 卡片、获取 Slack 用户身份、卡片提交、Email 双发、delivery record。 | 2026-07-24 前完成 EE 企业自建应用和 SaaS ISV / OAuth 两条 E2E,且同步结果可落到对应 Organization。 |
|
||||
| 钉钉 | EE 企业自建应用;SaaS 企业自建应用 | 2026-07-15 至 2026-07-22 | EE 与 SaaS tenant / workspace 自建应用凭据配置、Organization-scoped sync、回调校验、发送卡片 / 消息、用户身份映射、Web fallback、delivery record。 | 2026-07-24 前完成 EE 企业自建应用和 SaaS 企业自建应用 E2E;SaaS 需补齐租户接入文档。 |
|
||||
| 飞书 / Lark | EE 企业自建应用 | 2026-07-16 至 2026-07-22 | 企业自建应用 credential、Organization-scoped sync、回调 / 请求 URL、卡片通知、用户身份校验、提交鉴权、delivery record。 | 2026-07-24 前完成 EE 企业自建应用 E2E。 |
|
||||
| Microsoft Teams | EE 企业自建应用 | 2026-07-16 至 2026-07-23 | 企业自建 Teams App credential、Organization-scoped sync、Adaptive Card / fallback message、身份校验、提交回调、delivery record。 | 2026-07-24 前完成 EE 企业自建应用 sandbox E2E。 |
|
||||
| 企业微信 | EE 企业自建应用 | 2026-07-17 至 2026-07-23 | 企业自建应用 credential、Organization-scoped sync、消息发送、身份校验、有限交互或 Web fallback、delivery record、错误态。 | 2026-07-24 前完成 EE 企业自建应用通知 + Web 审批页 E2E;卡片内完整审批不作为硬门禁。 |
|
||||
|
||||
## 验收清单
|
||||
|
||||
| 类别 | 验收标准 |
|
||||
|-|-|
|
||||
| Human Roster | workspace member 初始化、新成员自动进入、成员离开后不可新选、external contact 校验、Dify Account 不误建 external contact。 |
|
||||
| HITL 节点 | 使用新节点和新 DSL;执行时根据 node version 路由到新旧实现;支持静态 contact、external contact、one-time Email、dynamic Email、current initiator、debug only notify me;配置可保存、导入、回显。 |
|
||||
| 通知 | Email 必发;有 IM binding 时 IM + Email 双发;部分失败继续,全部不可触达按规则失败;失败原因可见。 |
|
||||
| 审批与鉴权 | 打开页校验 task 状态;提交页再次校验 task 状态、approver 身份和 Email OTP;重复提交只有一个成功;链接转发不能在无 OTP 时越权提交。 |
|
||||
| 日志与审计 | 记录 resolved recipients、delivery records、recipient resolution、submitted_by、submitted_at、提交渠道、拒绝 / 失败原因。 |
|
||||
| Provider | 首发 provider 均通过 Organization-scoped sync、发送、身份校验、提交、失败记录、credential test、回调校验 E2E。 |
|
||||
| 迁移与兼容 | 旧节点代码和逻辑保持不变;旧 Email recipient 不导致已发布 workflow 失效;运行中 task 使用创建时 snapshot;migration dry run 可回滚。 |
|
||||
| 安全 | secret 不进日志;Email / IM 正文不完整入审计;Email OTP 有效期、重试次数、提交校验、最小限流和发送日志生效;敏感表单字段有脱敏策略。 |
|
||||
| Stretch scope | 有时间则支持 workspace 级 email service 配置;第一期只支持 Resend;不作为 2026-07-31 ready-to-merge 硬门禁。 |
|
||||
|
||||
## 风险与降级策略
|
||||
|
||||
| 风险 | 影响 | 截止点 | 降级策略 |
|
||||
|-|-|-|-|
|
||||
| PRD blocker 未在 2026-07-10 冻结 | 后端模型、DSL、鉴权和 RBAC 返工 | 2026-07-10 | 按本文默认裁决推进;延期未冻结项到后续版本。 |
|
||||
| Provider 能力与预期不一致 | 单个 provider 不能完整映射 Dify HITL 表单页,或身份校验存在限制 | 2026-07-24 | 降级到 request message + Web 审批页;企业微信按有限交互或 Web fallback 验收;仍需通过身份校验。 |
|
||||
| SaaS 钉钉企业自建应用配置成本高 | SaaS 首发接入和支持成本上升 | 2026-07-22 | ready-to-merge 范围可限定为试点租户路径;配置文档和自检工具先行。 |
|
||||
| URL 鉴权实现复杂 | Email / fallback 审批安全风险 | 2026-07-18 | 不允许无 OTP 的 Email recipient 提交;未完成安全闭环则该 recipient 类型不进入 ready-to-merge 范围。 |
|
||||
| RBAC 缺失 | Contact Directory / Roster 泄露跨 workspace 信息 | 2026-07-10 | 默认最小权限:普通 member 不可浏览完整 Roster;workspace admin 管理 workspace;enterprise admin 管理 deployment。 |
|
||||
| Dynamic Email 滥用 | SaaS 邮件滥发和安全投诉 | 2026-07-12 | merge 前启用最小限流和发送日志;workspace 级 Resend email service 配置作为 stretch scope。 |
|
||||
| 迁移影响旧 workflow | 线上 workflow 失效或回滚困难 | 2026-07-24 | 不自动改写已发布 DSL;兼容读取优先;旧节点保留运行路径。 |
|
||||
|
||||
## Go / No-go 标准
|
||||
|
||||
| 日期 | Gate | Go 条件 | No-go 条件 |
|
||||
|-|-|-|-|
|
||||
| 2026-07-13 | 契约冻结 | schema、API contract、mock fixture、provider contract、migration 方案均冻结,前端可以并行开发。 | 前端仍缺 mock / API contract,或后端模型复用边界不清。 |
|
||||
| 2026-07-18 | Core alpha | 后端 Email-only HITL、Roster、task、approval page、OTP 和原子提交端到端跑通;前端核心页面 mock 主路径跑通。 | 核心模型、Email 审批、OTP、first-writer-wins 或前端主路径仍无法闭环。 |
|
||||
| 2026-07-21 | 前端主路径可联调 | Human Roster、Contact Directory、节点配置、Web approval OTP、Last Run 前端主路径完成。 | 前端仍缺关键页面或状态机,无法接真实 API。 |
|
||||
| 2026-07-24 | Feature freeze | 所有首发 provider 至少完成 Organization-scoped sync 和 sandbox E2E;前端配置入口具备可联调形态;P0 安全项关闭。 | 任一 provider 无法同步、发送或校验提交身份,且没有可接受 fallback。 |
|
||||
| 2026-07-26 | Frontend RC handoff | 前端完成 provider 接入收敛、HITL 节点配置、Roster、Contact Directory、OTP 页面、Last Run 展示和 QA handoff 包。 | 前端仍缺可测 build、关键页面未联通、provider 降级态不明确、i18n / type-check 未过。 |
|
||||
| 2026-07-27 | QA entry | QA 同事进场,测试矩阵、环境、账号、provider sandbox、前端 RC build、缺陷 triage 节奏就绪。 | 仍缺可测环境、前端 RC build、关键 provider sandbox、测试账号或 RC 范围。 |
|
||||
| 2026-07-28 | RC1 | P0/P1 清零;迁移 dry run 和回滚演练通过。 | 仍有数据丢失、越权提交、旧 workflow 失效风险。 |
|
||||
| 2026-07-31 | Merge readiness | CI、code review、测试证据、迁移说明、配置文档、监控建议、回滚方案、最小限流和发送日志均就绪。 | provider 大面积失败、SaaS abuse guardrail 未生效、审计缺失关键字段,或仍有未关闭的 P0/P1。 |
|
||||
270
prd_requirements_review_hitl_phase2.md
Normal file
270
prd_requirements_review_hitl_phase2.md
Normal file
@ -0,0 +1,270 @@
|
||||
# HITL Phase 2 PRD Review
|
||||
|
||||
来源:<https://langgenius.feishu.cn/wiki/GMFdwe40Oi2rC9klP2HcNjnHnwd>
|
||||
本次复读基于 `revision_id = 1918`(读取时间:2026-07-10,Asia/Shanghai)。
|
||||
|
||||
## 直接结论
|
||||
|
||||
这版 PRD 相比上一版已经明显收敛,尤其是:
|
||||
|
||||
- `Human Roster` 已统一重命名为 `Contact`
|
||||
- `Workspace IM override` 已从非目标改为本期范围
|
||||
- `Dynamic Email`、`Current initiator`、`form/task` 状态层级、`Web 独立页面审批` 都补进了显式决策
|
||||
- `Magic link` 基本被收回,外部邮箱路径开始统一收敛到 `Email OTP`
|
||||
|
||||
但仍然**不建议直接无保护进入实现**。主要原因已从“规则缺失”转为“规则虽有,但仍有若干跨章节冲突、未落成矩阵、以及边界不完整”。当前最值得继续盯住的点是:
|
||||
|
||||
- `RBAC` 仍未完整定义
|
||||
- `Connection status` 虽有枚举,但没有生命周期
|
||||
- `Contact / Organization / Dify member` 的边界仍有灰区
|
||||
- `Web 鉴权链路` 已收敛,但不同审批主体的失败路径和回退策略还不完整
|
||||
- `abuse guardrails` 仍未量化
|
||||
|
||||
下面按你要求的 10 个维度更新。
|
||||
|
||||
## 1. 显式需求
|
||||
|
||||
- 系统已从 `Human Roster` 切换到 `Contact` 概念,且产品信息架构中明确将左侧模块拆为 `Agent` 与 `Contact` 两个独立模块。
|
||||
引用:§2 “提供 Contact,作为 HITL 可通知联系人的来源。”;§5 “Agent 与 Contact 模块拆分”;§5.3 “Workspace:Contact”
|
||||
|
||||
- `Contact` 的产品类型本期收敛为三类:`Dify member`、`Organization contact`、`External contact`。
|
||||
引用:§3.1 “本期 Contact 类型收敛为三类:Dify member、Organization contact、External contact。”
|
||||
|
||||
- `Organization` 在本期被定义为统一抽象:`CE / SaaS` 中当前 workspace 即 `Organization`,`EE` 中整个部署内所有 workspace 共同属于同一个 `Organization`。
|
||||
引用:§3.3 “本期用 Organization 统一 CE / SaaS / EE 的产品抽象:CE / SaaS 中,当前 workspace 即 Organization;EE 中,整个部署内所有 workspace 共同属于同一个 Organization。”
|
||||
|
||||
- 本期明确支持 `Workspace IM override`,但它只覆盖 workspace 内 contact 的 `IM identity / 通知行为`,不覆盖 IM Integration 的凭据。
|
||||
引用:§2 非目标中 “~~workspace级别的 im identify override~~ Workspace IM override 本期进入范围。”;§6.5 “Workspace IM override 本期需要支持,但它不是 IM 平台接入凭据 override。”
|
||||
|
||||
- `IM credential` 的产品作用域已明确为 `Organization` 级,而不是 workspace 级凭据 override。
|
||||
引用:§18.4 “IM channel 接入配置中的 App ID、App Secret…统一归属 Organization。”;同节 “不再采用:~~Workspace / tenant-level credential override 优先于 deployment-level credential 的凭据优先级。~~”
|
||||
|
||||
- `Connection status` 已被明确扩展为 `Not configured / Configured / Connected / Permission issue / Callback error / Connection error`。
|
||||
引用:§6.2 “Connection status 需要从粗粒度 Error 拆成可排查的产品状态”;同节列出六个状态
|
||||
|
||||
- `Dynamic Email` 本期只支持单个合法 email,不支持数组变量批量输入;并且命中现有 `Contact` 后要升级为 `Contact recipient` 而不是继续当作裸邮箱。
|
||||
引用:§8.3 “不再支持…通过数组变量一次传入多个 dynamic Email recipients。”;§8.3 “Dynamic Email 命中 Contact 后升级为 Contact recipient”
|
||||
|
||||
- `email matching` 规则已被明确为:对完整 email 执行 lower-case 后做完全相等比较;本期不做 `+tag` 消解或点号折叠。
|
||||
引用:§7.5 “先对完整 email 字符串执行 lower-case,再做完全相等比较。”;同节 “本期不做 provider-specific 规则:~~+tag 消解、点号折叠…~~”
|
||||
|
||||
- 默认通知规则已明确为:具备 `IM binding + Email` 的 recipient 并行走 `IM + Email`;Email 默认不可关闭。
|
||||
引用:§2 “默认通过 IM + Email 双渠道触达;Email 默认不可关闭。”;§9.1 “默认双渠道触达”
|
||||
|
||||
- `Current initiator` 与 `allowed approver` 的关系已被明确为:`Current initiator` 是独立 allowlist 来源,但通知发送产生的审批主体仍以 `Contact` 为中心记录。
|
||||
引用:§8.5 “Current initiator 与 allowed approver”;§9.4 “提交主体”
|
||||
|
||||
- `Web 独立页面审批` 与 `IM 卡片审批` 已被拆成两条鉴权链路:
|
||||
- `IM 卡片审批`:IM identity -> IM Binding -> Contact
|
||||
- `Web 独立页面审批`:按审批主体走 Dify 登录或 Email OTP
|
||||
引用:§17.3 “IM 卡片审批与 Web 独立页审批是两条鉴权链路”;§17.5 “不同审批主体的 Web 鉴权”
|
||||
|
||||
- `form/task` 状态机在产品文案上已明确只保留 `WAITING / SUBMITTED / TIMEOUT / EXPIRED`,`canceled / delivery_failed` 不进入 form status。
|
||||
引用:§10.1 “form/task 状态层级”;同节 “本期 form status 只使用 WAITING、SUBMITTED、TIMEOUT、EXPIRED。canceled 不进入 form status;delivery_failed 不进入 form status。”
|
||||
|
||||
- `导入导出 / DSL ID-Email 转换` 已被明确移出本期目标。
|
||||
引用:§11.2 “导入导出不作为本期目标”;§15 “Milestone 4 范围调整:移出本期 ~~DSL 导入导出 ID / Email 转换~~”
|
||||
|
||||
- `Success metrics / failure metrics` 已明确不在本期范围;`SaaS abuse guardrails` 单独成章,但仍待 SaaS 团队确认。
|
||||
引用:§18.11 “Success metrics和Failure metrics / 暂不考虑”;§19 “Saas Abuse guardrails / 由saas团队确认”
|
||||
|
||||
## 2. 隐藏假设
|
||||
|
||||
- [PRODUCT_DECISION] PRD 假设 `Organization` 作为统一抽象足以覆盖 `SaaS / CE / EE`,但这实际上隐含了“当前阶段不处理 SaaS/CE 未来多 workspace 语义”的假设。
|
||||
引用:§3.3 “CE / SaaS 中,当前 workspace 即 Organization”;§18.3 “CE 默认只有一个 workspace”
|
||||
|
||||
- [ENGINEERING_DECISION] PRD 假设“审批主体以 Contact 为中心”足以消解 IM / Email 双渠道重复通知问题,但这依赖 `Contact`、`IM Binding`、`normalized email` 的映射始终可逆。
|
||||
引用:§8.5 “allowed approver 以 Contact 为中心记录”;§18.6 “Contact-centric canonicalization”
|
||||
|
||||
- [PRODUCT_DECISION] PRD 假设 `Organization contact` 在 Web 独立页审批时可以可靠走 `Dify 登录`,这隐含了这些对象在实际产品里都拥有可用 Dify 身份的前提。
|
||||
引用:§17.5 “Dify member / Organization contact:Web 独立页要求 Dify 登录”
|
||||
|
||||
- [PRODUCT_DECISION] PRD 假设 `Email always-on` 对所有部署形态和客户约束都成立,但没有给出任何合规例外或部署级开关。
|
||||
引用:§2 “Email 默认不可关闭。”;§9.1 “Email 默认不可关闭”
|
||||
|
||||
- [ENGINEERING_DECISION] PRD 假设 `dynamic authorization` 能覆盖 pending task 的所有身份漂移问题,但没有写清与 snapshot 的边界如何在查询、展示、重发中共存。
|
||||
引用:§18.9 “pending task 的提交资格采用动态授权”;同节 “历史 task 永远保留创建时快照”
|
||||
|
||||
- [PRODUCT_DECISION] PRD 假设 `DingTalk self-managed integration` 虽然运维重,但仍是 SaaS 可接受路径;这实际上把大量接入负担转给租户管理员。
|
||||
引用:§4.1 “每个 tenant / workspace 需要自行创建钉钉企业自建应用”;同节 “必须提供 Test connection”
|
||||
|
||||
## 3. 模糊术语
|
||||
|
||||
- [BLOCKER] `Organization contact` 与 `Dify member`、`workspace member` 的边界还不够干净,尤其是在“离开 workspace 但仍在 organization 中”时。
|
||||
引用:§3.1 “Organization contact 表示仍属于当前 Organization 联系人池,但不一定是当前 workspace member。”;§18.2 “若联系人已不在当前 workspace,仍在 dify 系统中,联系人类型自动转为 dify member”
|
||||
|
||||
- [BLOCKER] `valid Contact` 仍是隐式术语。PRD 在动态授权链中大量使用它,但没有单独定义“valid”的判定条件集合。
|
||||
引用:§17.4 “动态授权判定链:… current IM Binding -> valid Contact -> allowed approver -> allow / deny”
|
||||
|
||||
- [ENGINEERING_DECISION] `Connection status` 现在有枚举,但“什么时候从 Configured 进入 Connected / Permission issue / Callback error / Connection error”仍是模糊的。
|
||||
引用:§6.2 “Connection status 需要从粗粒度 Error 拆成…”;同节没有给出状态迁移条件
|
||||
|
||||
- [BLOCKER] `Contact list / 联系人列表 / Contact` 在文档里交替出现,集合概念与单条记录概念仍有轻微混用风险。
|
||||
引用:§5 “后续文档中的联系人名录相关表述统一更新为 Contact;当需要强调集合含义时,使用 Contact list / 联系人列表。”;§3.2 标题 “Contact”
|
||||
|
||||
- [PRODUCT_DECISION] `Only notify me during debug` 的“me”在多人协作、代理触发、无可通知渠道时的语义仍不够明确。
|
||||
引用:§8.6 “实际通知对象替换为当前调试用户。”;全文未定义调试用户无有效渠道时的行为
|
||||
|
||||
## 4. 缺失的状态迁移
|
||||
|
||||
- [BLOCKER] `Connection status` 虽然有状态枚举,但缺少正式状态迁移图。
|
||||
引用:§6.2 列出六种状态;未说明 `Save/Test connection/Disable` 如何驱动迁移
|
||||
|
||||
- [ENGINEERING_DECISION] `IM Binding` 仍缺生命周期:手工配置、同步建立、覆盖、删除、失效、恢复之间没有状态机。
|
||||
引用:§6.3 “配置 IM identity”;§6.4 “IM 成员同步”;§18.2 “IM Binding 修改 / 删除”
|
||||
|
||||
- [PRODUCT_DECISION] `unmatched list` 仍缺生命周期与可逆性定义。
|
||||
引用:§6.4 “管理员可手动处理 unmatched 成员,例如忽略、稍后处理,或作为 external contact 添加。”
|
||||
|
||||
- [BLOCKER] `URL / token lifecycle` 虽然列出了 `issued / opened / verified / submitted / expired / revoked` 的概念,但没有定义重发、刷新、再次打开、再次验证后的状态转移。
|
||||
引用:§17.4 “URL / Token 生命周期”
|
||||
|
||||
- [BLOCKER] `Workspace member 离开`、`转为 external contact`、`从 Contact 移除` 三条分支仍缺一张统一状态图。
|
||||
引用:§18.2 “管理员可选择:转为 external contact / 从 Human Roster 移除”;同章仍混用 `Contact` 与旧术语
|
||||
|
||||
- [ENGINEERING_DECISION] `Workspace IM override` 现在已进入范围,但 create / update / reset / delete 对 pending task 和已发通知的影响只在 §18.9 的表格里部分定义,没有完整生命周期文案。
|
||||
引用:§6.5 “Workspace IM override 本期进入范围”;§18.9 表格 “Workspace IM override 修改”
|
||||
|
||||
## 5. 缺失的错误 / 边界场景
|
||||
|
||||
- [BLOCKER] `Current initiator` 在 API / CLI 场景下“没有明确身份”时仍未定义节点行为。
|
||||
引用:§8.5 “CLI/API 发起时,若调用方有明确身份,可作为 allowed approver。”;未覆盖“无明确身份”
|
||||
|
||||
- [BLOCKER] `Dynamic Email` 只明确不支持数组,但没有明确多值字符串、逗号分隔、空白值、重复值的前端与运行时拒绝策略。
|
||||
引用:§8.3 “不再支持…数组变量一次传入多个 dynamic Email recipients”;§10.3 “Dynamic Email 解析异常类型”
|
||||
|
||||
- [BLOCKER] `dynamic Email 命中多个 Contact` 或命中跨 workspace 同邮箱主体时的唯一归属规则没有单独写明。
|
||||
引用:§8.3 “命中 Contact 后升级为 Contact recipient”;§18.6 “优先匹配已存在联系人”
|
||||
|
||||
- [BLOCKER] `Dify member / Organization contact` 若不能完成 Dify 登录,是否允许退化为 Email OTP,PRD 当前明确否定统一 OTP,但没有定义失败后是否还有补救路径。
|
||||
引用:§17.5 “Dify member / Organization contact:Web 独立页要求 Dify 登录”;§17.5 同节未定义登录失败后替代路径
|
||||
|
||||
- [PRODUCT_DECISION] `企业微信` 被标为“不支持卡片内审批,只能做选择”,但复杂表单、文件表单、超出 action 数量限制时的用户体验路径仍未定义。
|
||||
引用:§18.5 企业微信行 “不支持 / 只能做选择(对应 Dify 表单的 action,并且 action 数量有限制)”
|
||||
|
||||
- [BLOCKER] `No one can approve this step yet` 已出现在节点预览示意,但真正的保存校验、运行时错误、可发布性规则还没写全。
|
||||
引用:§8.7 节点预览示意图;§10.4 “无可通知对象时报错”
|
||||
|
||||
- [PRODUCT_DECISION] `文件访问权限` 已增加原则,但没有具体说明文件对象本身的授权失败提示、日志记录和重试策略。
|
||||
引用:§9.3 “文件访问必须同时校验 task、访问者身份、allowed approver 和文件所属 task。”
|
||||
|
||||
## 6. 安全与权限问题
|
||||
|
||||
- [PRODUCT_DECISION] 完整 `RBAC` 矩阵已不再作为本期 blocker,但细粒度权限依然未定:谁能查看完整 Contact、谁能看 raw dynamic value、谁能管理 external contact,仍需后续确定。
|
||||
引用:§18.10 “不再作为当前 PRD blocker:~~在本期完整定义所有后台操作权限矩阵。~~”;同节 “普通 member 是否能查看完整 Contact…后续结合 RBAC 再定”
|
||||
|
||||
- [BLOCKER] 外部邮箱审批已基本收敛到 `Email OTP`,但 `OTP` 的速率限制、次数限制、锁定规则、重发策略仍未定义。
|
||||
引用:§17.5 “Email OTP 规则”;§19 “Saas Abuse guardrails / 由saas团队确认”
|
||||
|
||||
- [BLOCKER] `raw dynamic Email`、`form snapshot`、`submission content` 的可见范围与脱敏边界仍未收敛。
|
||||
引用:§16.4 “敏感信息边界待定”;同节 “后续需要结合安全与研发方案单独确认”
|
||||
|
||||
- [BLOCKER] 审计可见性虽然开始收敛到 `enterprise admin / workspace admin / workflow 编排者`,但不同主体可见字段范围没有定义。
|
||||
引用:§16.2 “审计可见性”;§16.2 “审计主体”
|
||||
|
||||
- [BLOCKER] 文件访问安全原则已写出,但对象级授权模型仍未定义,例如外部联系人是否能看其被要求审批的文件预览。
|
||||
引用:§9.3 “文件访问必须同时校验 task、访问者身份、allowed approver 和文件所属 task。”
|
||||
|
||||
- [PRODUCT_DECISION] `Email always-on` 在受监管场景、私有化场景是否允许例外,仍无权限/合规策略。
|
||||
引用:§2 “Email 默认不可关闭。”;全文未给出例外
|
||||
|
||||
## 7. 平台能力风险
|
||||
|
||||
- [BLOCKER] `IM 能力矩阵` 仍未填完,尤其 `通讯录同步` 仍为空,意味着产品已经决定依赖它,但没有明确哪些 provider 真支持。
|
||||
引用:§18.5 矩阵中 `通讯录同步` 列为空
|
||||
|
||||
- [ENGINEERING_DECISION] PRD 虽然把 `fallback URL` 从“身份 fallback”中剥离了,但仍在模板映射和产品规则中保留该术语,容易继续混淆“通知入口”和“鉴权链路”。
|
||||
引用:§18.5 “不能渲染卡片时,发送 request message + fallback URL。”;§18.8 表格列 “IM fallback”
|
||||
|
||||
- [BLOCKER] SaaS 钉钉仍是高运维负担路径,产品虽然补了约束,但没有给出失败后的支持边界、可观测性或 self-serve 预期。
|
||||
引用:§4.1 “必须提供 Test connection”;同节仍要求租户自备 app id / secret
|
||||
|
||||
- [BLOCKER] `Dify 登录` 被用作 `Organization contact` 的独立页鉴权前提,但对“跨 workspace 的内部人是否默认都有 Dify 登录路径”没有产品确认。
|
||||
引用:§17.5 “Dify member / Organization contact:Web 独立页要求 Dify 登录”
|
||||
|
||||
- [PRODUCT_DECISION] `企业微信` 能力限制已知,但没有补充对应的 PM 降级策略,例如强制转网页审批、禁止复杂表单、还是只支持 approve/reject。
|
||||
引用:§18.5 企业微信行说明
|
||||
|
||||
## 8. 应明确写出的 Non-goals
|
||||
|
||||
- [PRODUCT_DECISION] `Magic link` 不再是本期外部邮箱审批方案。
|
||||
引用:§9.3 “~~Magic link。~~ / Email OTP。”;§17.5 “不再采用:~~External contact…Magic link 或 Email OTP。~~”
|
||||
|
||||
- [PRODUCT_DECISION] `导入导出 / DSL ID-Email 转换` 不属于本期目标。
|
||||
引用:§11.2 “导入导出不作为本期目标”;§15 “Milestone 4 范围调整”
|
||||
|
||||
- [PRODUCT_DECISION] 不支持多个 IM 绑定、通知优先级、个人通知偏好、复杂审批规则、群聊通知。
|
||||
引用:§2 非目标对应条目
|
||||
|
||||
- [PRODUCT_DECISION] `Success metrics / failure metrics` 不属于本期目标。
|
||||
引用:§18.11 “暂不考虑”
|
||||
|
||||
- [PRODUCT_DECISION] 完整后台操作权限矩阵不作为本期 PRD blocker。
|
||||
引用:§18.10 “不再作为当前 PRD blocker:~~在本期完整定义所有后台操作权限矩阵。~~”
|
||||
|
||||
- [PRODUCT_DECISION] 不支持把 `dynamic Email` 解析为 Contact entity / member id / group id。
|
||||
引用:§2 非目标 “动态 recipient 解析为 Contact entity / member id / group id。”
|
||||
|
||||
- [PRODUCT_DECISION] 不支持把数组变量一次传入多个 `dynamic Email recipients`。
|
||||
引用:§8.3 “不再支持…数组变量一次传入多个 dynamic Email recipients。”
|
||||
|
||||
## 9. Blocking questions for product
|
||||
|
||||
- [BLOCKER] `Organization contact` 与 `Dify member` 的产品边界最终如何面向用户解释?它们是展示层类型、鉴权层类型,还是数据层类型?
|
||||
引用:§3.1 Contact 类型;§17.5 “Dify member / Organization contact:Web 独立页要求 Dify 登录”
|
||||
|
||||
- [BLOCKER] `Current initiator` 在 API / CLI 无明确身份时,节点究竟是禁止运行、禁止审批,还是降级为“无 initiator approver”?
|
||||
引用:§8.5 “若调用方有明确身份,可作为 allowed approver。”
|
||||
|
||||
- [BLOCKER] `Organization contact` 在 Web 独立页上若无法完成 Dify 登录,是否允许任何补救路径?
|
||||
引用:§17.5 “Organization contact:Web 独立页要求 Dify 登录”
|
||||
|
||||
- [BLOCKER] `Contact 管理权限` 的最小可交付口径是什么?当前只说“拥有管理 Contact 权限的人可以访问 Contact”,但没有更细。
|
||||
引用:§18.10 “拥有该权限的人可以访问 Contact,并可搜索跨 workspace 的 Dify member。”
|
||||
|
||||
- [BLOCKER] `OTP` 的限流、失效时间、错误提示、重试次数、锁定策略是什么?
|
||||
引用:§17.5 “Email OTP 规则”;§19 “Saas Abuse guardrails”
|
||||
|
||||
- [BLOCKER] `Connection status` 中 `Permission issue / Callback error / Connection error` 的产品判定条件是什么?
|
||||
引用:§6.2 “Connection status 状态机”
|
||||
|
||||
- [BLOCKER] `通讯录同步` 哪些 provider 本期真正支持?如果不支持,UI 上是隐藏还是禁用?
|
||||
引用:§6.4 “如果当前 IM 能力支持通讯录读取,可提供同步能力。”;§18.5 `通讯录同步` 列为空
|
||||
|
||||
- [BLOCKER] `Contact remove / convert / disable` 三条路径对 pending task 的统一 UX 是什么?目前文案分散在生命周期和变更矩阵中。
|
||||
引用:§18.2 联系人生命周期;§18.9 变更影响矩阵
|
||||
|
||||
- [BLOCKER] `企业微信` 的 action 数量限制是否会导致功能范围收缩?需要明确哪些表单或操作不支持。
|
||||
引用:§18.5 企业微信行
|
||||
|
||||
## 10. Engineering decisions that should not be left to implementation agents
|
||||
|
||||
- [ENGINEERING_DECISION] `Contact-centric canonicalization` 的 canonical key、优先级、日志归并和 UI 呈现必须统一设计。
|
||||
引用:§18.6 “多来源命中同一人的归并展示”;§18.6 “Contact-centric canonicalization”
|
||||
|
||||
- [ENGINEERING_DECISION] `form status / workflow outcome / delivery reason` 三层状态模型必须明确拆层,不能在实现时临场决定。
|
||||
引用:§10.1 “form/task 状态层级”
|
||||
|
||||
- [ENGINEERING_DECISION] `Organization-level credential` 与 `Workspace IM override` 的数据模型和运行时优先级必须先定稿。
|
||||
引用:§6.5 “override 只用于当前 workspace 内联系人 IM 身份 / 通知行为的覆盖”;§18.4 “IM 凭据作用域”
|
||||
|
||||
- [ENGINEERING_DECISION] `Connection status` 到 provider 错误、权限错误、回调错误的映射规则必须统一。
|
||||
引用:§6.2 “Connection status 状态机”
|
||||
|
||||
- [ENGINEERING_DECISION] `Dynamic authorization chain` 必须以统一校验链实现,而不是让每个入口各自拼接。
|
||||
引用:§17.4 “动态授权判定链”
|
||||
|
||||
- [ENGINEERING_DECISION] `URL / token lifecycle` 的一次性使用、重放保护、失效和重发策略必须单独设计。
|
||||
引用:§17.4 “URL / Token 生命周期”
|
||||
|
||||
- [ENGINEERING_DECISION] `OTP` token 方案、rate limit、错误码、审计字段不能留给实现层自行发明。
|
||||
引用:§17.5 “Email OTP 规则”;§16.4 “敏感信息边界待定”
|
||||
|
||||
- [ENGINEERING_DECISION] `审计 schema`、可见字段、脱敏边界、PII 存储策略必须统一设计。
|
||||
引用:§16.2 “审计可见性 / 审计主体”;§16.4 “敏感信息边界待定”
|
||||
|
||||
- [ENGINEERING_DECISION] `文件访问授权` 需要明确对象级校验模型,不应只靠 task token + allowed approver 做隐式实现。
|
||||
引用:§9.3 “文件访问必须同时校验 task、访问者身份、allowed approver 和文件所属 task。”
|
||||
|
||||
- [ENGINEERING_DECISION] `迁移` 与 `旧 DSL 兼容读取` 规则必须统一,而不是散落在节点实现和 workflow 兼容层。
|
||||
引用:§5.0 “旧 workflow DSL 需要保持兼容”;§11.3 “旧 Email recipient 迁移匹配”
|
||||
Reference in New Issue
Block a user