- 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)
4933 lines
51 KiB
Markdown
4933 lines
51 KiB
Markdown
# 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 或业务模块都不能创建第二套发送系统。** |