Files
devos/Docs/DevOS-Platform-v2/31_NOTIFICATION_COMMUNICATION_RUNTIME.md
phptits 851ccf1d7f v2 platform runtime (docs 22 Phase 2/4/7 + 17): Project/Environment + Config + Storage + Observability
- Project/Environment model with default environments (dev/staging/prod)
- Config Runtime: cascade resolution (platform→org→project→env), secrets via vault
- Storage Runtime: local provider, sha256 dedup, integrity check, file list/upload/delete
- Observability: execution query, per-action summary (success rate, avg, p95), health
- Realtime SSE: workspace event stream endpoint (GET /api/v1/v2/realtime/events)
- Phase 1 acceptance: core.health.check, core.user.create, core.user.list
- Actions: core.project.*, core.config.*, core.file.*, core.user.* (62 total)
2026-09-11 21:11:07 +00:00

4933 lines
51 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DevOS Notification / Communication Runtime
> 文档版本:v1.0
> 文档编号:31
> 状态:Architecture Specification
> 适用范围:DevOS Core / Event / Task / Agent / Workflow / Plugin / MCP / API / SDK / UI
> 项目根目录:`/home/dev/bun/devos`
---
# 1. 文档目标
DevOS 必须提供统一的:
> **Notification / Communication Runtime**
用于处理:
- Notification
- Message
- Communication
- Delivery
- Channel
- Provider
- Template
- Subscription
- Preference
- Recipient
- Audience
- Routing
- Delivery Policy
- Retry
- Rate Limit
- Deduplication
- Scheduling
- Batch Sending
- Webhook
- Email
- Push
- SMS
- In-App Notification
- Provider Failover
- Delivery Tracking
- Bounce / Complaint
- Unsubscribe
- Digest
- Notification Center
- Agent Notification
- Task Notification
- Workflow Notification
- System Alert
核心目标:
> **业务系统只产生“应该通知什么”,Communication Runtime 决定“发给谁、通过什么渠道、什么时候发、如何发送、失败后怎么办”。**
---
# 2. 核心原则
必须严格区分:
```text
Event
Notification
Message
Delivery
Provider
Channel
```
它们不是同一个东西。
---
# 3. Event
Event 表示:
> 系统发生了什么。
例如:
```text
task.completed
plugin.installed
agent.failed
server.offline
article.published
```
Event 不负责发送。
---
# 4. Notification
Notification 表示:
> 某个事件/条件是否需要通知某个受众。
例如:
```text
Task 完成
→ 通知项目负责人
```
Notification 是语义层。
---
# 5. Message
Message 表示:
> 实际准备发送的内容。
例如:
```text
Title:
任务已完成
Body:
SEO 批量生成任务已完成,共生成 100 篇。
```
---
# 6. Delivery
Delivery 表示:
> 一条 Message 通过某个 Channel 向某个 Recipient 进行的一次发送尝试。
例如:
```text
Message
↓
Email
↓
user@example.com
```
这是一次 Delivery。
---
# 7. Provider
Provider 是实际的外部发送实现。
例如:
```text
SMTP
SendGrid
Resend
AWS SES
Twilio
FCM
APNs
Discord
Slack
Generic Webhook
```
Provider 是实现。
---
# 8. Channel
Channel 表示通信方式:
```text
in_app
email
webhook
push
sms
chat
```
Channel 不等于 Provider。
例如:
```text
email
├── SMTP
├── SES
├── Resend
└── SendGrid
```
---
# 9. 总体架构
```text
Event
│
↓
Notification Rules
│
↓
Notification
│
┌────────┴────────┐
↓ ↓
Recipient Template
│ │
└────────┬────────┘
↓
Message
│
↓
Delivery Planner
│
┌────────────┼────────────┐
↓ ↓ ↓
In-App Email Webhook
↓ ↓ ↓
Provider Provider Provider
│ │ │
└────────────┼────────────┘
↓
Delivery
│
┌────────┴────────┐
↓ ↓
Event Observability
```
---
# 10. Runtime 边界
Communication Runtime 负责:
```text
Recipient Resolution
Template Rendering
Channel Selection
Provider Selection
Delivery
Retry
Scheduling
Deduplication
Rate Limit
Status Tracking
```
不负责:
```text
Business Logic
Agent Planning
Task Execution
Authorization
Secret Storage
Event Bus
```
这些由其他 Runtime 提供。
---
# 11. 与 Event Runtime 的关系
Event Runtime:
```text
Action
↓
Execution
↓
Event
```
Communication Runtime:
```text
Event
↓
Notification Rule
↓
Message
↓
Delivery
```
因此:
```text
Event ≠ Notification
```
一个 Event 可以:
```text
不通知
```
也可以:
```text
通知一个人
通知 1000 人
发送 Email
发送 Push
发送 Webhook
生成 Digest
```
---
# 12. 与 Task Runtime 的关系
发送大量消息:
```text
Notification
↓
Task
↓
Jobs
↓
Queue
↓
Worker
↓
Delivery
```
Communication Runtime 不创建自己的 Queue。
---
# 13. 与 Security Runtime 的关系
Communication Runtime 必须使用:
```text
Security Context
Authorization
Scope
Policy
```
但是不实现自己的 Authorization。
例如:
```text
Agent
↓
Notification
↓
Recipient
```
Agent 不能因为拥有 Notification Capability 就读取所有用户邮箱。
---
# 14. Recipient
Recipient 是通知目标。
类型:
```ts
type RecipientType =
| 'user'
| 'organization'
| 'project'
| 'team'
| 'role'
| 'email'
| 'phone'
| 'webhook'
| 'external';
```
---
# 15. Recipient Resolution
通知可以声明:
```text
project.owner
project.members
organization.admins
task.requester
agent.owner
```
Runtime 负责解析:
```text
Recipient Selector
↓
Security Scope
↓
Recipient Resolver
↓
Concrete Recipients
```
---
# 16. Recipient Selector
推荐:
```ts
interface RecipientSelector {
type:
| 'user'
| 'role'
| 'team'
| 'project'
| 'organization'
| 'expression';
id?: string;
role?: string;
filters?: Record<string, unknown>;
}
```
不允许业务代码自己查询用户表发送消息。
---
# 17. Recipient Address
最终 Delivery 需要:
```ts
interface RecipientAddress {
type: 'email' | 'phone' | 'push' | 'webhook' | 'in_app';
valueRef: string;
verified?: boolean;
metadata?: Record<string, unknown>;
}
```
敏感地址必须遵循 Credential / Identity / Security Policy。
---
# 18. 不直接暴露 Recipient 敏感信息
UI、Agent、Plugin 不应该任意读取:
```text
所有用户 Email
所有电话号码
所有 Webhook URL
```
而应该请求:
```text
Notification Capability
```
得到允许使用的 Recipient。
---
# 19. Audience
Audience 表示通知受众。
例如:
```text
Task Owner
Project Admin
SEO Team
Organization Admin
```
Audience 可以是动态计算的。
---
# 20. Audience 与 Recipient
```text
Audience
↓
Recipient Resolver
↓
Recipients
```
例如:
```text
"项目管理员"
```
最终解析为:
```text
User A
User B
User C
```
---
# 21. Notification
统一定义:
```ts
interface Notification {
id: string;
type: string;
sourceEventId?: string;
organizationId?: string;
projectId?: string;
environmentId?: string;
recipients: RecipientSelector[];
channels?: NotificationChannel[];
templateId?: string;
data: Record<string, unknown>;
priority?: 'low' | 'normal' | 'high' | 'critical';
scheduledAt?: Date;
expiresAt?: Date;
}
```
---
# 22. Notification Type
使用稳定的语义 ID。
例如:
```text
task.completed
task.failed
agent.completed
agent.failed
plugin.updated
security.alert
deployment.failed
server.offline
```
插件可以注册:
```text
seo.article.published
seo.scan.completed
```
---
# 23. Notification Type Registry
DevOS 维护统一 Registry。
定义:
```ts
interface NotificationTypeDefinition {
id: string;
description: string;
defaultChannels: NotificationChannel[];
defaultPriority: NotificationPriority;
templateSchema?: unknown;
sensitive?: boolean;
}
```
---
# 24. Notification 不直接发送
禁止:
```ts
sendEmail(...)
```
出现在业务 Service 中。
必须:
```text
Business Event
↓
Notification Runtime
↓
Communication Runtime
```
---
# 25. Message
Message 是渲染后的通信内容。
```ts
interface Message {
id: string;
notificationId: string;
channel: NotificationChannel;
subject?: string;
body: string;
format?: 'text' | 'html' | 'markdown' | 'json';
metadata?: Record<string, unknown>;
}
```
---
# 26. Template Runtime
模板必须独立。
支持:
```text
Email Template
In-App Template
Webhook Template
Push Template
SMS Template
```
---
# 27. Template Version
模板必须版本化:
```text
task.completed@1
task.completed@2
```
Delivery 必须记录:
```text
templateId
templateVersion
```
这样历史消息可以追溯。
---
# 28. Template Rendering
流程:
```text
Template
↓
Variables
↓
Validation
↓
Render
↓
Message
```
禁止模板执行任意代码。
---
# 29. Template Variables
例如:
```text
{{task.name}}
{{task.status}}
{{project.name}}
{{execution.id}}
```
变量来源必须来自:
```text
Notification Context
```
不能直接执行任意 JavaScript。
---
# 30. Template Security
禁止:
```text
eval()
new Function()
arbitrary template code
```
模板只能使用:
```text
approved variables
approved helpers
```
---
# 31. HTML Email
HTML 邮件必须经过:
```text
Template
↓
Render
↓
Sanitize
↓
Message
```
防止:
```text
XSS
unsafe HTML
external injection
```
---
# 32. Markdown
Markdown 只允许在明确支持 Markdown 的 Channel。
例如:
```text
in_app
chat
```
Email 是否转换 HTML 由 Template/Channel Policy 决定。
---
# 33. Channel Registry
统一注册:
```text
in_app
email
webhook
push
sms
chat
```
插件可以贡献新的 Channel Adapter。
---
# 34. In-App Notification
In-App 不需要外部 Provider。
流程:
```text
Notification
↓
Message
↓
In-App Delivery
↓
Notification Store
↓
Realtime
↓
UI
```
---
# 35. Notification Center
UI:
```text
Notifications
├── All
├── Unread
├── Important
├── System
├── Tasks
├── Agents
└── Security
```
---
# 36. Read State
每个用户需要:
```text
readAt
seenAt
archivedAt
```
Notification 内容本身可以共享。
Delivery/User State 单独存储。
---
# 37. Realtime
新通知:
```text
Notification
↓
Event Runtime
↓
Realtime Runtime
↓
SSE / WebSocket
↓
UI
```
不要创建第二套 WebSocket Runtime。
---
# 38. Email Channel
Email Channel 负责:
```text
Message
↓
Email Provider
```
Provider 可以:
```text
SMTP
SES
Resend
SendGrid
```
---
# 39. Email Provider
Provider Adapter:
```ts
interface EmailProvider {
send(
message: EmailMessage,
context: DeliveryContext,
): Promise<ProviderDeliveryResult>;
}
```
---
# 40. SMTP
SMTP Provider 可以使用:
```text
host
port
username
credential
```
Credential 通过:
```text
Credential Runtime
```
管理。
---
# 41. Email 不直接读取 Secret
禁止:
```ts
process.env.SMTP_PASSWORD
```
业务代码直接使用。
必须:
```text
Communication Runtime
↓
Provider Resolver
↓
Credential Runtime
↓
Secret Runtime
```
---
# 42. Webhook Channel
Webhook 是:
```text
Notification
↓
JSON Message
↓
Webhook Delivery
```
---
# 43. Webhook Security
必须支持:
```text
HMAC Signature
Timestamp
Nonce
Replay Protection
Timeout
Retry
```
---
# 44. SSRF Protection
Webhook URL 必须经过:
```text
Network Policy
```
禁止访问:
```text
127.0.0.1
localhost
169.254.169.254
internal network
private CIDR
```
除非明确允许。
---
# 45. Webhook Payload
统一:
```json
{
"id": "delivery-id",
"type": "task.completed",
"timestamp": "2026-09-12T00:00:00Z",
"data": {}
}
```
---
# 46. Webhook Version
Webhook Schema 必须版本化:
```text
v1
v2
```
Event Type:
```text
task.completed
```
Schema:
```text
eventVersion: 1
```
---
# 47. Push
Push Channel 可以支持:
```text
FCM
APNs
Web Push
```
Provider Adapter 统一:
```text
Push Runtime
↓
Provider
```
---
# 48. SMS
SMS 也作为 Channel:
```text
sms
```
Provider:
```text
Twilio
Vonage
Custom
```
SMS 必须受到:
```text
cost
rate limit
country policy
user preference
```
约束。
---
# 49. Chat Channel
未来支持:
```text
Slack
Discord
Teams
Telegram
```
但都统一为:
```text
chat
```
然后 Provider Adapter。
---
# 50. Channel Policy
用户可能:
```text
Email = enabled
Push = enabled
SMS = disabled
```
项目可能:
```text
SMS = forbidden
```
Organization 可能:
```text
External Webhook = disabled
```
最终:
```text
Global Policy
↓
Organization Policy
↓
Project Policy
↓
User Preference
↓
Notification Policy
```
---
# 51. Notification Preference
用户可以设置:
```text
Task Completed
In-App ✓
Email ✓
Push ✓
Task Failed
In-App ✓
Email ✓
Push ✓
Marketing
Email ✗
```
---
# 52. Preference 不等于 Security
Preference:
> 用户想不想收到?
Security:
> 系统允不允许发送?
所以:
```text
Security Policy
↓
Preference
↓
Delivery Policy
```
---
# 53. Critical Notification
某些通知:
```text
security.alert
production.down
critical.failure
```
可能:
```text
不能被普通偏好完全关闭
```
但必须明确由:
```text
Notification Policy
```
决定。
---
# 54. Notification Routing
例如:
```text
task.failed
```
Routing:
```text
In-App
Email
```
而:
```text
task.completed
```
可能只有:
```text
In-App
```
---
# 55. Routing Policy
```ts
interface NotificationPolicy {
notificationType: string;
channels: NotificationChannel[];
priority?: NotificationPriority;
quietHours?: boolean;
dedupeWindowSeconds?: number;
digest?: boolean;
}
```
---
# 56. Quiet Hours
支持:
```text
22:00 - 08:00
```
普通通知:
```text
delay
```
Critical:
```text
send immediately
```
由 Policy 决定。
---
# 57. Digest
大量通知可以合并:
```text
100 Task Completed
```
变成:
```text
今日任务摘要
完成 100 个任务
失败 3 个任务
```
---
# 58. Digest Runtime
流程:
```text
Notifications
↓
Group
↓
Aggregate
↓
Digest Template
↓
Message
↓
Delivery
```
Digest 不需要第二套 Queue。
---
# 59. Deduplication
例如:
```text
server.offline
```
短时间内连续产生:
```text
100 Events
```
不能发送:
```text
100 Email
```
支持:
```text
dedupeKey
dedupeWindow
```
---
# 60. Dedup Key
例如:
```text
server.offline:{serverId}
```
或者:
```text
task.failed:{taskId}
```
---
# 61. Delivery
```ts
interface Delivery {
id: string;
notificationId: string;
messageId: string;
channel: NotificationChannel;
providerId?: string;
recipientId?: string;
status:
| 'pending'
| 'scheduled'
| 'sending'
| 'sent'
| 'delivered'
| 'failed'
| 'retrying'
| 'cancelled';
attempts: number;
scheduledAt?: Date;
sentAt?: Date;
deliveredAt?: Date;
failedAt?: Date;
providerMessageId?: string;
}
```
---
# 62. Delivery Attempt
一次 Delivery 可以:
```text
Attempt 1
↓ fail
Attempt 2
↓ fail
Attempt 3
↓ success
```
必须记录每次 Attempt。
---
# 63. Delivery Attempt Schema
```ts
interface DeliveryAttempt {
id: string;
deliveryId: string;
attempt: number;
providerId: string;
startedAt: Date;
completedAt?: Date;
status: 'success' | 'failed';
providerStatus?: string;
providerRequestId?: string;
errorCode?: string;
latencyMs?: number;
}
```
---
# 64. Retry
支持:
```text
fixed
linear
exponential
jitter
```
例如:
```text
1 min
5 min
15 min
1 hour
```
---
# 65. Retryable Error
通常:
```text
timeout
429
5xx
temporary network error
provider unavailable
```
可以 Retry。
通常不能:
```text
invalid recipient
invalid credentials
invalid template
permission denied
unsubscribed
```
---
# 66. Dead Letter Queue
多次失败:
```text
Delivery
↓
Retry
↓
Retry
↓
DLQ
```
DLQ 使用:
```text
Task / Job Runtime
```
已有 Queue Runtime。
---
# 67. Manual Replay
管理员可以:
```text
Replay Delivery
```
但必须:
```text
permission
audit
idempotency
```
---
# 68. Idempotency
发送通信也必须考虑:
```text
network timeout
provider accepted
response lost
```
因此:
```text
Idempotency-Key
```
非常重要。
---
# 69. Provider Message ID
Provider 返回:
```text
providerMessageId
```
必须保存。
用于:
```text
delivery tracking
provider webhook
debugging
dedupe
```
---
# 70. Delivery Status
标准状态:
```text
pending
scheduled
sending
sent
delivered
failed
retrying
cancelled
```
Email 可能额外:
```text
bounced
complained
```
---
# 71. Bounce
Email Provider 可能通知:
```text
bounce
```
Event:
```text
communication.email.bounced
```
进入:
```text
Event Runtime
```
---
# 72. Complaint
同样:
```text
communication.email.complained
```
可更新:
```text
Recipient Preference
```
防止继续发送。
---
# 73. Unsubscribe
必须支持:
```text
global unsubscribe
channel unsubscribe
notification-type unsubscribe
```
但系统安全通知可以由 Policy 决定是否可关闭。
---
# 74. Consent
营销/商业通信如果涉及用户同意:
```text
Consent
```
应该独立建模。
不要简单用:
```text
notification_preferences
```
替代所有法律/合规语义。
---
# 75. Consent Runtime
如果产品需要:
```text
consent
withdrawal
proof
timestamp
source
policyVersion
```
建议独立:
```text
Consent Runtime
```
Communication Runtime 消费 Consent 状态。
---
# 76. Communication Provider
统一 Provider:
```ts
interface CommunicationProvider {
id: string;
channel: NotificationChannel;
capabilities: string[];
send(
message: Message,
context: DeliveryContext,
): Promise<ProviderDeliveryResult>;
}
```
---
# 77. Provider Health
Provider 必须支持:
```text
healthy
degraded
down
disabled
```
Communication Router 根据健康状态选择。
---
# 78. Provider Failover
例如:
```text
Email
↓
Provider A
↓ timeout
Provider B
```
但要特别注意:
> Provider A 可能已经接受消息但响应丢失。
因此 Failover 必须依赖:
```text
idempotency
provider semantics
delivery state
```
不能简单地认为 timeout = 未发送。
---
# 79. Communication Router
流程:
```text
Delivery
↓
Allowed Channels
↓
Provider Candidates
↓
Credential Check
↓
Health
↓
Rate Limit
↓
Cost
↓
Policy
↓
Selected Provider
```
---
# 80. Cost Routing
SMS/Email/Push 可能有不同成本。
Router 可以考虑:
```text
cost
latency
reliability
region
```
但:
```text
security
consent
policy
```
仍然是 Hard Filter。
---
# 81. Region
Provider 可以声明:
```text
region
dataResidency
supportedCountries
```
Policy 可以要求:
```text
Japan
EU
US
```
Router 过滤不符合要求的 Provider。
---
# 82. Communication Rate Limit
支持:
```text
global
organization
project
user
recipient
provider
channel
notificationType
```
例如:
```text
每用户每小时最多 10 条 SMS。
```
---
# 83. Anti-Spam
批量 Agent 自动化特别容易产生:
```text
10000 Email
```
因此必须支持:
```text
quota
rate limit
daily limit
per-recipient limit
per-notification-type limit
```
---
# 84. Batch Sending
批量发送:
```text
Notification
↓
Task
↓
Jobs
↓
Queue
↓
Workers
```
每个 Job 可以处理:
```text
100 recipients
```
具体 batch size 由 Provider Capability 决定。
---
# 85. Parallel Sending
可以并发:
```text
Worker 1
Worker 2
Worker 3
```
但必须遵守:
```text
provider concurrency
channel rate limit
organization quota
```
---
# 86. Scheduling
Notification 可以:
```text
send now
send at time
delay
digest
```
例如:
```text
Task 完成
↓
Delay 5 min
↓
Email
```
Schedule 交给:
```text
Scheduler Runtime
```
---
# 87. Event Trigger
Event 可以触发:
```text
Notification Rule
```
例如:
```text
deployment.failed
```
触发:
```text
security/admin notification
```
---
# 88. Workflow Trigger
Workflow 可以执行:
```text
notification.send
```
例如:
```text
Webhook
↓
Process
↓
Approval
↓
Notification
```
但发送仍然走:
```text
Communication Runtime
```
---
# 89. Agent Notification
Agent 可以请求:
```text
notify user
```
但 Agent 只能提出:
```text
Notification Request
```
最终:
```text
Security
↓
Preference
↓
Policy
↓
Communication Runtime
```
---
# 90. Agent 不直接 Email
禁止:
```text
Agent
↓
SMTP
```
禁止:
```text
Agent
↓
SendGrid API
```
必须:
```text
Agent
↓
Capability
↓
Action
↓
Communication Runtime
```
---
# 91. Plugin Notification
Plugin 可以注册:
```text
notification types
templates
channels
providers
```
但不能建立:
```text
Plugin-owned Notification Runtime
```
---
# 92. MCP Notification
MCP 可以暴露:
```text
notification.send
```
但:
```text
MCP
↓
Action Runtime
↓
Communication Runtime
```
不能绕过权限。
---
# 93. API
推荐:
```text
POST /v1/actions/notification.send
GET /v1/notifications
GET /v1/notifications/:id
POST /v1/notifications/:id/read
POST /v1/notifications/:id/archive
GET /v1/notification-preferences
PUT /v1/notification-preferences
GET /v1/deliveries
GET /v1/deliveries/:id
```
---
# 94. SDK
```ts
sdk.notifications.list();
sdk.notifications.markRead();
sdk.notifications.send();
sdk.notifications.preferences.get();
sdk.notifications.preferences.update();
```
SDK 不负责发送 Provider API。
---
# 95. CLI
建议:
```bash
devos notification list
devos notification inspect <id>
devos notification send-test
devos notification preferences
devos delivery list
devos delivery inspect <id>
devos delivery retry <id>
devos communication provider list
devos communication provider health
devos communication doctor
```
---
# 96. Notification UI
建议:
```text
System
└── Notifications
├── Notification Center
├── Preferences
├── Templates
├── Channels
├── Providers
├── Deliveries
└── Failed / DLQ
```
---
# 97. Delivery Inspector
显示:
```text
Delivery ID
Notification ID
Recipient
Channel
Provider
Status
Attempts
Created
Scheduled
Sent
Delivered
Error
Provider Message ID
```
---
# 98. 不默认显示敏感信息
例如:
```text
Webhook URL
Email Address
Phone
Provider Credential
```
需要根据权限脱敏。
---
# 99. Template UI
管理员可以:
```text
Create
Edit
Preview
Validate
Publish
Deprecate
```
Template 发布后版本固定。
---
# 100. Template Preview
支持:
```text
Preview Email
Preview Push
Preview In-App
Preview Webhook JSON
```
使用:
```text
sample context
```
不能真实发送。
---
# 101. Test Delivery
提供:
```text
Send Test
```
必须明确:
```text
permission
audit
rate limit
```
防止管理员误发送大量消息。
---
# 102. Notification Search
Global Search 可以搜索:
```text
notification
delivery
template
provider
```
但必须应用:
```text
Security Scope
```
---
# 103. Notification Data Model
建议:
```text
notifications
notification_recipients
notification_messages
notification_templates
notification_template_versions
notification_preferences
notification_policies
deliveries
delivery_attempts
communication_providers
communication_provider_credentials
communication_provider_health
notification_digests
notification_subscriptions
```
---
# 104. In-App 数据
可以额外:
```text
notification_user_state
```
保存:
```text
readAt
seenAt
archivedAt
```
避免修改共享 Notification。
---
# 105. Provider Credentials
数据库只保存:
```text
credentialId
```
而不是:
```text
smtpPassword
apiKey
webhookSecret
```
实际 Secret:
```text
Secret Runtime
```
---
# 106. Outbox
Event → Notification 的可靠性建议使用:
```text
Transactional Outbox
```
例如:
```text
Business Transaction
├── Resource Update
└── Outbox Event
↓
Event Runtime
↓
Notification Runtime
```
避免:
```text
DB 成功
Email 逻辑失败
```
导致状态不一致。
---
# 107. Notification Event
推荐:
```text
notification.created
notification.scheduled
notification.sent
notification.failed
notification.cancelled
notification.deduplicated
```
---
# 108. Delivery Event
推荐:
```text
delivery.created
delivery.started
delivery.sent
delivery.delivered
delivery.failed
delivery.retrying
delivery.cancelled
delivery.bounced
delivery.complained
```
---
# 109. Event Runtime Integration
这些 Event 全部进入:
```text
Event Runtime
```
不能:
```text
Notification Event Bus
```
另起一套。
---
# 110. Observability
所有 Delivery 必须有:
```text
requestId
correlationId
notificationId
deliveryId
attemptId
providerId
```
---
# 111. Metrics
至少:
```text
notifications_created_total
deliveries_total
deliveries_success_total
deliveries_failed_total
deliveries_retry_total
delivery_latency_ms
provider_failures_total
provider_rate_limit_total
email_bounce_total
email_complaint_total
notification_deduplicated_total
```
---
# 112. Cost
Communication Cost 可以计入:
```text
organization
project
agent
task
job
notification
delivery
provider
channel
```
例如:
```text
SMS:
$0.01 × 1000
```
最终可以归因到:
```text
Agent Task
```
---
# 113. Usage
统一 Usage:
```text
emails sent
SMS sent
push sent
webhooks sent
in-app notifications
```
并可以和:
```text
Model Usage
Storage Usage
Network Usage
```
统一进入:
```text
Usage Runtime
```
---
# 114. Budget
通信也应该支持:
```text
daily budget
monthly budget
per-task budget
per-project budget
```
例如:
```text
Agent Task:
Max communication cost = $2
```
达到预算:
```text
COMMUNICATION_BUDGET_EXCEEDED
```
---
# 115. Priority
支持:
```text
low
normal
high
critical
```
Queue 优先级由 Task/Job Runtime 处理。
---
# 116. Cancellation
尚未发送:
```text
pending
scheduled
```
可以取消。
已经发送:
```text
sent
```
不能假装取消。
因此:
```text
cancel()
```
只影响尚未执行的 Delivery。
---
# 117. Expiration
Notification 可以设置:
```text
expiresAt
```
例如:
```text
Task Approval
```
过期后:
```text
不要继续发送
```
---
# 118. Approval Notification
Approval Runtime 可以产生:
```text
approval.requested
approval.approved
approval.rejected
approval.expired
```
Communication Runtime 负责通知。
但:
```text
Communication Runtime
```
不负责 Approval Decision。
---
# 119. Security Alert
Security Runtime 可以产生:
```text
security.alert
```
Communication Runtime 负责:
```text
In-App
Email
Push
```
Security Runtime 不直接操作 SMTP。
---
# 120. Task Notification
Task Runtime 可以产生:
```text
task.started
task.completed
task.failed
task.cancelled
```
Communication Runtime 负责通知。
---
# 121. Agent Notification
Agent Runtime 可以产生:
```text
agent.started
agent.waiting
agent.completed
agent.failed
agent.approval_required
```
Communication Runtime 负责发送。
---
# 122. Workflow Notification
Workflow 可以声明:
```text
notify:
type: workflow.failed
recipients:
- project.owner
```
Workflow Engine 不直接发送。
---
# 123. Communication Context
模板渲染使用:
```ts
interface CommunicationContext {
notification: Notification;
event?: EventReference;
actor?: ActorReference;
organization?: ResourceReference;
project?: ResourceReference;
task?: ResourceReference;
job?: ResourceReference;
execution?: ResourceReference;
data: Record<string, unknown>;
}
```
---
# 124. Context Security
Communication Context 必须经过:
```text
Authorization
Scope
Field Permission
Redaction
```
防止模板意外输出敏感字段。
---
# 125. Template Field Permission
例如模板想使用:
```text
{{user.email}}
```
必须判断:
```text
communication context
+
recipient visibility
```
不能因为模板管理员可以编辑模板,就自动获得所有用户字段。
---
# 126. External Recipient
如果 Recipient 是:
```text
external email
```
必须确认:
```text
data policy
external sharing policy
```
否则可能产生数据泄露。
---
# 127. External Webhook
Webhook 更加敏感。
需要:
```text
allowed domains
network policy
payload policy
signature
```
---
# 128. Webhook Secret
Webhook Secret:
```text
Secret Runtime
```
签名:
```text
HMAC
```
Secret 不能进入:
```text
logs
events
audit
delivery payload
```
---
# 129. Email Security
支持:
```text
SPF
DKIM
DMARC
```
但这些属于:
```text
Provider / Domain Configuration
```
不是 Notification Runtime 自己实现邮件服务器。
---
# 130. Email Tracking
如果业务需要:
```text
open
click
bounce
complaint
```
可以接入 Provider Webhook。
但需要注意:
```text
privacy
consent
regional policy
```
---
# 131. Provider Webhook
Provider 状态回调:
```text
Provider
↓
Webhook Endpoint
↓
Authentication
↓
Event Runtime
↓
Delivery Update
```
不能直接修改业务表。
---
# 132. Provider Webhook Idempotency
Provider 可能重复发送:
```text
delivered
delivered
delivered
```
必须:
```text
eventId / providerEventId
```
去重。
---
# 133. Communication Provider Plugin
未来可以安装:
```text
@devos/provider-resend
@devos/provider-twilio
@devos/provider-slack
```
但它们只能提供:
```text
Provider Adapter
```
不能拥有:
```text
Notification Runtime
Queue
Audit
Permission
Secret Runtime
```
---
# 134. Plugin Notification Extension
插件可以贡献:
```text
Notification Type
Template
Recipient Resolver
Channel
Provider
```
例如 SEO Plugin:
```text
seo.scan.completed
seo.keyword.alert
seo.article.published
```
---
# 135. Plugin UI
插件可以贡献:
```text
Notification Settings
Template Settings
Provider Settings
Dashboard Widget
```
但使用:
```text
DevOS UI Shell
```
不能创建第二套 Notification Center。
---
# 136. MCP
MCP 可以暴露:
```text
notification.send
notification.list
notification.mark_read
```
但全部进入:
```text
Security
↓
Action Runtime
↓
Communication Runtime
```
---
# 137. Agent Capability
Agent 可看到:
```text
notification.send
```
但 Capability Discovery 必须根据:
```text
permission
scope
channel
recipient
policy
```
过滤。
---
# 138. Agent Notification Example
Agent:
```text
任务已经完成。
```
请求:
```json
{
"type": "task.completed",
"recipient": "task.requester",
"channels": ["in_app", "email"]
}
```
Runtime:
```text
Security
↓
Resolve Recipient
↓
Check Preference
↓
Check Policy
↓
Render Template
↓
Create Delivery
↓
Queue
↓
Provider
```
---
# 139. Batch Agent Example
例如:
```text
生成 100 篇文章
```
完成后不要:
```text
Agent → 100 Email
```
而:
```text
Task
↓
Event
↓
Notification
↓
Digest
↓
Email
```
可以最终只发:
```text
任务完成:
100 篇文章
97 成功
3 失败
```
---
# 140. Communication Runtime 不做业务摘要
“100 篇文章,97 成功,3 失败”应该由:
```text
Task / Agent / Workflow
```
提供结构化数据。
Communication Runtime 只负责:
```text
Render
Deliver
Track
```
---
# 141. Digest 可以聚合,但不理解业务
Digest Runtime 可以:
```text
count
group
sum
```
例如:
```text
100 task.completed
```
但不应该理解:
```text
SEO
CRM
DevOps
```
---
# 142. Message Localization
支持:
```text
en-US
zh-CN
ja-JP
```
模板:
```text
task.completed.en
task.completed.zh
task.completed.ja
```
---
# 143. Locale Resolution
优先级:
```text
Recipient Preference
↓
Project
↓
Organization
↓
System Default
```
---
# 144. Timezone
Notification Scheduler 必须考虑:
```text
recipient timezone
project timezone
organization timezone
```
例如:
```text
每日 09:00
```
不是服务器 UTC 09:00。
---
# 145. Internationalization
Notification Type 不应该直接存:
```text
任务完成
```
而存:
```text
task.completed
```
模板负责本地化。
---
# 146. Accessibility
In-App Notification 必须支持:
```text
ARIA
keyboard navigation
screen reader
contrast
notification grouping
```
---
# 147. Notification Center Performance
不要一次加载:
```text
100000 notifications
```
必须:
```text
cursor pagination
```
推荐:
```text
createdAt + id
```
作为稳定排序。
---
# 148. Notification Read Optimization
未读数:
```text
unread_count
```
可以使用缓存/计数,但 PostgreSQL 作为最终一致性 Source of Truth。
---
# 149. Redis
Redis 可以用于:
```text
unread count cache
rate limit
dedupe lock
delivery concurrency
provider health cache
```
不能成为:
```text
notification source of truth
```
---
# 150. Storage
如果消息包含附件:
```text
Message
↓
Attachment
↓
Storage Runtime
```
Communication Runtime 不自己管理 Blob。
---
# 151. Large Attachments
Email 附件不应该直接把:
```text
100MB
```
塞进数据库。
使用:
```text
Storage Reference
```
Provider 根据能力:
```text
signed URL
stream
attachment
```
发送。
---
# 152. Artifact
Task 生成:
```text
report.pdf
```
应该:
```text
Artifact
↓
Storage
```
Notification 只引用:
```text
artifactId
```
---
# 153. Communication 与 Artifact
正确:
```text
Artifact
↓
Message Attachment Reference
↓
Provider
```
错误:
```text
Notification DB
↓
复制整个 PDF Blob
```
---
# 154. Data Retention
不同数据可以有不同 retention:
```text
Notification
Delivery
Delivery Attempt
Provider Response
Message Content
Audit
```
---
# 155. Message Content Retention
敏感通信内容不能无限保存。
支持:
```text
retention policy
redaction
deletion
archive
```
---
# 156. Audit Retention
Audit 按:
```text
Audit Runtime
```
的规则保存。
Communication Runtime 不自己定义完整 Audit System。
---
# 157. Privacy
Communication Runtime 必须支持:
```text
data minimization
purpose limitation
retention
redaction
access control
export
deletion
```
---
# 158. User Data Export
如果平台需要用户数据导出:
```text
Notification
Delivery
Preferences
```
可以通过:
```text
Export Runtime
```
统一导出。
---
# 159. Deletion
删除用户时:
```text
Identity
↓
Data Lifecycle
↓
Notification References
```
按照平台 Data Retention Policy 处理。
---
# 160. Tenant Isolation
必须保证:
```text
Organization A
```
无法读取:
```text
Organization B
```
的:
```text
Notification
Delivery
Template
Provider
Recipient
```
---
# 161. Project Isolation
同一个 Organization 内:
```text
Project A
```
默认不能读取:
```text
Project B
```
的项目级 Notification。
---
# 162. Environment Isolation
例如:
```text
production
```
不能错误发送:
```text
staging recipient
```
必须通过:
```text
Environment Scope
```
隔离。
---
# 163. Production Guard
Production 可以要求:
```text
approved provider
verified sender
verified domain
```
防止测试配置向真实用户发消息。
---
# 164. Development Safety
Development 环境建议:
```text
Email → Mailpit
SMS → Mock
Push → Mock
Webhook → Local Receiver
```
防止开发环境误发真实消息。
---
# 165. Test Provider
必须提供:
```text
MockCommunicationProvider
```
支持:
```text
success
failure
timeout
rate limit
bounce
duplicate
provider accepted but response lost
```
---
# 166. Contract Tests
必须测试:
```text
Provider Adapter
Notification Routing
Template Rendering
Recipient Resolution
Preference
Deduplication
Retry
Rate Limit
Scheduling
Delivery
Webhook
```
---
# 167. Security Tests
必须测试:
```text
Tenant isolation
Recipient authorization
Template injection
SSRF
Webhook signature
Secret leakage
External sharing
Unsubscribe
Agent authorization
Plugin authorization
MCP authorization
```
---
# 168. Delivery Tests
必须覆盖:
```text
success
failure
retry
DLQ
manual replay
timeout
provider failover
idempotency
duplicate provider webhook
```
---
# 169. Notification Tests
必须覆盖:
```text
event → notification
notification → recipients
preferences
quiet hours
critical notifications
digest
dedupe
expiration
localization
```
---
# 170. Performance Tests
测试:
```text
10k notifications
100k deliveries
large recipient list
high concurrency
provider rate limit
large digest
```
重点不是单纯吞吐,而是:
```text
不会重复发送
不会跨租户
不会突破 Provider Rate Limit
不会突破预算
```
---
# 171. Failure Recovery
Worker Crash:
```text
Delivery
↓
Lease
↓
Worker crash
↓
Lease expire
↓
Retry
```
继续使用:
```text
Task/Job/Queue/Worker Runtime
```
---
# 172. Provider Down
```text
Provider A
↓
down
```
Router:
```text
Provider B
```
如果没有备用:
```text
Delivery → retry
```
最终:
```text
DLQ
```
---
# 173. Network Timeout
如果:
```text
request timeout
```
不能直接假设:
```text
provider did not receive
```
必须使用:
```text
idempotency
provider status
providerMessageId
```
尽可能判断。
---
# 174. Communication State Machine
```text
pending
↓
scheduled
↓
sending
├──→ sent
│ ↓
│ delivered
│
└──→ retrying
↓
sending
↓
failed
↓
DLQ
```
---
# 175. Notification State
Notification:
```text
created
scheduled
processing
partially_sent
completed
failed
cancelled
expired
```
---
# 176. Partial Completion
例如:
```text
100 recipients
97 delivered
3 failed
```
Notification:
```text
partially_completed
```
而不是:
```text
failed
```
---
# 177. Aggregated Delivery Status
可以计算:
```text
total
pending
sending
sent
delivered
failed
```
用于:
```text
Notification Detail
```
---
# 178. Communication Doctor
CLI:
```bash
devos communication doctor
```
检查:
```text
Provider
Credential
DNS
SMTP
Webhook
Rate Limit
Templates
Scheduler
Queue
Worker
Event
Realtime
```
---
# 179. Provider Test
```bash
devos communication provider test <id>
```
应该执行:
```text
credential check
connectivity
test message
provider response
```
测试消息必须明确标记:
```text
TEST
```
---
# 180. Architecture Package
推荐:
```text
packages/
├── notification/
│ ├── domain/
│ ├── runtime/
│ ├── policy/
│ ├── template/
│ ├── recipient/
│ ├── routing/
│ ├── preference/
│ ├── digest/
│ └── testing/
│
├── communication/
│ ├── runtime/
│ ├── provider/
│ ├── delivery/
│ ├── email/
│ ├── webhook/
│ ├── push/
│ ├── sms/
│ └── chat/
```
如果项目当前规模较小:
```text
packages/notification/
```
内部模块化即可。
---
# 181. Provider Package
未来:
```text
packages/communication/providers/
├── mock/
├── smtp/
├── ses/
├── resend/
├── twilio/
├── fcm/
├── apns/
├── slack/
└── generic-webhook/
```
不要求一次全部实现。
---
# 182. Recommended Initial Providers
第一阶段只需要:
```text
Mock
In-App
SMTP
Generic Webhook
```
之后再增加:
```text
Push
SMS
Chat
```
---
# 183. 为什么不一开始实现所有 Channel
因为 DevOS 的目标是:
> 建立统一 Runtime,而不是第一天实现几十个 Provider。
先保证:
```text
Notification
↓
Delivery
↓
Provider
```
架构稳定,再增加 Provider。
---
# 184. 与 API / Integration Runtime 的关系
26 号文档定义:
```text
Integration / Provider Runtime
```
Communication Runtime 应复用:
```text
Credential
Network
Provider
Webhook
Rate Limit
```
不要重新实现。
---
# 185. 与 Event Runtime 的关系
16 号:
```text
Event Runtime
```
负责:
```text
Event
Event Store
Event Bus
Replay
Subscription
Webhook
Realtime
```
31 号:
```text
Notification Runtime
```
消费 Event。
---
# 186. 与 Observability Runtime 的关系
17 号:
```text
Observability
```
负责:
```text
Log
Metric
Trace
Audit
Alert
```
31 号只产生 telemetry。
---
# 187. 与 Configuration Runtime 的关系
18 号:
```text
Configuration Runtime
```
负责:
```text
SMTP host
Provider configuration
Channel configuration
```
Secret:
```text
Secret Runtime
```
---
# 188. 与 Storage Runtime 的关系
15 号:
```text
Storage Runtime
```
负责:
```text
attachments
artifacts
large files
```
Communication Runtime 只引用。
---
# 189. 与 Model Runtime 的关系
30 号:
```text
Model Runtime
```
可以用于:
```text
AI-generated notification
translation
summarization
classification
```
例如:
```text
Notification Data
↓
Model Runtime
↓
Localized Summary
↓
Communication Runtime
```
但这不是 Communication Runtime 自己调用 Provider。
---
# 190. AI Notification
如果需要:
```text
“帮我把这 20 个任务失败信息总结成一封邮件”
```
正确:
```text
Agent
↓
Model Runtime
↓
Structured Result
↓
Notification
↓
Communication Runtime
```
---
# 191. Model Failure
如果 AI Summary 失败:
```text
Communication Runtime
```
应该可以使用:
```text
fallback template
```
而不是让整个通知系统失败。
---
# 192. Agent + Communication
最终:
```text
Agent
↓
Goal
↓
Task
↓
Action
↓
Event
↓
Notification
↓
Communication
```
这样 Agent 不需要理解:
```text
SMTP
FCM
Twilio
```
---
# 193. Project Factory
Project Manifest 可以声明:
```yaml
capabilities:
- notification
- email
- webhook
```
Factory 根据 Capability 安装:
```text
Notification Runtime
Provider Modules
UI
API
```
---
# 194. Plugin Manifest
插件可以声明:
```yaml
notifications:
- type: seo.scan.completed
- type: seo.article.published
templates:
- seo.scan.completed
```
---
# 195. Plugin Permission
例如:
```yaml
permissions:
- notification.create
- notification.read
```
如果插件需要:
```text
external email
```
还应该明确:
```text
communication.email.send
```
---
# 196. Agent Capability
Agent 默认只获得:
```text
notification.send
```
如果需要外部渠道:
```text
notification.send.email
notification.send.webhook
```
需要额外授权。
---
# 197. MCP Capability
MCP Capability:
```text
notification.send
```
实际:
```text
MCP
↓
Security Context
↓
Action Runtime
↓
Notification Runtime
```
---
# 198. No Second Communication Runtime
绝对禁止:
```text
Plugin EmailService
Agent EmailService
Workflow EmailService
SEO EmailService
```
最终全部应该使用:
```text
Communication Runtime
```
---
# 199. Architecture Contract
任何发送行为必须满足:
```text
Security
↓
Authorization
↓
Scope
↓
Notification
↓
Delivery
↓
Communication Provider
```
---
# 200. Zcode Forbidden Patterns
禁止:
```ts
await transporter.sendMail(...)
```
出现在:
```text
business service
agent
plugin
workflow
controller
mcp
```
禁止:
```ts
fetch(webhookUrl)
```
直接出现在业务逻辑。
禁止:
```ts
twilio.messages.create(...)
```
直接出现在 Agent/Plugin。
---
# 201. Zcode Correct Pattern
```ts
await actionRuntime.execute(
'notification.send',
{
type: 'task.completed',
recipients: [
{
type: 'user',
id: userId,
},
],
data: {
taskId,
},
},
context,
);
```
之后:
```text
Action Runtime
↓
Notification Runtime
↓
Communication Runtime
↓
Provider
```
---
# 202. Implementation Phase 1
实现:
```text
Notification Domain
Notification Type Registry
Recipient
Message
Delivery
```
先使用:
```text
Mock Provider
```
---
# 203. Implementation Phase 2
实现:
```text
Template Runtime
Preference
Routing
Deduplication
Retry
```
---
# 204. Implementation Phase 3
实现:
```text
In-App
Realtime
Notification Center
```
---
# 205. Implementation Phase 4
实现:
```text
SMTP
Generic Webhook
```
---
# 206. Implementation Phase 5
实现:
```text
Provider Health
Failover
Rate Limit
Budget
Cost
Usage
```
---
# 207. Implementation Phase 6
实现:
```text
Push
SMS
Chat
```
按真实业务需要逐步添加。
---
# 208. Implementation Phase 7
实现:
```text
Digest
Quiet Hours
Scheduling
Localization
Advanced Preferences
```
---
# 209. Implementation Phase 8
接入:
```text
Agent
Workflow
Plugin
MCP
Task
Event
```
---
# 210. Definition of Done
Notification / Communication Runtime 完成必须至少满足:
```text
[ ] Notification Domain
[ ] Message
[ ] Recipient
[ ] Audience
[ ] Template
[ ] Template Version
[ ] Channel
[ ] Provider
[ ] Delivery
[ ] Delivery Attempt
[ ] Retry
[ ] DLQ
[ ] Deduplication
[ ] Preference
[ ] Routing Policy
[ ] Quiet Hours
[ ] Scheduling
[ ] Digest
[ ] In-App
[ ] Email
[ ] Webhook
[ ] Provider Health
[ ] Provider Failover
[ ] Rate Limit
[ ] Budget
[ ] Usage
[ ] Cost
[ ] Realtime
[ ] Event Integration
[ ] Task Integration
[ ] Agent Integration
[ ] Plugin Integration
[ ] MCP Integration
[ ] Security
[ ] Audit
[ ] Observability
[ ] Localization
[ ] Contract Tests
[ ] Security Tests
[ ] Mock Provider
```
---
# 211. Security Definition of Done
必须证明:
```text
[ ] No cross-tenant notification access
[ ] No unauthorized recipient access
[ ] No secret leakage
[ ] No webhook SSRF
[ ] No template code execution
[ ] No unauthorized external communication
[ ] No preference bypass
[ ] No Agent privilege escalation
[ ] No Plugin privilege escalation
[ ] No MCP privilege escalation
[ ] No duplicate delivery after retry
```
---
# 212. Performance Definition of Done
必须证明:
```text
[ ] Async batch delivery
[ ] Provider rate limiting
[ ] Worker concurrency control
[ ] Delivery lease recovery
[ ] Notification pagination
[ ] Deduplication
[ ] Backpressure
[ ] Provider failover
```
---
# 213. 最终 Runtime 关系
```text
EVENT
│
↓
Notification Rule
│
↓
NOTIFICATION
│
┌───────────┴───────────┐
↓ ↓
RECIPIENT TEMPLATE
│ │
└───────────┬───────────┘
↓
MESSAGE
│
↓
DELIVERY PLANNER
│
↓
COMMUNICATION
RUNTIME
│
┌───────────┼───────────┐
↓ ↓ ↓
In-App Email Webhook
↓ ↓ ↓
Provider Provider Provider
│ │ │
└───────────┼───────────┘
↓
DELIVERY
│
┌───────────┴───────────┐
↓ ↓
EVENT OBSERVABILITY
```
---
# 214. DevOS 完整通信链
```text
User / Agent / Workflow / Plugin
│
↓
Action Runtime
│
↓
Event
│
↓
Notification Runtime
│
┌───────┼────────┐
↓ ↓ ↓
Policy Recipient Template
│ │ │
└───────┼────────┘
↓
Message
│
↓
Communication Runtime
│
Provider Router
│
┌───────┼────────┐
↓ ↓ ↓
Email Push Webhook
│ │ │
└───────┼────────┘
↓
Delivery
│
┌─────┴─────┐
↓ ↓
Event Metrics
↓ ↓
Realtime Observability
```
---
# 215. 最终 Golden Rules
## Golden Rule 1
> **Event 表示发生了什么,Notification 表示需要通知什么。**
## Golden Rule 2
> **Notification 不直接发送,Delivery 才代表一次实际发送。**
## Golden Rule 3
> **Channel 是通信方式,Provider 是通信实现。**
## Golden Rule 4
> **所有 Email / SMS / Push / Webhook / Chat 都必须进入统一 Communication Runtime。**
## Golden Rule 5
> **业务代码不能直接调用 SMTP、Twilio、SendGrid、FCM 等 Provider SDK。**
## Golden Rule 6
> **Provider Credential 永远通过 Credential / Secret Runtime。**
## Golden Rule 7
> **所有批量发送必须使用 Task → Job → Queue → Worker Runtime。**
## Golden Rule 8
> **Communication Runtime 不重新实现 Queue、Event、Security、Audit、Storage。**
## Golden Rule 9
> **Security / Consent / Scope 是发送前的硬性约束。**
## Golden Rule 10
> **Preference 决定用户偏好,但不能覆盖 Security Policy。**
## Golden Rule 11
> **所有 Delivery 必须支持状态、Attempt、Retry、Idempotency 和 Observability。**
## Golden Rule 12
> **Provider 可以替换,但 Notification API 不应该变化。**
---
# 216. 最终结论
DevOS 最终不应该出现:
```text
SEOEmailService
AgentEmailService
WorkflowEmailService
PluginEmailService
CRMEmailService
```
而应该只有:
```text
Notification Runtime
↓
Communication Runtime
↓
Provider Runtime
```
业务只需要说:
```text
“任务完成,请通知项目负责人。”
```
DevOS 自己负责:
```text
找谁
↓
是否允许通知
↓
用户喜欢什么渠道
↓
选择什么 Channel
↓
选择什么 Provider
↓
使用什么 Credential
↓
什么时候发送
↓
是否需要 Digest
↓
是否重复
↓
是否超过 Rate Limit
↓
是否超过 Budget
↓
发送
↓
失败 Retry
↓
Provider Failover
↓
记录 Delivery
↓
产生 Event
↓
Realtime / Audit / Metrics
```
最终形成:
```text
EVENT
↓
NOTIFICATION
↓
RECIPIENT + POLICY + TEMPLATE
↓
MESSAGE
↓
DELIVERY
↓
COMMUNICATION RUNTIME
↓
PROVIDER
↓
EXTERNAL CHANNEL
```
**最终 Golden Rule:**
> **业务系统只描述“通知什么”;Notification Runtime 决定“通知谁”;Communication Runtime 决定“怎么发送”;Provider 只负责“实际通信”。任何 Agent、Plugin、Workflow、MCP 或业务模块都不能创建第二套发送系统。**