@agentunion/fastaun-browser 0.5.4 → 0.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/CHANGELOG.md +177 -67
  2. package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/216/245/345/205/245/344/270/216/346/274/224/347/244/272/346/214/207/345/215/227.md +290 -0
  3. package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/234/215/345/212/241/346/236/266/346/236/204/344/270/216/350/257/246/347/273/206/345/256/236/347/216/260/350/256/241/345/210/222-codex.md +994 -0
  4. package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/234/215/345/212/241/350/277/220/347/273/264/344/270/216/345/217/221/345/270/203/346/214/207/345/215/227.md +144 -0
  5. package/_packed_docs/CHANGELOG.md +177 -67
  6. package/_packed_docs/INDEX.md +124 -65
  7. package/_packed_docs/KITE_DOCS_GUIDE.md +65 -30
  8. package/_packed_docs/agent.md/SCHEMA.md +83 -58
  9. package/_packed_docs/agent.md/examples/codeagent-claudecode.md +1 -1
  10. package/_packed_docs/agent.md/examples/openclaw-lobster.md +1 -1
  11. package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +1 -1
  12. package/_packed_docs/audit/AUN/346/234/215/345/212/241Go/345/214/226/351/207/215/346/236/204/347/262/276/347/273/206/345/214/226/346/272/220/347/240/201/345/256/241/346/237/245-20260718.md +366 -0
  13. package/_packed_docs/aun/345/205/254/347/275/221/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +234 -0
  14. package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1095 -0
  15. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1199 -0
  16. package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +6 -4
  17. package/_packed_docs/group-message-rpc-alignment-gaps.md +741 -0
  18. package/_packed_docs/message-online-push-alignment.md +572 -0
  19. package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -20
  20. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +219 -247
  21. package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +14 -14
  22. package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +3 -3
  23. package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +165 -421
  24. package/_packed_docs/protocol/README.md +1 -0
  25. package/_packed_docs/protocol/aun-docs-guide.md +7 -4
  26. package/_packed_docs/protocol/index.md +25 -19
  27. package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +63 -18
  28. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +22 -0
  29. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +93 -84
  30. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +6 -2
  31. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +73 -34
  32. package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +3 -3
  33. package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +21 -9
  34. package/_packed_docs/sdk/09-group-rpc-manual.md +319 -285
  35. package/_packed_docs/sdk/09-message-rpc-manual.md +144 -103
  36. package/_packed_docs/sdk/09-payload-reference.md +1 -1
  37. package/_packed_docs/sdk/09-storage-rpc-manual.md +14 -3
  38. package/_packed_docs/sdk/09-stream-rpc-manual.md +8 -8
  39. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +34 -23
  40. package/_packed_docs/sdk/CHANGELOG-0.5.6.md +73 -0
  41. package/_packed_docs/sdk/INDEX.md +45 -37
  42. package/_packed_docs/sdk/README.md +11 -9
  43. package/_packed_docs//345/217/221/345/270/203/346/212/245/345/221/212-0.5.6.md +260 -0
  44. package/_packed_docs//346/266/210/346/201/257/345/220/214/346/255/245/344/270/216/345/216/206/345/217/262/346/213/211/345/217/226/344/273/243/347/240/201/345/256/241/346/237/245/351/227/256/351/242/230/346/270/205/345/215/225.md +229 -0
  45. package/_packed_docs//346/266/210/346/201/257/345/220/214/346/255/245/344/270/216/345/216/206/345/217/262/346/213/211/345/217/226/346/224/271/351/200/240/346/226/271/346/241/210.md +750 -0
  46. package/dist/agent-md-schema.d.ts +14 -0
  47. package/dist/agent-md-schema.d.ts.map +1 -0
  48. package/dist/agent-md-schema.js +103 -0
  49. package/dist/agent-md-schema.js.map +1 -0
  50. package/dist/agent-md.d.ts +11 -5
  51. package/dist/agent-md.d.ts.map +1 -1
  52. package/dist/agent-md.js +295 -53
  53. package/dist/agent-md.js.map +1 -1
  54. package/dist/aid-store.d.ts +7 -7
  55. package/dist/aid-store.d.ts.map +1 -1
  56. package/dist/aid-store.js +46 -18
  57. package/dist/aid-store.js.map +1 -1
  58. package/dist/aid.d.ts +2 -0
  59. package/dist/aid.d.ts.map +1 -1
  60. package/dist/aid.js +29 -7
  61. package/dist/aid.js.map +1 -1
  62. package/dist/auth.d.ts.map +1 -1
  63. package/dist/auth.js +31 -11
  64. package/dist/auth.js.map +1 -1
  65. package/dist/bundle.js +29920 -19719
  66. package/dist/cert-utils.d.ts +1 -0
  67. package/dist/cert-utils.d.ts.map +1 -1
  68. package/dist/cert-utils.js +36 -16
  69. package/dist/cert-utils.js.map +1 -1
  70. package/dist/client/delivery.d.ts +106 -11
  71. package/dist/client/delivery.d.ts.map +1 -1
  72. package/dist/client/delivery.js +1925 -374
  73. package/dist/client/delivery.js.map +1 -1
  74. package/dist/client/group-state.d.ts.map +1 -1
  75. package/dist/client/group-state.js +27 -24
  76. package/dist/client/group-state.js.map +1 -1
  77. package/dist/client/lifecycle.d.ts +15 -1
  78. package/dist/client/lifecycle.d.ts.map +1 -1
  79. package/dist/client/lifecycle.js +477 -132
  80. package/dist/client/lifecycle.js.map +1 -1
  81. package/dist/client/mention-mode.d.ts +7 -0
  82. package/dist/client/mention-mode.d.ts.map +1 -0
  83. package/dist/client/mention-mode.js +184 -0
  84. package/dist/client/mention-mode.js.map +1 -0
  85. package/dist/client/peers.d.ts +1 -1
  86. package/dist/client/peers.d.ts.map +1 -1
  87. package/dist/client/peers.js +26 -3
  88. package/dist/client/peers.js.map +1 -1
  89. package/dist/client/rpc-pipeline.d.ts +34 -2
  90. package/dist/client/rpc-pipeline.d.ts.map +1 -1
  91. package/dist/client/rpc-pipeline.js +503 -99
  92. package/dist/client/rpc-pipeline.js.map +1 -1
  93. package/dist/client/runtime.d.ts +1 -3
  94. package/dist/client/runtime.d.ts.map +1 -1
  95. package/dist/client/runtime.js +4 -7
  96. package/dist/client/runtime.js.map +1 -1
  97. package/dist/client/v2-e2ee.d.ts +43 -2
  98. package/dist/client/v2-e2ee.d.ts.map +1 -1
  99. package/dist/client/v2-e2ee.js +931 -138
  100. package/dist/client/v2-e2ee.js.map +1 -1
  101. package/dist/client.d.ts +46 -15
  102. package/dist/client.d.ts.map +1 -1
  103. package/dist/client.js +785 -304
  104. package/dist/client.js.map +1 -1
  105. package/dist/errors.d.ts.map +1 -1
  106. package/dist/errors.js +4 -1
  107. package/dist/errors.js.map +1 -1
  108. package/dist/facades.d.ts +26 -1
  109. package/dist/facades.d.ts.map +1 -1
  110. package/dist/facades.js +142 -60
  111. package/dist/facades.js.map +1 -1
  112. package/dist/group-id.d.ts.map +1 -1
  113. package/dist/group-id.js +2 -17
  114. package/dist/group-id.js.map +1 -1
  115. package/dist/group-index.d.ts +6 -1
  116. package/dist/group-index.d.ts.map +1 -1
  117. package/dist/group-index.js +44 -25
  118. package/dist/group-index.js.map +1 -1
  119. package/dist/index.d.ts +5 -4
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +3 -2
  122. package/dist/index.js.map +1 -1
  123. package/dist/keystore/index.d.ts +10 -5
  124. package/dist/keystore/index.d.ts.map +1 -1
  125. package/dist/keystore/indexeddb-identity-store.d.ts +0 -12
  126. package/dist/keystore/indexeddb-identity-store.d.ts.map +1 -1
  127. package/dist/keystore/indexeddb-identity-store.js +0 -60
  128. package/dist/keystore/indexeddb-identity-store.js.map +1 -1
  129. package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
  130. package/dist/keystore/indexeddb-shared.js +9 -5
  131. package/dist/keystore/indexeddb-shared.js.map +1 -1
  132. package/dist/keystore/indexeddb-token-store.d.ts +3 -1
  133. package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
  134. package/dist/keystore/indexeddb-token-store.js +47 -2
  135. package/dist/keystore/indexeddb-token-store.js.map +1 -1
  136. package/dist/register-flow.d.ts.map +1 -1
  137. package/dist/register-flow.js +28 -3
  138. package/dist/register-flow.js.map +1 -1
  139. package/dist/seq-tracker.d.ts +28 -8
  140. package/dist/seq-tracker.d.ts.map +1 -1
  141. package/dist/seq-tracker.js +224 -61
  142. package/dist/seq-tracker.js.map +1 -1
  143. package/dist/storage/vfs.d.ts +1 -0
  144. package/dist/storage/vfs.d.ts.map +1 -1
  145. package/dist/storage/vfs.js +26 -2
  146. package/dist/storage/vfs.js.map +1 -1
  147. package/dist/tools/cross-sdk-agent.js +399 -11
  148. package/dist/tools/cross-sdk-agent.js.map +1 -1
  149. package/dist/transport.d.ts +12 -0
  150. package/dist/transport.d.ts.map +1 -1
  151. package/dist/transport.js +226 -102
  152. package/dist/transport.js.map +1 -1
  153. package/dist/v2/session/session.d.ts.map +1 -1
  154. package/dist/v2/session/session.js +3 -4
  155. package/dist/v2/session/session.js.map +1 -1
  156. package/dist/v2/state/commitment.d.ts.map +1 -1
  157. package/dist/v2/state/commitment.js +1 -2
  158. package/dist/v2/state/commitment.js.map +1 -1
  159. package/dist/validators.d.ts.map +1 -1
  160. package/dist/validators.js +8 -14
  161. package/dist/validators.js.map +1 -1
  162. package/dist/version.d.ts +1 -1
  163. package/dist/version.js +1 -1
  164. package/package.json +11 -9
  165. package/dist/group-resources.d.ts +0 -98
  166. package/dist/group-resources.d.ts.map +0 -1
  167. package/dist/group-resources.js +0 -635
  168. package/dist/group-resources.js.map +0 -1
  169. package/dist/keystore/indexeddb.d.ts +0 -179
  170. package/dist/keystore/indexeddb.d.ts.map +0 -1
  171. package/dist/keystore/indexeddb.js +0 -2031
  172. package/dist/keystore/indexeddb.js.map +0 -1
  173. package/dist/namespaces/auth.d.ts +0 -98
  174. package/dist/namespaces/auth.d.ts.map +0 -1
  175. package/dist/namespaces/auth.js +0 -992
  176. package/dist/namespaces/auth.js.map +0 -1
  177. package/dist/namespaces/custody.d.ts +0 -51
  178. package/dist/namespaces/custody.d.ts.map +0 -1
  179. package/dist/namespaces/custody.js +0 -302
  180. package/dist/namespaces/custody.js.map +0 -1
  181. package/dist/namespaces/meta.d.ts +0 -109
  182. package/dist/namespaces/meta.d.ts.map +0 -1
  183. package/dist/namespaces/meta.js +0 -549
  184. package/dist/namespaces/meta.js.map +0 -1
