领域合同
- Asset
- ADP-DLV-DOC-DOC-0001
- Feature
- dingtalk-direct-notifications
- 领域
- delivery-integrations
- 文档状态
- draft
- 文档 Owner
- DOC
- 事实源
- canonical-docs
- 更新
- 2026/10/14
当前实现与本次授权
基线为 Plane master 77cf8dd9c4576566dd44b780f5fb24da7d6120da。现有内核登记
work_item.assigned.v1 和 work_item.mentioned.v1,实际 routing 为钉钉单聊;站内和邮件仍使用其现有链路。
本次增加本人相关钉钉事件及个人/项目事件设置,不统一其它渠道、不添加通知视图。
交付 source_id:e7ff8a26-65a7-4ea1-a06e-7e39a62b7398,范围为下表第一批五类消息。
用户于 2026-10-14 在项目对话中批准实施;Linear 保存执行任务,本文保存产品合同。
下述新增行为是交付目标,未经对应源码和外部发布证据不得称为已上线。
旧 Epic、Plane Run、AutomationReview、awaiting-review/request-changes Automation 事件与项目 Run 摘要
不是当前合同。本次不能恢复它们;业务事实来自原生 Issue.state、阶段责任、验收反馈和评论。
第一批事件
| 事件 | 唯一业务来源 | 接收人 | 触发条件 |
|---|---|---|---|
work_item.acceptance_required.v1 | 原生验收阶段进入活动 / 当前验收责任变更 | 当前有效的人类阶段负责人 | Issue 进入 professional_acceptance 或 test,或在该阶段把负责人改为此人 |
work_item.changes_requested.v1 | 已持久化的验收反馈及其退回业务动作 | 退回后执行阶段的人类责任人与当前 Issue assignees 的去重并集 | 专业/测试验收明确退回并要求重新处理;不是任意回退状态或评论关键词 |
work_item.blocked_changed.v1 | 已持久化的原生状态变更 | 执行阶段有效人类责任人与当前 Issue assignees 的去重并集 | progress_role 进入或离开 blocked |
work_item.comment_replied.v1 | 新评论及其明确的 parent | 被直接回复评论的作者 | 别人新增直接回复;不扩展到整条讨论所有参与人,编辑已有回复不重新提醒 |
work_item.due_date_changed.v1 | 已持久化的截止日期变更 | 当前有效人类阶段负责人和当前 Issue assignees 的去重并集 | 别人更改或移除 target_date,且前后值不同 |
当前 assignees、原生 progress role 与有效阶段负责人以 owning issue domain 的公共解析路径为准。 没有明确、有效的人类验收责任时不猜测创建者或 Project Admin;保留无合格收件人的路由诊断。 普通成员身份、关注关系、创建者身份本身不构成第一批收件理由。
收件人和过期语义
- 除系统自动触发外排除 actor;任何事件都排除 bot、inactive user 和无有效 Workspace/Project/Issue 访问权者。
- 回复消息还需校验父评论、新评论的访问范围与存续;父评论作者不可变地绑定到该回复来源。
- 每次路由、实际发送和免打扰后重试都重新检查访问权、当前责任及事件相关性。
- 验收阶段/责任已变化、退回反馈已被新处理覆盖、阻塞状态与冻结值不符、截止日期又变化或来源已删除时 取消过时 delivery;完成、取消或归档的工作不再发送待处理提醒。
- 同一来源里同一用户同时是负责人和 assignee,只生成一条 delivery,并保留合并后的 reasons。
- 同一次新增评论同时直接回复并提及同用户时只发送一条私聊,呈现“回复并提及了你”。 回复偏好关闭而提及仍启用时保留提及提醒,提及关闭而回复开启时保留回复提醒;两者均关闭则不发送。 去重不能通过删除原生 mention 关系或永久忽略另一事件实现。
事件、事务与幂等
沿用不可变 NotificationEvent、NotificationEventOutbox、NotificationRecipient、
NotificationDelivery 与追加写 NotificationDeliveryAttempt。不新增执行器、跨服务 notification ingress、
HTTP webhook 接入、调度系统或另一个通知事实库。
事件由 owning issue、comment 或验收/责任 mutation 在其提交业务事实的同一数据库事务中创建;
提交后沿用 transaction.on_commit 唤醒和既有 Celery sweeper。普通 UI、API、business credential、
bulk mutation 及阶段业务按钮等当前调用方必须统一触发相应 producer,不能只连接一个前端入口。
源身份采用不可变持久化行及其业务变更序列:IssueActivity、新增 IssueComment、阶段进入/责任 revision、
退回 feedback/action identity。进入同一阶段的新一轮验收必须有新的源身份;重复保存和请求重放使用原身份。
退回通知不能由 ready 状态或评论文本推测。source key 格式由实现确定并在交付时记录,所有调用方一次切换。
同 idempotency key/同 digest 返回已有 event/outbox;不同 digest 拒绝并保存脱敏冲突证据。
(event, user, channel) 唯一;回复/提及共享来源时 additionally 收敛为同一逻辑收件人的单次投递。
不重放历史活动、不回填历史 event/delivery、不把普通站内或邮件链路改成并行新旧钉钉路径。
新内核 safe snapshot 仅含来源身份、Issue 编号、短标题、前后状态/日期和低敏感度原因; 不保存完整评论、完整验收反馈、附件、diff、secret 或 Provider raw response。 Deep link 由服务端从持久化实体与可信 base URL 构造,评论回复尽量定位原评论。
设置与权限门
每个新增事件有个人和项目开关,字段由当前 typed API 一次同步到模型、migration、serializer、service、UI 和 i18n。
五个新事件开关默认开启;已有个人 dingtalk_enabled=False、全局关闭、未绑定或未激活连接均保持关闭。
此默认使已经主动启用钉钉的用户获得批准的本人提醒,个人可分别关闭每类事件,Project Admin 可关闭项目内事件。
既有指派/提及的项目设置和值保持原合同,不借本次更改其默认值或开启状态。
门顺序:全局发送开关 → connection mode/readiness → 项目事件开关 → 当前访问权/责任/相关性 → 有效 binding/generation → 个人钉钉与事件开关 → quiet hours。任何后置设置不能绕过前置门。 普通成员只改自己的设置;项目规则只允许对应 Project Admin 或 Workspace Admin。
clean break 与业务边界
受影响的事件 producer、设置 contract 与调用方同步更新,删除失效分支与活跃文档里的退役语义。 不新增 alias、fallback、旧字段映射、双读/双写、双模式或过渡开关。保留重要历史和现有未触及的站内/邮件能力。 通知、Provider accepted、已读或点击均不推进验收、不提交 request-changes、不重试执行、不改变 Issue.state。