@@ -1,421 +1,165 @@
1
- # 15 - 离线推送通知协议 (Push Notification)
2
-
3
- ## 1. 概述
4
-
5
- 当目标 AID 的所有设备均离线时,AUN Gateway 通过事件通知将推送摘要发送给 `push_notify_aid`(推送代理 AID),由其完成最终的平台推送(APNs / FCM / WebPush 等)。
6
-
7
- **设计原则:**
8
-
9
- - push_notify_aid 是普通客户端 AID,不是 AUN 内部服务
10
- - 通过事件通知(非 P2P 消息)下发推送摘要——轻量、实时、不持久化
11
- - push_token 对 Gateway 完全不透明(opaque),push_notify_aid 自签自验
12
- - 任意一台设备在线即不触发推送
13
- - 推送内容仅含元数据,不含消息正文(E2EE 安全保证)
14
- - 背压控制:串行确认,Gateway 等 push_notify_aid ack 后再发下一批
15
- - 跨域推送:推送由**目标 AID 所属域**的 Gateway 触发,发送方域不参与
16
-
17
- ---
18
-
19
- ## 2. 架构
20
-
21
- ```mermaid
22
- graph TB
23
- Sender[发送方 AID] -->|message.send| GW[Gateway]
24
- GW -->|目标全部离线| PA[PushAggregator]
25
- PA -->|event/push.offline_message| GW
26
- GW -->|事件通知| PNA[push_notify_aid<br/>推送代理客户端]
27
- PNA -->|push.ack| GW
28
- PNA -->|平台推送| PLATFORM[APNs / FCM / WebPush]
29
- PLATFORM -->|通知| Target[目标终端]
30
-
31
- PNA -.->|connect Gateway 保持在线| GW
32
- ```
33
-
34
- **关键约束:**
35
-
36
- - push_notify_aid 作为普通客户端 AID 连接到 Gateway,通过事件通知接收推送摘要
37
- - push_notify_aid 离线时事件丢弃——推送是 best-effort,消息可靠性由 message.pull 保证
38
- - 目标 AID 有任意一台设备在线时,不触发推送
39
-
40
- ---
41
-
42
- ## 3. 推送注册流程
43
-
44
- ### 3.1 应用层:客户端向推送代理注册
45
-
46
- ```mermaid
47
- sequenceDiagram
48
- participant App as 应用客户端
49
- participant PNA as push_notify_aid
50
-
51
- Note over App,PNA: 应用层行为,AUN 协议不规定细节
52
- App->>PNA: 注册推送(aid, device_id, platform, device_token)
53
- PNA->>PNA: 生成 push_token(格式自定)
54
- PNA-->>App: push_token
55
- ```
56
-
57
- push_token 的格式、签名算法、有效期完全由 push_notify_aid 自行决定。AUN 协议不做任何约束。
58
-
59
- ### 3.2 协议层:connect 时携带推送配置
60
-
61
- ```mermaid
62
- sequenceDiagram
63
- participant C as Client
64
- participant GW as Gateway
65
-
66
- C->>GW: connect(aid, token, push_notify_aid, push_token)
67
- GW->>GW: 认证 AID 身份 ✓
68
- GW->>GW: 持久化 push_config
69
- GW-->>C: connected
70
- ```
71
-
72
- ---
73
-
74
- ## 4. 离线推送时序
75
-
76
- ```mermaid
77
- sequenceDiagram
78
- participant A as Sender AID
79
- participant GW as Gateway
80
- participant PA as PushAggregator
81
- participant PNA as push_notify_aid
82
-
83
- A->>GW: message.send(to=B, payload=...)
84
- GW->>GW: 持久化消息 + 查询 B 在线状态
85
-
86
- alt B 有任意设备在线
87
- GW->>GW: 投递到 B 的在线 session
88
- Note over GW: 不触发推送
89
- else B 全部设备离线
90
- GW->>PA: enqueue(target=B, from=A, msg_id, ts)
91
- PA->>PA: 聚合窗口 + 频控 + 背压检查
92
-
93
- alt 触发推送 且 in_flight < max
94
- PA->>GW: event/push.offline_message
95
- GW->>PNA: 事件通知(batch_id, summary, push_token)
96
- PA->>PA: in_flight++, 启动 ack_timeout
97
- PNA->>PNA: 验证 push_token ✓ → 发送平台推送
98
- PNA->>GW: push.ack(batch_id)
99
- GW->>PA: release(batch_id)
100
- PA->>PA: in_flight--
101
- else in_flight = max(背压)
102
- PA->>PA: 排队等待槽位释放
103
- else 频控抑制
104
- PA->>PA: 延迟到下一窗口
105
- end
106
- end
107
-
108
- GW-->>A: ack(msg_id, seq)
109
- ```
110
-
111
- ---
112
-
113
- ## 5. 背压与 in-flight 控制
114
-
115
- ```mermaid
116
- stateDiagram-v2
117
- [*] --> Idle: 初始状态
118
- Idle --> Sending: 有待推送 & in_flight < max
119
- Sending --> WaitAck: 事件已发出, in_flight++
120
- WaitAck --> Idle: 收到 push.ack, in_flight--
121
- WaitAck --> Idle: ack_timeout 超时, in_flight--
122
- WaitAck --> Queued: 新推送到达但 in_flight = max
123
- Queued --> Sending: 槽位释放
124
- ```
125
-
126
- ### 参数
127
-
128
- | 参数 | 默认值 | 说明 |
129
- |------|--------|------|
130
- | max_in_flight | 1 | 同一 push_notify_aid 未确认批次上限(串行) |
131
- | ack_timeout | 30s | 超时未 ack 自动释放槽位 |
132
- | batch_size | 50 | 每批最多聚合多少个 target_aid 的通知 |
133
-
134
- ### 行为规则
135
-
136
- - in_flight < max 发送事件,in_flight++
137
- - in_flight = max 排队等待
138
- - 收到 `push.ack(batch_id)` in_flight--,触发队列中下一批
139
- - 超时 → in_flight--,**不重试**(推送是 best-effort,过时推送是噪音)
140
- - push_notify_aid 离线 事件丢弃,in_flight 不增加
141
-
142
- ---
143
-
144
- ## 6. 在线判断规则
145
-
146
- ```mermaid
147
- flowchart TD
148
- A[消息到达,目标 AID = B] --> B{B 的在线设备数 > 0?}
149
- B -->|≥ 1 台在线| C[投递到在线 session,不推送]
150
- B -->|0 台在线| D{push_config 存在?}
151
- D -->|是| F[进入 PushAggregator]
152
- D -->|否| G[仅持久化,等对方上线 pull]
153
- F --> H[聚合 + 频控 + 背压 → 推送]
154
- ```
155
-
156
- **边界情况:**
157
-
158
- - 目标 AID 上线瞬间:清空该 AID 的聚合桶,取消待发推送
159
- - 最后一台设备断连:不立即触发推送,只有后续新消息到达时发现全离线才走推送路径
160
-
161
- ---
162
-
163
- ## 7. 跨域推送
164
-
165
- **核心原则:推送由目标 AID 所属域的 Gateway 触发。**
166
-
167
- 发送方域不感知目标域的 push_config 和白名单,也不需要任何跨域配置同步。
168
-
169
- ```mermaid
170
- sequenceDiagram
171
- participant A as alice.domain-a.com
172
- participant GW_A as Gateway A
173
- participant GW_B as Gateway B
174
- participant PA_B as PushAggregator B
175
- participant PNA as push.domain-b.com<br/>(连在 GW_B)
176
-
177
- A->>GW_A: message.send(to=bob.domain-b.com)
178
- GW_A->>GW_A: 持久化消息
179
- GW_A->>GW_B: 跨域 relay 消息
180
- GW_B->>GW_B: 查询 bob 本地在线状态
181
-
182
- alt bob 在本域有设备在线
183
- GW_B->>GW_B: 投递到 bob 的在线 session
184
- else bob 本域全部离线
185
- GW_B->>PA_B: enqueue(target=bob, from=alice.domain-a.com)
186
- PA_B->>GW_B: event/push.offline_message
187
- GW_B->>PNA: 事件通知
188
- PNA->>GW_B: push.ack
189
- end
190
-
191
- GW_B-->>GW_A: relay ack
192
- GW_A-->>A: ack
193
- ```
194
-
195
- **规则:**
196
-
197
- | 关注点 | 行为 |
198
- |--------|------|
199
- | 推送配置存储 | 仅存于目标 AID 所属域,不跨域同步 |
200
- | 白名单管理 | 各域独立配置 `allowed_notify_aids`,互不影响 |
201
- | push_notify_aid 必须连接位置 | 目标 AID 所属域的 Gateway |
202
- | push_notify_aid 跨域时 | 不支持。push_notify_aid 必须与其服务的 AID 同域 |
203
- | summary.senders 中的跨域 AID | 保留完整 AID(含域名),如 `alice.domain-a.com` |
204
-
205
- **约束:** push_notify_aid 必须与其服务的目标 AID 处于同一域。如果应用希望在多个域提供推送服务,需要在每个域部署独立的 push_notify_aid 并分别加入白名单。
206
-
207
- ---
208
-
209
- ## 8. 聚合与频控
210
-
211
- ### 8.1 PushAggregator 数据结构
212
-
213
- 每个离线目标 AID 一个聚合桶:
214
-
215
- ```
216
- bucket[target_aid] = {
217
- push_notify_aid: "push.myapp.com",
218
- push_token: "eyJhb...",
219
- pending: [{from, msg_id, ts}, ...],
220
- first_enqueue_ts: timestamp,
221
- last_push_ts: timestamp,
222
- }
223
- ```
224
-
225
- ### 8.2 去重规则
226
-
227
- 同一 target_aid 在频控窗口内只产生一次推送通知。具体行为:
228
-
229
- - 首条消息触发推送后,该 target_aid 进入频控冷却期(默认 60s)
230
- - 冷却期内新消息只更新聚合桶的 summary(unread_count++、senders 去重追加),不产生新推送
231
- - 冷却期结束时,若桶内有新增未推送内容,合并为一条推送发出
232
-
233
- 效果:无论短时间内收到多少条消息,target_aid 最多每 60s 收到一次推送通知,且 summary 是累积聚合的。
234
-
235
- ### 8.3 触发规则
236
-
237
- | 规则 | 说明 | 默认值 |
238
- |------|------|--------|
239
- | 首条即推 | 桶为空且不在冷却期时,第一条消息立即触发 | 开启 |
240
- | 窗口聚合 | 首条之后的消息等待窗口合并 | 5 秒 |
241
- | 数量上限 | 桶内积累 N 条立即触发(不等窗口) | 20 条 |
242
-
243
- ### 8.4 频控规则
244
-
245
- | 维度 | 限制 | 说明 |
246
- |------|------|------|
247
- | 同一 target_aid | 60 秒内最多 1 次推送 | 避免终端刷屏 |
248
- | 同一 push_notify_aid | 1000 次/分钟 | 保护推送代理服务 |
249
- | 全局 | 5000 次/分钟 | 系统保护 |
250
-
251
- 频控被触发时消息不丢弃,等窗口过后下一次聚合时一并推送。
252
-
253
- ---
254
-
255
- ## 9. 协议字段
256
-
257
- ### 9.1 connect 扩展字段
258
-
259
- ```json
260
- {
261
- "method": "auth.login",
262
- "params": {
263
- "aid": "bob.example.com",
264
- "challenge_response": "...",
265
- "push_notify_aid": "push.myapp.com",
266
- "push_token": "eyJhbGciOiJIUzI1NiJ9..."
267
- }
268
- }
269
- ```
270
-
271
- - `push_notify_aid` 和 `push_token` 均为可选字段
272
- - 两者必须同时提供或同时不提供
273
- - 不提供 = 不需要离线推送
274
- - 每次 connect 覆盖写(最新连接为准)
275
-
276
- ### 9.2 事件通知格式
277
-
278
- Gateway 向 push_notify_aid 下发的事件通知:
279
-
280
- ```json
281
- {
282
- "method": "event/push.offline_message",
283
- "params": {
284
- "batch_id": "uuid-xxx",
285
- "items": [
286
- {
287
- "target_aid": "bob.example.com",
288
- "push_token": "eyJhbGciOiJIUzI1NiJ9...",
289
- "summary": {
290
- "unread_count": 3,
291
- "senders": ["alice.example.com", "charlie.example.com"],
292
- "latest_ts": 1716100005,
293
- "group_ids": ["g-abc123.agentid.pub"]
294
- }
295
- }
296
- ]
297
- }
298
- }
299
- ```
300
-
301
- **安全约束:** 不包含消息正文。E2EE 场景下 Gateway 无法解密,推送代理只需知道"有 N 条未读来自谁"即可构造推送文案。
302
-
303
- ### 9.3 push.ack RPC
304
-
305
- push_notify_aid 处理完一批推送后回调确认:
306
-
307
- ```json
308
- {
309
- "method": "push.ack",
310
- "params": {
311
- "batch_id": "uuid-xxx"
312
- }
313
- }
314
- ```
315
-
316
- Gateway 收到后释放 in-flight 槽位,触发下一批。
317
-
318
- ### 9.4 push.update_config RPC(可选)
319
-
320
- 允许客户端在不重连的情况下更新推送配置:
321
-
322
- ```json
323
- {
324
- "method": "push.update_config",
325
- "params": {
326
- "push_notify_aid": "push.myapp.com",
327
- "push_token": "new-token..."
328
- }
329
- }
330
- ```
331
-
332
- ---
333
-
334
- ## 10. push_token 鉴权模型
335
-
336
- ### 10.1 push_notify_aid 白名单
337
-
338
- Gateway 配置允许的 push_notify_aid 白名单,只有白名单内的 AID 才能被设置为推送代理:
339
-
340
- - 客户端 connect 时携带的 `push_notify_aid` 不在白名单内 → 忽略该字段,不报错,不存储
341
- - 白名单为空 → 禁用推送功能
342
- - 白名单配置在 Gateway 启动配置中,运行时不可动态修改
343
-
344
- ```json
345
- {
346
- "push": {
347
- "allowed_notify_aids": [
348
- "push.myapp.com",
349
- "push.partner.com"
350
- ]
351
- }
352
- }
353
- ```
354
-
355
- ### 10.2 token 透传模型
356
-
357
- ```mermaid
358
- sequenceDiagram
359
- participant PNA as push_notify_aid
360
- participant GW as Gateway
361
-
362
- Note over PNA,GW: push_token 生命周期
363
- PNA->>PNA: 签发 push_token(格式/算法自定)
364
- Note over GW: Gateway 存储 push_token(opaque bytes)
365
- Note over GW: 不验签、不解析、不判断过期
366
- GW->>PNA: event/push.offline_message(..., push_token="xxx")
367
- PNA->>PNA: 自己验签 push_token
368
- alt token 有效
369
- PNA->>PNA: 执行推送
370
- PNA->>GW: push.ack(batch_id)
371
- else token 无效/过期
372
- PNA->>PNA: 丢弃
373
- PNA->>GW: push.ack(batch_id)
374
- Note over PNA: 客户端下次 connect 带新 token
375
- end
376
- ```
377
-
378
- **职责划分:**
379
-
380
- | 角色 | 职责 |
381
- |------|------|
382
- | push_notify_aid | 签发 token、验证 token、决定格式和有效期、处理后 ack |
383
- | Gateway | 存储 token、透传 token、不解析不验证、管理 in-flight |
384
- | Client | 向 push_notify_aid 申请 token、connect 时携带 |
385
-
386
- ---
387
-
388
- ## 11. 持久化
389
-
390
- ### push_config 表
391
-
392
- ```sql
393
- CREATE TABLE push_config (
394
- aid VARCHAR(255) PRIMARY KEY,
395
- push_notify_aid VARCHAR(255) NOT NULL,
396
- push_token TEXT NOT NULL,
397
- updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
398
- );
399
- ```
400
-
401
- - 随 connect 写入/更新(UPSERT)
402
- - 可加内存缓存(TTL 5 分钟)
403
-
404
- ---
405
-
406
- ## 12. 边界情况
407
-
408
- | 场景 | 处理 |
409
- |------|------|
410
- | push_notify_aid 离线 | 事件丢弃,不持久化。推送是 best-effort,消息可靠性由 pull 保证 |
411
- | 目标 AID 未配置推送 | 不推送,消息正常持久化等对方上线 pull |
412
- | 目标 AID 上线瞬间 | 清空聚合桶,取消待发推送 |
413
- | E2EE 消息 | 推送内容只含元数据(发送者、数量),不含密文 |
414
- | 群组消息 | 群内每个离线成员独立聚合,summary 含 group_ids |
415
- | push_token 过期 | push_notify_aid 丢弃但仍 ack,客户端下次 connect 刷新 token |
416
- | ack 超时 | 释放槽位,不重试。后续新消息触发新批次时会包含累积通知 |
417
- | 同一 AID 多设备不同推送配置 | 以最后一次 connect 为准(单条记录覆盖) |
418
- | 跨域消息推送 | 由目标 AID 所属域的 Gateway 触发,发送方域不参与 |
419
- | push_notify_aid 跨域 | 不支持,必须与目标 AID 同域 |
420
-
421
-
1
+ # 15 - 离线推送通知协议(Push Notification
2
+
3
+ ## 1. 目标与权威依据
4
+
5
+ 当可靠消息的目标安装没有 AUN 长连接时,Push Service 向该安装登记的 Push Server 发送不含消息正文的唤醒事件。终端收到外部平台通知后重新连接,并通过原有 `message.pull` / `group.pull` 获取真实消息。
6
+
7
+ 本章描述对外协议。冲突时按以下顺序解释:
8
+
9
+ 1. `docs/superpowers/契约冻结-v3-to-v4.md`
10
+ 2. `docs/superpowers/specs/2026-07-24-push-service-design-v3.md`
11
+ 3. 本文档
12
+
13
+ V1 使用独立 Go Push Service、单可用 Gateway、单 Push Service 实例和批次级 ACK。`push.offline_message` 不经 federation 转发;明文 token 仅允许隔离 PoC。
14
+
15
+ ## 2. 术语与职责
16
+
17
+ | 名称 | 含义 |
18
+ | --- | --- |
19
+ | `push_notify_aid` | 应用和 SDK 使用的推送代理 AID 名称 |
20
+ | `push_server_aid` | `push.register` 线上 RPC 的冻结字段;与 `push_notify_aid` 指向同一角色 |
21
+ | Push Server | 普通 AUN 客户端,验证 opaque token、调用 APNs/FCM/WebPush,并按 delivery 幂等处理 |
22
+ | Push Service | 保存 registration、candidate、delivery、batch 和频控状态,负责调度、投递、ACK、重试与恢复 |
23
+ | Gateway | 注入可信身份、路由 `push.*`、查询长连接 Session、定向投递事件;不保存 registration、不解析 token |
24
+
25
+ Message/Group 只在消息形成可靠事实后异步提交候选。推送失败不得反向改变消息发送成功语义。
26
+
27
+ ## 3. 安装登记与注销
28
+
29
+ ### 3.1 Python SDK 推荐入口
30
+
31
+ 应用启动时在 `connect()` 中携带 `push_notify_aid` `push_token`:
32
+
33
+ ```python
34
+ await client.connect({
35
+ "push_notify_aid": "push.example.com",
36
+ "push_token": token,
37
+ })
38
+ ```
39
+
40
+ 这是 SDK 便利语义,不是 `auth.connect` 协议扩展。Python SDK 先建立 AUN 会话,再把 `push_notify_aid` 映射为 `push_server_aid` 调用 `push.register`;字段不会进入认证握手,也不会保存在可公开读取的 session options 中。登记失败时本次 `connect()` 回滚并抛错。
41
+
42
+ 本轮只修改 Python SDK。Go、TypeScript、JavaScript 尚无专用 Push facade 或 connect 自动登记。
43
+
44
+ ### 3.2 运行期变更
45
+
46
+ 应用无需断开连接即可更新或注销当前安装:
47
+
48
+ ```python
49
+ await client.push.register(push_notify_aid="push.example.com", push_token=new_token)
50
+ await client.push.unregister()
51
+ ```
52
+
53
+ `register()` 可附带 `provider`、`app_id` 诊断字段。`unregister()` 幂等禁用当前 `(aid, device_id, slot_id)`,不删除历史 delivery。
54
+
55
+ ### 3.3 `push.register`
56
+
57
+ | 项目 | 契约 |
58
+ | --- | --- |
59
+ | 请求 | `push_server_aid`、`push_token`;可选 `provider`、`app_id` |
60
+ | 可信安装 | 只取 Gateway 注入的 `_auth.aid/device_id/slot_id` |
61
+ | 成功结果 | `registration_id`、`registration_version` |
62
+ | 更新语义 | 同一安装 UPSERT,version 递增并重新启用 |
63
+ | 校验 | Push Server 白名单、同域约束、字段类型和 token 长度 |
64
+
65
+ 请求体不得自报或覆盖 AID、device、slot、connection ID 等可信身份字段。
66
+
67
+ ### 3.4 `push.unregister`
68
+
69
+ 请求无业务参数。Push Service 根据 `_auth.aid/device_id/slot_id` 禁用当前安装;已禁用或不存在仍返回幂等成功 `status=disabled`。
70
+
71
+ ## 4. 主链路
72
+
73
+ 1. 终端登记当前安装的 Push Server 和 opaque token。
74
+ 2. Message/Group 在消息持久化成功后异步调用 `push.enqueue`。
75
+ 3. Push Service 等待离线宽限期,再调用 `gateway.query_sessions(long_only=true)` 复核目标 AID。
76
+ 4. 任一目标长连接在线时抑制候选;查询错误、超时或非法响应视为“未知”,不得推断离线。
77
+ 5. 确认离线后,Push Service 为每条有效 installation registration 生成稳定 delivery。
78
+ 6. Scheduler Push Server、目标、公平性、频控、batch 数量和事件字节上限构建批次。
79
+ 7. Push Service 选择 Push Server 最早建立的确定长连接,定向投递 `push.offline_message`。
80
+ 8. Push Server 按 `delivery_id` 幂等执行平台推送,并用 `push.ack` 返回批次结果。
81
+
82
+ 短连接不抑制离线推送,也不能承载 `push.offline_message`。
83
+
84
+ ## 5. 候选与可靠性边界
85
+
86
+ `push.enqueue` 仅允许 Gateway 注入 `_caller_id=message` 或 `group`。候选 ID 由版本、kind、消息标识、目标 AID 和可选 group ID 规范化后计算 SHA-256。
87
+
88
+ - 数据库提交成功后才能返回 `accepted`。
89
+ - 相同 candidate ID 和相同不可变内容返回 `duplicate`。
90
+ - 相同 ID 但内容冲突必须返回冲突错误。
91
+ - 生产者临时调用失败时保留同一队列项并退避,直到 accepted、duplicate TTL 到期。
92
+ - 队列满、进程在确认前崩溃或 TTL 到期允许丢失唤醒提示,但必须记录指标和诊断;真实消息仍可 pull。
93
+
94
+ ## 6. `push.offline_message`
95
+
96
+ 事件名为 `push.offline_message`,一个 batch 只属于一个 Push Server,并固定定向到一个长连接 `connection_id`。`federation_forward=false`。
97
+
98
+ 批次字段:
99
+
100
+ | 字段 | 说明 |
101
+ | --- | --- |
102
+ | `protocol_version` | V1 固定为字符串 `1` |
103
+ | `batch_id` | 64 位十六进制稳定标识 |
104
+ | `expires_at_ms` | 批次最早过期时间 |
105
+ | `items` | 1 到配置上限条 installation delivery |
106
+
107
+ item 字段:
108
+
109
+ | 字段 | 说明 |
110
+ | --- | --- |
111
+ | `delivery_id` | Push Server 幂等键;重试期间保持不变 |
112
+ | `target_aid` | 需要唤醒的目标 AID |
113
+ | `device_id` / `slot_id` | 目标安装身份 |
114
+ | `push_token` | Push Server 自签自验的 opaque token |
115
+ | `category` | 候选类型,如 `message` 或 `group` |
116
+ | `new_count` | 本批新增提示计数 |
117
+ | `latest_at_ms` | 最新候选发生时间 |
118
+
119
+ 事件不得包含消息正文、E2EE 密文、发送者隐私数据、证书私钥或其他身份材料。
120
+
121
+ ## 7. Push Server 处理规则
122
+
123
+ - 必须先校验协议版本、batch 过期时间和 item 结构。
124
+ - 必须验证自己的 opaque token;Gateway 和 Push Service 不解析 token 业务内容。
125
+ - 必须按 `delivery_id` 幂等。重复事件不得重复产生不可逆平台副作用,但仍需重新 ACK。
126
+ - 普通终端不订阅该事件;只有承担 Push Server 角色的客户端处理。
127
+
128
+ Python Mock Push Server 使用修改后的 Python SDK 接收事件和调用 `client.push.ack()`,仅用于隔离测试,不代表生产 APNs/FCM 适配实现。
129
+
130
+ ## 8. `push.ack`
131
+
132
+ 请求字段为 `batch_id` 和批次级 `status`。V1 只允许:
133
+
134
+ | status | 结果 |
135
+ | --- | --- |
136
+ | `accepted` | 批次内 delivery 进入 accepted |
137
+ | `retryable_failure` | 未超重试上限的 delivery 回到 pending 并退避 |
138
+ | `permanent_failure` | 批次内 delivery 进入 permanent_failed |
139
+
140
+ 成功响应的 `status` `applied`、`duplicate` `stale`。ACK 只信任 `_auth.aid`,必须与 batch owner 一致;它只能影响创建 batch 时冻结的 membership。
141
+
142
+ ACK timeout、响应丢失、dispatch 结果未知和进程重启都由持久状态机恢复。V1 不提供逐 delivery ACK。
143
+
144
+ ## 9. 在线判断、聚合与容量
145
+
146
+ - 在线复核只看 `long_only=true` 的 Session。
147
+ - Push Server 多长连接时,按 `(created_at_ms ASC, connection_id ASC)` 选择第一个。
148
+ - registration TTL、candidate TTL、离线宽限、聚合窗口、目标 cooldown、Push Server/全局频控、batch 数量、事件字节上限和每 Server 最大并行 batch 均是运行约束。
149
+ - 数据库是恢复真源;内存只能缓存热状态,不能单独决定 timeout、重试或恢复。
150
+ - 同一 Push Server 和不同 Push Server 之间都必须避免长期饥饿。
151
+
152
+ ## 10. 安全、域与发布边界
153
+
154
+ - Push Server 必须在所属域的允许列表中,且与目标 registration 同域。
155
+ - token 只允许记录不可逆短指纹,不得出现在日志、指标、错误或诊断响应中。
156
+ - 生产环境必须使用可信 token 加密和密钥管理;当前明文模式只能用于隔离 PoC。
157
+ - `push.offline_message` V1 不跨 federation;跨域 E2E 尚未作为完成项验收。
158
+ - 测试不得创建、删除、清空或重建既有 AID 身份、数据库和固定 Push Server 材料。
159
+
160
+ ## 11. 实现状态
161
+
162
+ - Push Service、Gateway 路由、Message/Group 候选链和 Python SDK/Mock Push Server 已按冻结契约实现。
163
+ - Python SDK 提供 `connect()` 自动登记和 `client.push.register/unregister/ack`。
164
+ - Go、TypeScript、JavaScript SDK 本轮未修改;文档不得宣称其已有专用 Push facade。
165
+ - 生产发布仍受 token 加密硬门阻断;运行和回滚要求见 `docs/AUN离线推送服务运维与发布指南.md`。
@@ -42,6 +42,7 @@ AUN 是 ACP 协议的 2.0 版本,采用 WebSocket + JSON-RPC 2.0 定义 Agent
42
42
  | [08-AUN-E2EE.md](08-AUN-E2EE.md) | Legacy P2P E2EE 信封说明;当前默认主路径见 SDK V2 多设备 wrap 文档 |
43
43
  | [08-AUN-E2EE-Group.md](08-AUN-E2EE-Group.md) | 群组 E2EE V2:消息级密钥、逐设备密钥包裹、成员状态签名验证 |
44
44
  | [10-Group-子协议.md](10-Group-子协议.md) | `group.*` 群组管理、群消息、`group.index` 签名索引、`_meta.group_indexes` 和 CAS 更新 |
45
+ | [13-Agent行为规范.md](13-Agent行为规范.md) | Agent 自主模式、收发方响应义务、群 `mention_mode` 与 channel 过滤边界 |
45
46
  | [16-系统目录保护方案.md](16-系统目录保护方案.md) | `memberdata` 与 `group_data` 的系统目录保护、`group_data` 目录树隐藏与读下载/写保护边界、Group FS 授权路径和配额归属 |
46
47
 
47
48
  ### 附录
@@ -18,10 +18,12 @@ AUN 协议采用**主协议 + 子协议**架构:
18
18
  ├── 04-Peer-子协议.md ← peer.* 对等认证
19
19
  └── 05-Relay-子协议.md ← relay.* 中继传输
20
20
 
21
- 业务层与公共基础
22
- ├── 06-服务协议.md ← message/meta/search/task + 跨域消息路由
23
- ├── 07-错误码与状态机.md ← 错误码汇总、状态机
24
- └── 08-AUN-E2EE.md ← Legacy P2P E2EE 信封;当前主路径见 SDK E2EE V2 文档
21
+ 业务层与公共基础
22
+ ├── 06-服务协议.md ← message/meta/search/task + 跨域消息路由
23
+ ├── 07-错误码与状态机.md ← 错误码汇总、状态机
24
+ ├── 08-AUN-E2EE.md ← Legacy P2P E2EE 信封;当前主路径见 SDK E2EE V2 文档
25
+ ├── 10-Group-子协议.md ← 群组协议与 mention_mode
26
+ └── 13-Agent行为规范.md ← Agent 自主模式与 channel 过滤边界
25
27
  ```
26
28
 
27
29
  ## 渐进式查阅流程
@@ -43,6 +45,7 @@ AUN 协议采用**主协议 + 子协议**架构:
43
45
  | Relay 中继 | 05-Relay-子协议.md |
44
46
  | 消息收发、搜索、任务 | 06-服务协议.md |
45
47
  | 群组、group.index 签名索引和 CAS | 10-Group-子协议.md |
48
+ | 群提及过滤 mention_mode、Agent 自主行为与响应义务 | 10-Group-子协议.md、13-Agent行为规范.md |
46
49
  | 错误码和状态机 | 07-错误码与状态机.md |
47
50
  | E2EE 加密 | ../sdk/E2EE_V2消息通信时序图.md / 08-AUN-E2EE-Group.md;旧信封查 08-AUN-E2EE.md |
48
51
  | 安全威胁和防护 | 09-安全考虑.md |