@agentunion/fastaun 0.5.33 → 0.5.34

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 (89) hide show
  1. package/CHANGELOG.md +30 -2
  2. package/README.md +28 -26
  3. package/_packed_docs/CHANGELOG.md +30 -2
  4. package/_packed_docs/INDEX.md +17 -3
  5. package/_packed_docs/KITE_DOCS_GUIDE.md +10 -4
  6. package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +58 -8
  7. package/_packed_docs/sdk/0.5.33-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +464 -316
  8. package/_packed_docs/sdk/0.5.33-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +499 -304
  9. package/_packed_docs/sdk/0.5.34-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +133 -0
  10. package/_packed_docs/sdk/0.5.34-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +107 -0
  11. package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +16 -13
  12. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +13 -1
  13. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +17 -7
  14. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +55 -14
  15. package/_packed_docs/sdk/09-collab-rpc-manual.md +48 -30
  16. package/_packed_docs/sdk/09-custody-api-manual.md +3 -3
  17. package/_packed_docs/sdk/09-group-rpc-manual.md +53 -6
  18. package/_packed_docs/sdk/09-message-rpc-manual.md +22 -0
  19. package/_packed_docs/sdk/09-meta-rpc-manual.md +2 -1
  20. package/_packed_docs/sdk/09-payload-reference.md +9 -8
  21. package/_packed_docs/sdk/09-proxy-rpc-manual.md +20 -14
  22. package/_packed_docs/sdk/09-storage-rpc-manual.md +1698 -1659
  23. package/_packed_docs/sdk/09-stream-rpc-manual.md +33 -20
  24. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +11 -9
  25. package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +53 -28
  26. package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/274/200/345/217/221/347/247/273/346/244/215/346/214/207/345/215/227.md +62 -28
  27. package/_packed_docs/sdk/INDEX.md +21 -9
  28. package/_packed_docs/sdk/README.md +11 -6
  29. package/dist/auth.js +8 -2
  30. package/dist/auth.js.map +1 -1
  31. package/dist/client/control-messages.js +2 -2
  32. package/dist/client/control-messages.js.map +1 -1
  33. package/dist/client/delivery.d.ts +5 -0
  34. package/dist/client/delivery.js +146 -32
  35. package/dist/client/delivery.js.map +1 -1
  36. package/dist/client/lifecycle.js +3 -0
  37. package/dist/client/lifecycle.js.map +1 -1
  38. package/dist/client/rpc-budget.d.ts +21 -0
  39. package/dist/client/rpc-budget.js +82 -0
  40. package/dist/client/rpc-budget.js.map +1 -0
  41. package/dist/client/rpc-pipeline.d.ts +3 -0
  42. package/dist/client/rpc-pipeline.js +166 -60
  43. package/dist/client/rpc-pipeline.js.map +1 -1
  44. package/dist/client/sync-channels.d.ts +89 -0
  45. package/dist/client/sync-channels.js +489 -0
  46. package/dist/client/sync-channels.js.map +1 -0
  47. package/dist/client/v2-e2ee.d.ts +4 -1
  48. package/dist/client/v2-e2ee.js +401 -298
  49. package/dist/client/v2-e2ee.js.map +1 -1
  50. package/dist/client.d.ts +2 -0
  51. package/dist/client.js +63 -1
  52. package/dist/client.js.map +1 -1
  53. package/dist/index.d.ts +1 -1
  54. package/dist/index.js.map +1 -1
  55. package/dist/pubsub/binding.js +14 -1
  56. package/dist/pubsub/binding.js.map +1 -1
  57. package/dist/pubsub/channel.d.ts +4 -0
  58. package/dist/pubsub/channel.js +26 -0
  59. package/dist/pubsub/channel.js.map +1 -1
  60. package/dist/pubsub/client.d.ts +9 -0
  61. package/dist/pubsub/client.js +154 -31
  62. package/dist/pubsub/client.js.map +1 -1
  63. package/dist/pubsub/credentials.d.ts +3 -0
  64. package/dist/pubsub/credentials.js +57 -20
  65. package/dist/pubsub/credentials.js.map +1 -1
  66. package/dist/pubsub/index.d.ts +3 -0
  67. package/dist/pubsub/index.js +69 -53
  68. package/dist/pubsub/index.js.map +1 -1
  69. package/dist/pubsub/service.d.ts +3 -0
  70. package/dist/pubsub/service.js +167 -12
  71. package/dist/pubsub/service.js.map +1 -1
  72. package/dist/pubsub/types.d.ts +2 -0
  73. package/dist/storage/lowlevel.d.ts +3 -1
  74. package/dist/storage/lowlevel.js +13 -0
  75. package/dist/storage/lowlevel.js.map +1 -1
  76. package/dist/storage/types.d.ts +10 -0
  77. package/dist/storage/types.js.map +1 -1
  78. package/dist/storage/vfs.d.ts +3 -1
  79. package/dist/storage/vfs.js +2 -2
  80. package/dist/storage/vfs.js.map +1 -1
  81. package/dist/tools/cross-sdk-agent.d.ts +55 -5
  82. package/dist/tools/cross-sdk-agent.js +88 -21
  83. package/dist/tools/cross-sdk-agent.js.map +1 -1
  84. package/dist/transport.d.ts +12 -0
  85. package/dist/transport.js +91 -6
  86. package/dist/transport.js.map +1 -1
  87. package/dist/version.d.ts +1 -1
  88. package/dist/version.js +1 -1
  89. package/package.json +1 -1
@@ -19,6 +19,8 @@
19
19
  | `/pull/{stream_id}` | HTTP SSE | 拉流。推荐使用 `Authorization: Bearer {pull_token}`,可跨域 |
20
20
  | `/health` | HTTP GET | 健康检查 |
21
21
 
22
+ 四 SDK 均通过控制面 facade 封装上述 RPC:Python 使用 `client.stream.create/close/get_info/list_active`,TypeScript 与 Browser JS 使用 `client.stream.create/close/getInfo/listActive`,Go 使用 `client.Stream().Create/Close/GetInfo/ListActive(ctx, params)`。WS 推流和 SSE 拉流仍需按下文数据面端点自行连接。
23
+
22
24
  ---
23
25
 
24
26
  ## stream.create
@@ -31,7 +33,7 @@
31
33
  |------|------|------|------|
32
34
  | `content_type` | string | 否 | 内容类型,默认 `"text/plain"`。常用值:`text/plain`(文本流)、`application/json-stream`(JSON 对象流)、`text/event-stream`(SSE 风格事件流) |
33
35
  | `metadata` | object | 否 | 自定义元数据,如 `{"model": "gpt-4", "task_id": "xxx"}` |
34
- | `target_aid` | string | 否 | 绑定拉流方 AID。当前实现中,只有拉流方显式提供 `aid` 时才会做该匹配校验 |
36
+ | `target_aid` | string | 否 | 绑定拉流方 AID。指定后,拉流请求必须通过 `X-Stream-AID` 提供完全匹配的 AID,否则返回 403 |
35
37
 
36
38
  ### 响应
37
39
 
@@ -43,7 +45,7 @@
43
45
  | `push_token` | string | 推流凭证 |
44
46
  | `pull_token` | string | 拉流凭证,便于通过 message.send 单独传递 |
45
47
  | `push_headers` | object | 推流 Authorization header(`{"Authorization": "Bearer {push_token}"}`) |
46
- | `pull_headers` | object | 拉流 Authorization header(`{"Authorization": "Bearer {pull_token}"}`) |
48
+ | `pull_headers` | object | 拉流 Authorization header;设置 `target_aid` 时还包含 `X-Stream-AID` |
47
49
 
48
50
  ### 调用示例
49
51
 
@@ -59,7 +61,7 @@ result = await client.call("stream.create", {
59
61
  # "push_token": "ec80...",
60
62
  # "pull_token": "c438953be0ca887b...",
61
63
  # "push_headers": {"Authorization": "Bearer ec80..."},
62
- # "pull_headers": {"Authorization": "Bearer c438..."}
64
+ # "pull_headers": {"Authorization": "Bearer c438...", "X-Stream-AID": "target.aid.com"}
63
65
  # }
64
66
  ```
65
67
 
@@ -67,9 +69,15 @@ result = await client.call("stream.create", {
67
69
 
68
70
  ### 错误
69
71
 
72
+ `content_type` 必须是非空字符串,包含 `/` 且不超过 255 bytes;`metadata` 必须是对象,UTF-8 JSON 编码后不超过 4096 bytes。
73
+ `target_aid` 如提供必须是非空且合法的 AID;服务端会将其写入返回的 `pull_headers`。
74
+
70
75
  | code | message | 原因 |
71
76
  |------|---------|------|
72
- | -33402 | Stream limit exceeded | 活跃流数超过服务配置上限 |
77
+ | -33402 | Stream limit exceeded | 活跃流数或关闭通知积压超过服务配置上限 |
78
+ | -33405 | Stream invalid params | `content_type`、`metadata` 或 `target_aid` 参数无效 |
79
+ | -33407 | Stream internal error | 外部地址不可用或服务内部错误 |
80
+ | -32020 | Service stopping | 服务正在停止,暂不接受新流 |
73
81
 
74
82
  ---
75
83
 
@@ -108,7 +116,7 @@ await client.call("stream.close", {"stream_id": "4d5067f203cf42ba"})
108
116
 
109
117
  ## stream.get_info
110
118
 
111
- 获取流的状态和统计信息。仅流的创建者或 `target_aid` 可调用。
119
+ 获取流的状态和统计信息。仅流的创建者或绑定的 `target_aid` 可调用;控制面通过已认证的调用方 AID 判定权限。
112
120
 
113
121
  ### 参数
114
122
 
@@ -169,7 +177,7 @@ for s in result["streams"]:
169
177
 
170
178
  ## 数据面:推流 WebSocket
171
179
 
172
- 连接 `stream.create` 返回的 `push_url`,通过 WebSocket 发送 JSON 帧。使用 `Authorization: Bearer` 或 `X-Stream-Token` 请求头传递 token;query string 不接受凭据。
180
+ 连接 `stream.create` 返回的 `push_url`,通过 WebSocket 发送 JSON 帧。使用返回的 `push_headers`(或 `Authorization: Bearer` / `X-Stream-Token` 请求头)传递 token;query string 不接受凭据。
173
181
 
174
182
  ### 帧格式
175
183
 
@@ -181,8 +189,8 @@ for s in result["streams"]:
181
189
  | 字段 | 类型 | 必填 | 说明 |
182
190
  |------|------|------|------|
183
191
  | `cmd` | string | 是 | 固定 `"data"` |
184
- | `data` | string | 是 | 数据内容,无大小限制(WS 帧上限 64MB) |
185
- | `seq` | integer | 否 | 序列号,不提供则服务端自增 |
192
+ | `data` | string | 是 | 数据内容;完整 WebSocket 消息最大 64 MiB,单条数据还必须不超过历史缓冲配置及运行时内存预算 |
193
+ | `seq` | integer | 否 | 正整数序列号,不提供则服务端自增;低于或等于当前序号的帧会被忽略 |
186
194
 
187
195
  **关闭帧**:
188
196
  ```json
@@ -194,7 +202,7 @@ for s in result["streams"]:
194
202
  ```python
195
203
  import websockets, json
196
204
 
197
- async with websockets.connect(push_url, ssl=ssl_ctx) as ws:
205
+ async with websockets.connect(push_url, additional_headers=push_headers, ssl=ssl_ctx) as ws:
198
206
  for i, token in enumerate(llm_tokens, 1):
199
207
  await ws.send(json.dumps({"cmd": "data", "data": token, "seq": i}))
200
208
  await ws.send(json.dumps({"cmd": "close"}))
@@ -202,7 +210,7 @@ async with websockets.connect(push_url, ssl=ssl_ctx) as ws:
202
210
 
203
211
  ### 断线重连
204
212
 
205
- WebSocket 断开后,服务端保留流状态最多 120 秒。重连后继续从断点 seq 推送即可。
213
+ WebSocket 推流端离线后,默认 120 秒内可恢复(该超时可配置);流关闭后默认保留 60 秒,保留与清理策略均可配置。重连后继续从断点 seq 推送即可。
206
214
 
207
215
  ---
208
216
 
@@ -210,7 +218,7 @@ WebSocket 断开后,服务端保留流状态最多 120 秒。重连后继续
210
218
 
211
219
  连接 `stream.create` 返回的 `pull_url`,接收标准 SSE 流。
212
220
 
213
- 使用 `Authorization: Bearer` 或 `X-Stream-Token` 请求头传递 pull token;若提供拉流方 AID,使用 `X-Stream-AID` 请求头;query 参数不接受凭据或身份。
221
+ 使用 `Authorization: Bearer` 或 `X-Stream-Token` 请求头传递 pull token;指定 `target_aid` 时必须使用 `X-Stream-AID` 请求头提供匹配 AID;query 参数不接受凭据或身份。
214
222
 
215
223
  ### SSE 格式
216
224
 
@@ -235,8 +243,7 @@ data: {}
235
243
  - 客户端重连时可携带 `Last-Event-ID`
236
244
  - 服务端会跳过 `seq <= Last-Event-ID` 的缓冲数据,再继续实时推送
237
245
 
238
- 注意:这只覆盖仍保留在当前流内存缓冲中的历史数据,不是持久化重放。
239
- 如果请求的 seq 早于当前内存缓冲最小值,服务端不会返回显式 gap 错误,而是从仍保留的最早帧继续推送。
246
+ 注意:这只覆盖仍保留在当前流内存缓冲中的历史数据,不是持久化重放。`Last-Event-ID` 必须是非负整数;格式无效或为负数返回 400,超出当前序号或已早于保留窗口返回 416。
240
247
 
241
248
  ### 完整示例
242
249
 
@@ -244,7 +251,7 @@ data: {}
244
251
  import aiohttp
245
252
 
246
253
  async with aiohttp.ClientSession() as session:
247
- async with session.get(pull_url, headers={"Accept": "text/event-stream"}) as resp:
254
+ async with session.get(pull_url, headers={**pull_headers, "Accept": "text/event-stream"}) as resp:
248
255
  buffer = ""
249
256
  async for chunk in resp.content.iter_any():
250
257
  buffer += chunk.decode()
@@ -255,10 +262,15 @@ async with aiohttp.ClientSession() as session:
255
262
 
256
263
  | 状态码 | 说明 |
257
264
  |--------|------|
258
- | 403 | pull_token 无效,或显式提供的 aid 与 target_aid 不匹配 |
265
+ | 400 | `Last-Event-ID` 不是非负整数 |
266
+ | 403 | pull_token 无效,或缺少/提供的 `X-Stream-AID` 与 target_aid 不匹配 |
259
267
  | 404 | 流不存在 |
260
- | 410 | 流已关闭 |
261
- | 429 | 拉流端数量已达上限 |
268
+ | 410 | 推流路径对应的流已关闭 |
269
+ | 416 | `Last-Event-ID` 超出当前序号或已早于保留窗口 |
270
+ | 429 | 拉流端数量或重放内存预算已达上限 |
271
+ | 503 | 服务正在停止或数据面准入容量已耗尽 |
272
+
273
+ 流关闭但尚未清理时,SSE 仍可回放 `event: done`;清理后返回 404。410 仅用于推流路径。
262
274
 
263
275
  ---
264
276
 
@@ -267,11 +279,12 @@ async with aiohttp.ClientSession() as session:
267
279
  | code | message | 说明 |
268
280
  |------|---------|------|
269
281
  | -33401 | Stream not found | stream_id 无效或流已被清理 |
270
- | -33402 | Stream limit exceeded | 活跃流数超过上限 |
282
+ | -33402 | Stream limit exceeded | 活跃流数或关闭通知积压超过上限 |
271
283
  | -33403 | Stream permission denied | 非创建者执行受限操作 |
272
284
  | -33404 | Stream already closed | 流已关闭 |
273
- | -33405 | Stream invalid params | 参数无效(如缺少 stream_id) |
285
+ | -33405 | Stream invalid params | 参数无效(如缺少 stream_id,或 `content_type`、`metadata`、`target_aid` 校验失败) |
274
286
  | -33406 | Stream rate limited | 速率限制 |
275
- | -33407 | Stream internal error | 服务内部错误 |
287
+ | -33407 | Stream internal error | 外部地址不可用或服务内部错误 |
288
+ | -32020 | Service stopping | 服务正在停止,暂不接受新流 |
276
289
 
277
290
 
@@ -1,6 +1,6 @@
1
1
  # AUN SDK 文档查阅指南
2
2
 
3
- AUN SDK 文档位于 `docs/sdk/`,索引文件 `docs/sdk/INDEX.md` 分三层:Layer 1 地图、Layer 2 主题索引、Layer 3 单篇摘要。按需逐层读取,避免一次性加载整套文档。
3
+ AUN SDK 文档位于 `aun-sdk-core/docs/sdk/`,当前对照四 SDK **0.5.34** 源码。索引文件 `INDEX.md` 分三层:Layer 1 地图、Layer 2 主题索引、Layer 3 单篇摘要。`0.5.xx-*` 为版本增量专题,CHANGELOG 保留历史记录;现行接口以基础手册、RPC 手册和最新版本专题为准。
4
4
 
5
5
  ## SDK 文档定位
6
6
 
@@ -10,7 +10,7 @@ AUN SDK 文档位于 `docs/sdk/`,索引文件 `docs/sdk/INDEX.md` 分三层:
10
10
  - `AID`:不可变身份值对象,负责签名、验签和 agent.md 签验。
11
11
  - `AUNClient`:认证、连接、状态机、事件和 RPC。
12
12
  - `PushFacade`:Python SDK 的当前安装推送登记、注销和 Push Server 批次 ACK。
13
- - `ServiceProxyClient`:Python SDK 的 Service Proxy provider 侧客户端,负责 Gateway 控制面注册和 proxy-server 数据面隧道注册。
13
+ - `ServiceProxyClient`:四 SDK 均有 Service Proxy 客户端入口,负责 Gateway 控制面注册和 proxy-server 数据面隧道注册;Browser provider 隧道需具备设置请求头能力的 `webSocketFactory`,见 [Proxy 手册](09-proxy-rpc-manual.md)。
14
14
 
15
15
  业务 RPC 的底层参数见 `09-*-rpc-manual.md`。P2P 共享 seq/peer 游标、pending peers/统计快照、need_render、device 定向发送、TTL volatile 和 ACK 见 `09-message-rpc-manual.md`。当前 Agent.md Schema、签名和上传前校验见 `../protocol/Ownership协议定义2.1.md` 与 `04-连接与认证.md`;`../agent.md/SCHEMA.md` 为 legacy 2.0。当前 Ownership 2.1 应用接入见 `Ownership2.1-SDK应用集成指南.md`,SDK 移植见 `Ownership2.1-SDK开发与移植指南.md`,wire schema 见 `../protocol/Ownership协议定义2.1.md`;旧集成/实现指南与管理专题为 legacy。新服务端为旧 SDK 保留隔离的 owner RPC/Auth JSONL,不参与 2.1 双文件关系判断。Group/Org owner 不走通用流程,名片实体主签、owner token 上传、可选 owner 附签、实体证书代际和原 CAS pending见协议 §1.3/§2.5。peer A/T/H、human Tail 策略、稀疏覆盖、后台续拉和每个 AUNClient 一个网络 Pull Gate(同 namespace 单飞、不同 namespace 最多 4 个并行、相同 key 折叠、可运行项前台 FIFO 优先)见 `03-核心概念.md`;`message.history` / `group.history` 与 Piggy ACK 见 Message/Group RPC Manual;SDK 50k 内存去重、应用持久幂等及三类 batch 的当前契约见 Message RPC Manual。
16
16
 
@@ -33,7 +33,7 @@ Group 的成员 block/status、暂停群权限和两阶段群主转让,以及
33
33
  - 连接与状态:AUNClient / 九态状态机 / Gateway / 重连 / 当前 access token getter / connect-disconnect-close 并发与取消
34
34
  - E2EE:默认加密、ProtectedHeaders、P2P / Group V2
35
35
  - RPC 与事件:`client.call()`、`client.on()`、`client.notify()`、RPC 手册
36
- - AUN EventService:白名单/凭证授权、设备订阅、发布确认、TTL及恢复见[应用集成指南](AUN事件发布订阅应用集成指南.md);协议、单实例、完整Verify、公平背压和四端差异见[开发移植指南](AUN事件发布订阅开发移植指南.md)
36
+ - AUN EventService:0.5.34 版本增量(多角色、持久目录、durable outbox、实时目录)见[0.5.34 应用集成指南](0.5.34-SDK应用集成指南.md)和[0.5.34 开发与移植指南](0.5.34-SDK开发与移植指南.md);完整事件协议、租约、凭证和 fanout 流程见[AUN事件发布订阅应用集成指南](AUN事件发布订阅应用集成指南.md)与[AUN事件发布订阅开发移植指南](AUN事件发布订阅开发移植指南.md)
37
37
  - 离线推送:Python `connect()` 的 `push_notify_aid/push_token`、`client.push.register/unregister`、Push Server ACK
38
38
  - 消息同步:共享 seq 下的 peer A/T/H、稀疏覆盖/前驱、human Tail→Forward、50k 内存去重/应用持久幂等、N=4 网络 Gate、后台工作片续调度、`message.peers_snapshot` 的轻量对端水位/可选整体积压估计、目录/Pull逐页next_pending_seq、可靠commit后持续更新与每N次FIFO(无额外SQL、原列表顺序不改)、need_render/页内计数、`source` 和同步生命周期;Group 保持原终态规则
39
39
  - P2P TTL 消息:`message.send.ttl` 秒级钳制、按 device 内存收件箱、volatile 双游标、自动 ACK/去重、服务 epoch 与重启语义
@@ -56,15 +56,16 @@ Group 的成员 block/status、暂停群权限和两阶段群主转让,以及
56
56
 
57
57
  | 编号 | 文档 | 定位 |
58
58
  |------|------|------|
59
- | - | [AUN事件发布订阅应用集成指南](AUN事件发布订阅应用集成指南.md) | 在线通知接入、两种授权、多设备、成功语义、恢复和诊断 |
60
- | - | [AUN事件发布订阅开发移植指南](AUN事件发布订阅开发移植指南.md) | 线上协议、实例注册、凭证、背压、调度预算和跨端实现 |
59
+ | - | [AUN事件发布订阅应用集成指南](AUN事件发布订阅应用集成指南.md) | 多角色接入、两种授权、目录合并、先持久再发布与重启恢复 |
60
+ | - | [AUN事件发布订阅开发移植指南](AUN事件发布订阅开发移植指南.md) | 独立租约、SQLite/IndexedDB、成功删队列、原TTL与新发送尝试、凭证复核、过期失败及分角色实时清单查询 |
61
61
  | - | [0.5.21 SDK 应用集成指南](0.5.21-SDK应用集成指南.md) | 应用开发者的 TypeScript 接入、消息持久幂等、resolve/owner、凭证组织、诊断与升级 |
62
62
  | - | [0.5.21 SDK 开发与移植指南](0.5.21-SDK开发与移植指南.md) | SDK 开发者的 peer/batch 提交、共识缓存、原 CAS/旧任务、checkpoint、语言差异及验收 |
63
63
  | - | [0.5.22 SDK 应用集成指南](0.5.22-SDK应用集成指南.md) | TypeScript 接线、审批恢复、resolve、缓存及凭证组织 |
64
64
  | - | [0.5.22 SDK 开发与移植指南](0.5.22-SDK开发与移植指南.md) | 同步、Stage/CAS、撤销续期、缓存、服务依赖及 Rust 清单 |
65
65
  | - | [0.5.24 SDK 应用集成指南](0.5.24-SDK应用集成指南.md) | 当前消息接线、无任务 Ownership、两个 local 编排、缓存和凭证组织 |
66
66
  | - | [0.5.24 SDK 开发与移植指南](0.5.24-SDK开发与移植指南.md) | 消息提交、NS 事实和远端 CAS、local 身份隔离、缓存新鲜度与语言差异 |
67
- | - | [0.5.32 应用指南](0.5.32-SDK应用集成指南.md)、[开发与移植指南](0.5.32-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0532);[Python](../../python/CHANGELOG.md)、[Go](../../go/CHANGELOG.md)、[TS](../../ts/CHANGELOG.md)、[JS](../../js/CHANGELOG.md) CHANGELOG | 当前目标对照已发布 0.5.31:EventService、设备租约、公平背压、消息调度、限流缓存及 Ownership |
67
+ | - | [0.5.34 SDK 应用集成指南](0.5.34-SDK应用集成指南.md)、[开发与移植指南](0.5.34-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0534);[Python](../../python/CHANGELOG.md)、[Go](../../go/CHANGELOG.md)、[TS](../../ts/CHANGELOG.md)、[JS](../../js/CHANGELOG.md) CHANGELOG | 对照已发布 0.5.33:EventService 多角色、持久目录与 durable outbox、实时目录、Storage 条件 ACL、Group FS、Service Proxy 和弹性补拉 |
68
+ | - | [0.5.32 应用指南](0.5.32-SDK应用集成指南.md)、[开发与移植指南](0.5.32-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0532);[Python](../../python/CHANGELOG.md)、[Go](../../go/CHANGELOG.md)、[TS](../../ts/CHANGELOG.md)、[JS](../../js/CHANGELOG.md) CHANGELOG | 历史基线:EventService 初始 API、设备租约、公平背压、消息调度、限流缓存及 Ownership |
68
69
  | - | [0.5.30 应用指南](0.5.30-SDK应用集成指南.md)、[开发与移植指南](0.5.30-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0530--控制流按需恢复与-sdk-行为对齐未发布) | 按需控制流恢复、observer.forward 本地字段剥离、本地 human owner、Storage 版本预检及四端差异 |
69
70
  | - | [0.5.29 应用指南](0.5.29-SDK应用集成指南.md)、[开发与移植指南](0.5.29-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0529--共识查询缓存与普通上传未发布) | 0.5.29 基线:共识输入输出、无 TTL 的 ETag 缓存、resolve、普通上传锁与恢复、NS 配套及四端移植 |
70
71
  | - | [0.5.28 应用指南](0.5.28-SDK应用集成指南.md)、[开发与移植指南](0.5.28-SDK开发与移植指南.md);[0.5.27 应用指南](0.5.27-SDK应用集成指南.md)、[开发与移植指南](0.5.27-SDK开发与移植指南.md) | 0.5.28 agent.md 上传/下载校验、共识 fresh、分类控制消息、Owner 通知与风控;四端实现和验证范围见 [parity](../../python/CHANGES_FOR_PARITY.md#v0528--校验控制消息与风控未发布) |
@@ -90,7 +91,7 @@ Group 的成员 block/status、暂停群权限和两阶段群主转让,以及
90
91
  | - | [组织服务 RPC 手册](09-组织服务RPC手册.md) | Org Service 生命周期/成员 RPC、内部接口和未实现方法 |
91
92
  | 05 | [E2EE加密通信](05-E2EE加密通信.md) | E2EE V2、ProtectedHeaders、need_render、agent.md 版本提示、旧 SPK 保留 |
92
93
  | - | [ProtectedHeaders用法专题](ProtectedHeaders用法专题.md) | `protected_headers` 四端 API、实例级/单次调用、E2EE V2 HMAC 完整性和接收信任边界 |
93
- | 06 | [API手册](06-API手册.md) | AIDStore / resolve opts 与输入输出 / frontmatter 类型 / Agent.md 校验签名 / AID / AUNClient 生命周期并发 / 四 SDK access token getter / 群组高层身份编排 / History 与已读门面 / 已读变更及本地补偿完成 / 消息来源与 Pull 同步生命周期 / 事件 / RPC;当前增量见 [0.5.32 parity](../../python/CHANGES_FOR_PARITY.md#v0532) |
94
+ | 06 | [API手册](06-API手册.md) | AIDStore / resolve opts 与输入输出 / frontmatter 类型 / Agent.md 校验签名 / AID / AUNClient 生命周期并发 / 四 SDK access token getter / 群组高层身份编排 / History 与已读门面 / 已读变更及本地补偿完成 / 消息来源与 Pull 同步生命周期 / 事件 / RPC;当前增量见 [0.5.34 parity](../../python/CHANGES_FOR_PARITY.md#v0534) |
94
95
  | 07 | [错误处理](07-错误处理.md) | Result、Python `ErrorInfo.cause`、异常、错误码、重试 |
95
96
  | 08 | [最佳实践](08-最佳实践.md) | 幂等、消息同步/History、AUNClient 级 Pull Gate(同 namespace 单飞、客户端最多 4 个并行)、测试数据 |
96
97
  | - | [Storage RPC 手册](09-storage-rpc-manual.md) | Storage RPC、实际字节 MIME、三阶段 Content-Type、OSS 403、HTTP 下载与凭据边界、默认读缓存持久层、条件读取与 noCache |
@@ -103,8 +104,9 @@ Group 的成员 block/status、暂停群权限和两阶段群主转让,以及
103
104
 
104
105
  | 场景 | 推荐路径 |
105
106
  |------|----------|
106
- | 接入 AUN 发布订阅或处理未收到事件 | [应用集成指南](AUN事件发布订阅应用集成指南.md):场景 L5-38、门面 L39-55、白名单 L56-127、凭证 L128-152、多设备 L153-168、恢复 L169-184、持久化/诊断 L185-216、依据 L217-222 |
107
- | 实现或移植 AUN 发布订阅 | [开发移植指南](AUN事件发布订阅开发移植指南.md):分层 L5-19、实例 L20-39、协议/幂等 L40-87、授权 L88-115、目录 L116-127、分发/预算 L128-173、接收 L174-185、跨端状态 L186-204、验收 L205-229 |
107
+ | 接入 AUN 发布订阅或处理未收到事件 | [应用集成指南](AUN事件发布订阅应用集成指南.md):架构 L5-76、多角色门面 L77-103、Bus目录合并 L106-174、Sub订阅 L175-230、Pub先持久再发布 L231-290、凭证 L291-398、多设备 L399-414、原ID/TTL恢复 L415-430、存储/成功删除/诊断 L431-477、本次依据 L478-484 |
108
+ | 实现或移植 AUN 发布订阅 | [开发移植指南](AUN事件发布订阅开发移植指南.md):多角色分层 L5-64、实例与加载 L65-132、协议/幂等 L133-184、独立授权 L185-323、目录合并 L324-341、耐久入队/删除/TTL/预算 L342-430、订阅与发布恢复 L431-529、四端存储隔离 L530-554、统计错误及验收 L555-588 |
109
+ | 接入或移植 0.5.34 SDK | [应用集成指南](0.5.34-SDK应用集成指南.md):本版变化与架构、EventService 多角色和持久化、Storage 条件 ACL、Group FS/Service Proxy、弹性补拉与验收;[开发与移植指南](0.5.34-SDK开发与移植指南.md):四端分层、EventService 共同契约、控制消息、ACL、Group FS/Storage/Proxy、弹性补拉和验收;[parity](../../python/CHANGES_FOR_PARITY.md#v0534) |
108
110
  | 接入或升级 0.5.21,查看 TypeScript 应用示例 | [0.5.21 SDK 应用集成指南](0.5.21-SDK应用集成指南.md) |
109
111
  | 实现、移植或审查 0.5.21 SDK | [0.5.21 SDK 开发与移植指南](0.5.21-SDK开发与移植指南.md) |
110
112
  | 接入或升级 0.5.22,查看 TypeScript 示例、关系审批、默认读缓存及完整成员包 | [0.5.22 SDK 应用集成指南](0.5.22-SDK应用集成指南.md) |
@@ -1,6 +1,6 @@
1
1
  # AUN事件发布订阅应用集成指南
2
2
 
3
- 面向应用开发者,按 Bus 宿主、Pub 发布方、Sub 订阅方说明调用顺序、配置与结果处理;每条主流程用序列图配套实际 SDK 示例。本文对照当前工作区四端 SDK 与[事件订阅发布方案](../../../docs/AUN文档/AUN事件订阅发布方案.md)整理;源码能力、包发布和服务部署状态应分别核对。SDK 内部契约见[开发移植指南](AUN事件发布订阅开发移植指南.md)。
3
+ 面向应用开发者,按 Bus 宿主、Pub 发布方、Sub 订阅方说明调用顺序、配置与结果处理;每条主流程用序列图配套实际 SDK 示例。本文对照四端 SDK 0.5.34 工作区源码与[事件订阅发布方案](../../../docs/AUN文档/AUN事件订阅发布方案.md)整理;源码能力、包发布和服务部署状态应分别核对。SDK 内部契约见[开发移植指南](AUN事件发布订阅开发移植指南.md),底层消息与实例 RPC 见[消息 RPC 手册](09-message-rpc-manual.md)。
4
4
 
5
5
  ## 1. 适用场景与交付边界
6
6
 
@@ -49,10 +49,10 @@ Bus SDK 决定谁能发布、谁订阅了什么,并将事件逐个发往目标
49
49
  | 应用直接控制全部参与者 | 配置事件目录和发布、订阅 AID 白名单 |
50
50
  | 应用审批后授予临时权限 | Bus 宿主应用本地签发凭证,再将完整凭证交给调用方 |
51
51
  | 同一 AID 多设备选择不同事件 | 每个设备分别鉴权和订阅,只向实际订阅的设备实例投递 |
52
- | 短暂断线后继续观察 | SDK 恢复授权和订阅;尚在 TTL 内的内存消息可能补收 |
52
+ | 断线或进程重启后继续收发 | SDK 恢复授权和订阅;本地尚未完成发布的记录按原 ID、原 TTL 恢复 |
53
53
  | 必须保存历史、补齐每次变化或确认业务提交 | 当前 EventService 不提供事件日志、历史查询、重放或业务 ACK;不能据此保证每次变化都已处理 |
54
54
 
55
- 事件只走正 TTL 的 volatile 内存消息路径。超过 TTL、队列容量耗尽、消息服务重启或 Bus 重启,都可能丢失尚未交付的事件。它适合在线通知,不提供持久消息队列的交付承诺。
55
+ 事件的两跳网络传输仍走正 TTL 的 volatile 内存消息路径。SDK 本地持久化保护尚未完成发布的记录;达到所选回复模式的成功阶段后删除本地正文。Bus 已受理后的 fanout、服务端 volatile 收件箱和事件历史不在持久恢复范围内,超过 TTL、接收容量不足、消息服务或 Bus 重启仍可能导致事件未交付。
56
56
 
57
57
  ```mermaid
58
58
  sequenceDiagram
@@ -62,11 +62,12 @@ sequenceDiagram
62
62
  C->>S: authorize(含目录)→ subscribe
63
63
  S-->>C: 订阅生效
64
64
  P->>S: authorize(含目录)
65
- P->>P: publish返回event_id:本地入队
65
+ P->>P: 本地持久化成功后,publish返回event_id并入队
66
66
  P->>S: 后台发送publish
67
67
  opt replyMode为accepted
68
68
  S-->>P: publish.result:Bus受理
69
69
  end
70
+ P->>P: 达到所选成功阶段后删除本地持久正文
70
71
  S-->>C: event:按剩余TTL定向投递
71
72
  C->>C: SDK校验后交付应用
72
73
  ```
@@ -85,18 +86,18 @@ sequenceDiagram
85
86
 
86
87
  所有业务方法都以 `bus_aid` 为目标参数。应用使用统一门面,内部 Binding、租约令牌、device 和 slot 由 SDK 管理。
87
88
 
88
- - 同一个 client 对同一个 Bus 只能承担 `pub`、`sub`、`bus` 中一种角色;切换会报 `BUS_ROLE_CONFLICT`,`close` 不释放这个角色绑定。
89
+ - 同一个 client 对同一个 Bus 可以同时承担 `pub`、`sub`、`bus`;发布与订阅分别调用 `authorize`,使用独立授权材料和租约。
89
90
  - 同一个 client 可以在不同 Bus 上承担不同角色。签发、撤销和统计只由已启动本地 Bus 的宿主调用。
90
91
  - 未绑定时,`start(bus_aid, ...)` 表示在当前身份启动本地 Bus,要求 `bus_aid == client.aid`。接入远端 Bus 直接调用 `authorize`,由它自动建立客户端。
91
- - 若 Bus 自己也要发布,使用同 AID 的另一个 AUNClient 作为 `pub`,并为它授予发布权限。
92
+ - Bus 自己发布或订阅时,直接在同一个 EventService 上分别授权 `pub`、`sub`,仍须满足相应白名单或凭证权限。`renew`、`drain`、`close` 覆盖该 Bus 已绑定的相关角色。
92
93
 
93
94
  ### 2.1 按自己的角色阅读
94
95
 
95
96
  | 角色 | 应用需要做什么 | 代码与序列图 |
96
97
  | --- | --- | --- |
97
- | Bus 宿主 | 配置目录与权限 → start → 本地签发/撤销或更新名单 → stats → drain/close | §3.1、§4、§7 |
98
- | Pub 发布方 | authorize 自动加载目录 → 分别 publish 多个事件 → 观察完成结果 | §3.3;凭证接入见 §4.3 |
99
- | Sub 订阅方 | authorize 自动加载目录 → 注册回调 → subscribe → 按事件名处理 → 按需取消 | §3.2;凭证接入见 §4.2 |
98
+ | Bus 宿主 | 配置目录与权限 → start → 本地签发/撤销或更新名单 → publications/subscriptions/stats → drain/close | §3.1、§4、§7 |
99
+ | Pub 发布方 | authorize 自动加载目录 → 分别 publish 多个事件 → 观察完成结果及 publications 汇总 | §3.3;凭证接入见 §4.3 |
100
+ | Sub 订阅方 | authorize 自动加载目录 → 注册回调 → subscribe → 按事件名处理 → subscriptions 查询及按需取消 | §3.2;凭证接入见 §4.2 |
100
101
 
101
102
  下面按角色配套序列图和代码。角色图中的“AUN 消息通道”合并表示架构图中的 Gateway 与消息服务;Pub/Sub 到 Bus 的请求及定向回复均经过它。SDK 内部队列和协议执行顺序见[开发移植指南](AUN事件发布订阅开发移植指南.md)。
102
103
 
@@ -118,6 +119,7 @@ sequenceDiagram
118
119
  alt 注册成功
119
120
  M-->>G: 实例租约:100 秒有效,30 秒后续期
120
121
  G-->>B: 注册结果
122
+ B->>B: 加载持久目录及有效关系,合并本次配置
121
123
  B->>B: 启用承接、队列与分发
122
124
  B-->>A: start 完成
123
125
  else 已有实例
@@ -166,6 +168,8 @@ Bus 宿主直接维护配置、签发和撤销凭证、查询统计,无需额
166
168
 
167
169
  一个 Bus 的目录可登记多个事件。示例让同一发布方、订阅方使用两个事件;需要不同权限时,分别配置各事件的 `publish_aids` 和 `subscribe_aids`。各事件也可独立设置正文约束、版本和 TTL。
168
170
 
171
+ 事件目录、白名单和订阅关系默认持久保存。启动先加载已有目录,再合并本次配置;后续 `updateConfig` 也按事件合并,同名事件以本次条目为准,未提交的事件保留。收回某事件的白名单权限时提交该事件的空名单;省略事件或传空配置不会清空已有目录。
172
+
169
173
  同一个 Bus AID 同时只允许一个设备实例运行。第二个实例启动返回 `DEVICE_CONFLICT`;需要独立服务时使用不同 Bus AID。实际环境须支持 `aun.pubsub/1` 控制消息及 `message.evtsvc.*` 实例注册能力。
170
174
 
171
175
  ### 3.2 订阅方一次鉴权多个事件并登记订阅
@@ -183,13 +187,16 @@ sequenceDiagram
183
187
  N->>B: 申请订阅权限
184
188
  B-->>N: 设备租约及获准目录
185
189
  N-->>S: SDK 自动加载目录,必要时续页
190
+ S->>S: 完整目录及授权材料持久保存
186
191
  S-->>A: 鉴权完成
187
192
  A->>S: onEvent(bus_aid, handler)
188
193
  A->>S: subscribe(bus_aid, events)
189
194
  S->>N: subscribe:设备租约及事件列表
190
195
  N->>B: 登记当前设备、slot 的订阅
196
+ B->>B: 保存订阅关系
191
197
  B-->>N: subscribe.result
192
198
  N-->>S: 订阅成功
199
+ S->>S: 保存本角色订阅意图
193
200
  S-->>A: subscribe 完成
194
201
  B->>N: event:指定已订阅的设备与 slot
195
202
  N-->>S: Push 或 TTL 内的 Pull
@@ -215,6 +222,8 @@ await sub.subscribe(busAid, eventNames);
215
222
 
216
223
  `authorize` 建立权限租约,同时取得并缓存本次获准事件的目录;白名单和凭证模式都无需再单独调用 `catalog`。大目录由 SDK 自动分页取齐后才返回。`subscribe` 成功回复后订阅生效,可以一次传全部获准事件,也可只传其中一部分;新增范围需重新鉴权。鉴权范围内任一事件未获准,整个鉴权失败。
217
224
 
225
+ 同一角色在相同授权模式和凭证下再次 `authorize`,新增事件与已有授权范围合并;不同凭证不能混合扩大权限。后续 `subscribe` 追加关系,`unsubscribe` 移除对应关系,其余订阅及目录条目保留。
226
+
218
227
  回调在订阅前注册,支持返回 Promise。也可以不注册回调,使用 `await sub.nextEvent(busAid, 5)` 主动等待,超时单位为秒。Python 对应 `next_event(bus_aid, timeout=5)`;Go 用 `NextEvent(ctx, bus_aid)` 的 context 控制超时。
219
228
 
220
229
  回调与主动等待选择一种消费方式;有回调时,新事件进入回调路径,不会同时成为 `nextEvent` 的副本。回调按顺序执行,异常不会终止后续事件,也不会要求 Bus 重发;慢处理会占用有界接收容量。
@@ -235,10 +244,11 @@ sequenceDiagram
235
244
  B->>B: 校验权限,建立设备授权租约
236
245
  B-->>N: authorize.result:租约与目录首页
237
246
  N-->>P: 定向返回原 Pub 设备
238
- P->>P: SDK 自动取齐后续页,缓存获准目录
247
+ P->>P: SDK 自动取齐后续页,持久保存获准目录与授权材料
239
248
  P-->>A: 目录缓存就绪,鉴权完成
240
249
  A->>P: publish(bus_aid, event_name, JSON对象)
241
- P-->>A: 返回 event_id:已进入本地有界队列
250
+ P->>P: 先将待发布正文及原 ID、期限写入持久存储
251
+ P-->>A: 写入成功,返回 event_id:已进入本地有界队列
242
252
  P->>N: 后台发送 publish,保留原 TTL
243
253
  N-->>P: AUN 已接受发送
244
254
  N->>B: 发布请求
@@ -247,6 +257,7 @@ sequenceDiagram
247
257
  B-->>N: publish.result:Bus 已受理
248
258
  N-->>P: 仅回原 Pub 设备
249
259
  end
260
+ P->>P: none 发送成功 / accepted 收到 Bus 受理后删除持久正文
250
261
  P-->>A: waitPublished / onPublish 返回对应阶段结果
251
262
  Note over B: 后台向有效订阅设备公平分发
252
263
  ```
@@ -264,18 +275,18 @@ await Promise.all([pub.waitPublished(busAid, doneId), pub.waitPublished(busAid,
264
275
 
265
276
  | 观察结果 | 可以确认什么 |
266
277
  | --- | --- |
267
- | `publish` 返回 `event_id` | 本地发布队列已收下任务,尚未保证发送成功 |
278
+ | `publish` 返回 `event_id` | 待发布记录已本地持久化并入队,尚未保证发送成功;持久写入失败则调用失败 |
268
279
  | 默认 `replyMode: 'none'` 的 `waitPublished` 成功 | AUN 接受了发往 Bus 的消息 |
269
280
  | `replyMode: 'accepted'` 的 `waitPublished` 返回 `status: 'accepted'` | Bus 完成授权、去重及内存受理,后续分发仍在后台执行 |
270
281
  | `onEvent` / `nextEvent` 收到事件 | 当前设备 SDK 已收到并校验;业务处理结果由应用负责 |
271
282
 
272
283
  一次 `authorize` 可授权多个事件;每次 `publish` 指定一个完整事件名和对应 JSON 正文。不同事件的发布共用该 Bus 的有界队列与公平调度,应用按每个 `event_id` 观察结果。订阅方通过 `event.event_name` 分发给各业务处理函数。
273
284
 
274
- `waitPublished` 的错误必须由调用方处理;也可用 `onPublish(busAid, handler)` 观察后台发送完成,其参数含 `event_id`、`result` 或 `error`。结果缓存有界且只在内存中,不能作为长期审计记录,过期或淘汰后等待可能报 `UNKNOWN_EVENT`。
285
+ `waitPublished` 的错误必须由调用方处理;也可用 `onPublish(busAid, handler)` 观察后台发送完成,其参数含 `event_id`、`result` 或 `error`。正常完成结果使用有界运行时缓存,重启后不保证可查;待发布记录过期时保存可查询的失败结果。结果保存仍受容量限制,不能作为长期审计记录。
275
286
 
276
287
  `data` 必须为 JSON 对象,允许嵌套 JSON 值;不能直接传数组、字符串、`null`、非有限数或不可序列化对象。TTL 默认为目录配置(缺省 30 秒),取整数 1—3600 秒且不得超过该事件 `max_ttl_seconds`。正文连同事件封装受 64 KiB 明文预算限制。
277
288
 
278
- 本地排队、加密、两跳网络发送与 Bus 排队共用原始期限。超时表示结果可能未知;重试复用原 `eventId` 和原事件内容,由 SDK 保留原期限。同 ID 改正文、事件名或版本会冲突;内存去重不构成持久的“恰好一次”保证。
289
+ 本地排队、加密、两跳网络发送与 Bus 排队共用原始期限。超时表示结果可能未知;重试复用原 `eventId` 和原事件内容,由 SDK 保留原期限,并为恢复或失败后的新发送尝试更新内部请求和网络消息标识。同 ID 并发调用须等待同一持久写入结果,不能在写入成功前确认接收。同 ID 改正文、事件名或版本会冲突;内存去重不构成持久的“恰好一次”保证。
279
290
 
280
291
  ## 4. 场景二:应用审批与凭证授权
281
292
 
@@ -392,8 +403,8 @@ Bus 从 AUN 验签结果取得发布者、订阅者的 AID 和设备身份,再
392
403
  | 变更 | 应用动作与生效边界 |
393
404
  | --- | --- |
394
405
  | 取消某事件 | `await sub.unsubscribe(busAid, [eventName])`;SDK 移除本地意图,后续恢复不再补订阅它 |
395
- | 白名单缩权 | Bus 宿主 `updateConfig(busAid, { allowlist })`;取消的权限及对应订阅立即收缩,凭证租约继续按凭证校验 |
396
- | 白名单增加权限 | 调用方重新 `authorize` 申请完整所需范围,自动加载目录后订阅新增事件;续期不会扩展原 scope |
406
+ | 白名单缩权 | Bus 宿主 `updateConfig(busAid, { allowlist })`;取消的权限及对应订阅立即收缩,客户端成功续期后同步持久授权范围及订阅意图,凭证租约继续按凭证校验 |
407
+ | 白名单增加权限 | 调用方重新 `authorize` 申请新增范围,同角色且授权来源相同时合并已有范围,自动加载目录后订阅新增事件;续期不会扩展原 scope |
397
408
  | 修改事件目录或版本 | Bus 宿主 `updateConfig(busAid, { catalog })`;客户端重新 `catalog`,发布使用当前 `schemaVersion` |
398
409
  | 关闭回调 | 调用注册返回的 `stopEvents()`;它只取消本地 handler,不等于远端 `unsubscribe` |
399
410
 
@@ -409,25 +420,38 @@ Bus 从 AUN 验签结果取得发布者、订阅者的 AID 和设备身份,再
409
420
  | 发布/订阅授权 | 默认有效 200 分钟、每 1 小时续期;凭证模式还受凭证链期限约束,以回复 `expires_at` 为准 |
410
421
  | 凭证状态证明 | 按 `proofExpiresAt` 独立刷新;过期且无法刷新时暂停相关操作,不等每小时续期 |
411
422
  | 当前进程短断线 | 连接 ready 后尝试续期;需要重新鉴权时使用已保存的授权材料,并恢复未取消的订阅 |
412
- | Bus 重启 | 配置可恢复,原租约、订阅和事件队列不恢复;客户端重新鉴权和订阅 |
413
- | 客户端进程重启或显式 close | 应用重新执行接入流程;SDK 不保存跨进程订阅意图 |
423
+ | Bus 重启 | 加载目录并合并本次配置,恢复仍有效且通过权限复核的授权租约、订阅;已受理的 fanout 队列不恢复 |
424
+ | 客户端进程重启或显式 close | 保留目录、授权及订阅意图和待发布记录;新进程分别 `authorize` 所需 Pub/Sub,已绑定角色可再次 `start`,加载后鉴权并恢复订阅和发布 |
414
425
  | Bus 失去实例租约 | 停止承接与分发,不自动抢占后来实例;宿主显式 `start`,客户端重新鉴权、订阅 |
415
426
 
416
- 自动恢复只恢复关系,不补发已过期或丢失事件。无需调用内部 `recover`,公开门面没有该方法。
427
+ Bus 宿主在新进程重新 `start(busAid, options)`;远端 Pub/Sub 分别重新 `authorize(busAid, role, ...)` 建立目标角色,内部启动随即加载该角色持久状态。SDK 不会在初始化时自动枚举所有历史 Bus。恢复待发布记录时沿用原 `event_id` 和 `expires_at`,不会重新计满 TTL;已过期则记录失败供完成接口查询,不再发送。恢复不补发 Bus 已受理后丢失的事件,也不提供历史重放。无需调用内部 `recover`,公开门面没有该方法。
417
428
 
418
- 停机先停止上游提交,再对相关 Bus 执行 `drain(busAid)`、`close(busAid)`;先排空发布方,再排空 Bus。`drain` 等待已接管任务及回调,不证明所有设备都收到或提交业务。`close` 清理队列、挂起等待和授权状态;再次接入需重新鉴权和订阅,目录随鉴权自动加载。关闭 AUNClient 也会关闭其 EventService。
429
+ 停机先停止上游提交,再对相关 Bus 执行 `drain(busAid)`、`close(busAid)`;先排空发布方,再排空 Bus。`drain` 等待已接管任务及回调,不证明所有设备都收到或提交业务。`close` 清理运行时队列和挂起等待,保留持久目录、订阅意图及尚未完成的发布记录;中断发送也保留待发布记录。再次接入时重新鉴权并恢复。关闭 AUNClient 也会关闭其 EventService。
419
430
 
420
431
  ## 7. 持久化、统计与故障定位
421
432
 
422
- | SDK | Bus 配置与凭证材料保存方式 |
433
+ | SDK | 默认状态保存方式 |
434
+ | --- | --- |
435
+ | Python / Go | 复用当前身份的 SQLite `{aun_path}/AIDs/{self-aid}/aun.db`,保存 Bus 目录、有效授权与订阅、客户端状态及待发布记录;显式 `state_path` / `StatePath` 的 Bus 状态使用 `event-service.sqlite3`,凭证仍用 `credential-state.json`,客户端发布队列仍在自身 `aun.db` |
436
+ | TS(Node.js) | 复用当前身份的 SQLite `aun.db` 保存上述状态;`start` 的 `state.load/save` 可覆盖 Bus 状态,`credentialOptions.state.load/save` 可覆盖凭证材料存储 |
437
+ | JS(浏览器) | 复用 IndexedDB `aun-keystore` 的 `metadata`;Bus 状态按身份及 Bus 隔离,客户端另区分角色及设备实例;自定义 Bus 和凭证存储回调同 TS |
438
+
439
+ Bus 状态包括目录、白名单、签发及暂停记录,以及可复核恢复的授权租约和订阅。客户端按身份、Bus、角色及设备实例隔离保存授权材料、目录、订阅意图、待发布记录和过期失败结果。首次启动后直接使用默认持久层,无需另配存储回调;重启加载后增量合并后续注册和订阅。Python / Go 可导入旧 `event-service.json`,后续写入 SQLite。各语言内部状态格式不是跨语言导入协议。
440
+
441
+ 发布持久记录的顺序为“写入成功 → 确认本地入队 → 后台发送 → 按回复模式判定成功 → 删除本地正文”。默认 `none` 在 AUN 接受发送后删除,`accepted` 在收到 Bus 受理回复后删除;关闭、中断或未确认成功时保留。该保障不覆盖 Bus 后台 fanout、服务端 volatile 收件箱和事件历史。
442
+
443
+ 默认凭证适配器仍使用元数据键 `pubsub_credentials_v1`,保存原凭证、登记/撤销请求、提交证据和结果;Bus 状态与凭证材料各自保存。`self-aid` 指当前 SDK 身份,客户端待发布记录保存在发布者自身的数据库中。
444
+
445
+ 实时目录用 `publications(busAid, params)` 和 `subscriptions(busAid, params)`,Go 对应 `Publications` / `Subscriptions`。Bus 宿主查询全局;Pub 查询自身 AID、当前发布权限内的受理汇总;Sub 查询当前设备租约实际生效的订阅。多角色时,`publications` 的 `role` 可选 `"bus" / "pub"`,`subscriptions` 可选 `"bus" / "sub"`;省略时优先本地 Bus,否则使用对应 Pub/Sub,这个参数只用于本地选择。
446
+
447
+ | 查询 | `items` 条目 |
423
448
  | --- | --- |
424
- | Python / Go | 凭证材料默认自动写入 `{aun_path}/AIDs/{self-aid}/aun.db`;显式 `state_path` / `StatePath` 时,指定目录保存 `event-service.json` 和 `credential-state.json` |
425
- | TS | 凭证材料默认自动写入自身 AID 的 `aun.db`;服务配置通过 `start` 的 `state.load/save` 保存,`credentialOptions.state.load/save` 可覆盖凭证存储 |
426
- | JS | 凭证材料默认自动写入浏览器 IndexedDB `aun-keystore` 的 `metadata`,按自身 AID 隔离;服务配置及自定义凭证存储回调同 TS |
449
+ | `publications` | `publisher_aid`、`event_name`、`published`、`first_published_at`、`last_published_at`;按事件名汇总,不含正文或逐消息历史 |
450
+ | `subscriptions` | `subscriber_aid`、`event_name`、`device_id`、`slot_id`、`expires_at`;不含租约令牌或凭证 |
427
451
 
428
- 服务状态包括目录、白名单、签发及暂停记录;它不保存事件历史、租约、订阅或投递队列。重启加载的已保存配置优先于初始配置,变更应通过 `updateConfig` 提交。各语言内部状态格式不是跨语言导入协议,不能直接交换目录中的状态文件。
452
+ 两种结果均含 `service_aid`、`since`、`as_of`、`items`、`next_page_token`;时间为 UTC Unix 毫秒。参数可选 `event_name`、`limit`(默认 50,上限 200)与 `page_token`,末页 token 为 null。每页反映当时的有效关系,无冻结快照;token 有效 60 秒并绑定查询范围,Bus 重启后旧 token 失效,应从首页重查;完整回复最多 64 KiB。发布计数以 Bus 首次受理为准,去重和拒绝不增加;消息 TTL 到期后汇总仍在,Bus 重启后清零。Pub 的 none 发送成功可能尚未到达 Bus;Sub 的授权事件目录也不等于已订阅目录。
429
453
 
430
- 默认凭证适配器统一使用元数据键 `pubsub_credentials_v1`,保存原凭证、登记/撤销请求、提交证据和结果,应用无需另写存储回调。凭证材料自动保存与 Bus 配置保存是两件事;要恢复完整 Bus 配置,仍需按上表配置服务状态存储。`self-aid` 指运行 Bus 的当前身份,不是发布者或订阅者。
454
+ 例如 `await bus.publications(busAid)` 查全局发布汇总,`await pub.publications(busAid, { role: "pub" })` 查自身,`await sub.subscriptions(busAid, { role: "sub" })` 查自己的实际订阅;需要事件定义仍调用 `catalog`。
431
455
 
432
456
  Bus 宿主应用调用 `bus.stats(busAid, { event_name: eventName })`,结果位于 `counts`,`since` 为本次运行起点,`as_of` 为查询时点。计数不持久保存。
433
457
 
@@ -444,7 +468,7 @@ Bus 宿主应用调用 `bus.stats(busAid, { event_name: eventName })`,结果
444
468
  | 表现或错误 | 核查顺序 |
445
469
  | --- | --- |
446
470
  | `SERVICE_NOT_STARTED` / `DEVICE_CONFLICT` | 确认 Bus 是否已成功 start、是否有其他承接实例 |
447
- | `BUS_ROLE_CONFLICT` / `SERVICE_IDENTITY_MISMATCH` | 检查同 client 的角色及宿主 AID |
471
+ | `ROLE_MISMATCH` / `SERVICE_IDENTITY_MISMATCH` | 检查是否已授权调用所需角色,以及宿主 AID 是否正确;角色并存无需拆分 client |
448
472
  | `FORBIDDEN` / `REAUTH_REQUIRED` | 检查名单或凭证 scope、租约、证明和撤销状态 |
449
473
  | `CATALOG_REQUIRED` / `SCHEMA_MISMATCH` / `UNSUPPORTED_SCHEMA_VERSION` | 获取当前事件目录,再使用匹配版本发布 |
450
474
  | `OVERLOADED` / `MESSAGE_TOO_LARGE` | 检查发布及接收容量、正文尺寸;未入队的调用不能视为成功 |
@@ -455,5 +479,6 @@ Bus 宿主应用调用 `bus.stats(busAid, { event_name: eventName })`,结果
455
479
 
456
480
  - 门面与应用接线:[Python](../../python/src/aun_core/pubsub/__init__.py)、[TypeScript](../../ts/src/pubsub/index.ts)、[JavaScript](../../js/src/pubsub/index.ts)、[Go](../../go/pubsub_service.go)。
457
481
  - 应用场景:[Python 应用测试](../../python/tests/unit/test_pubsub_application.py)、[场景测试](../../python/tests/unit/test_pubsub_scenarios.py)、[设备与恢复 E2E](../../python/tests/e2e_test_event_pubsub_recovery.py)。
458
- - 本轮真实跨端证据:[实施计划 §9.9](../../../docs/AUN文档/AUN事件订阅发布TDD实施计划.md#99-凭证默认存储授权目录与移除管理身份)与[128项汇总](../../tests/cross-sdk/artifacts/pubsub-4sdk-20261105/remove-manager-acceptance/final-acceptance-summary.json):四种 Bus 各32/32,覆盖两种授权、同SDK和有向跨SDK;本地签发与统计、authorize自动目录后直接发布订阅均通过。
482
+ - 此前真实跨端证据:[实施计划 §9.9](../../../docs/AUN文档/AUN事件订阅发布TDD实施计划.md#99-凭证默认存储授权目录与移除管理身份)与[128项汇总](../../tests/cross-sdk/artifacts/pubsub-4sdk-20261105/remove-manager-acceptance/final-acceptance-summary.json):四种 Bus 各32/32,覆盖两种授权、同SDK和有向跨SDK;该归档不作为本次角色并存与发布队列持久化变更的验收结果。
483
+ - 本次变更已通过本机相关单元测试、SQLite/IndexedDB 存储重开与故障模拟及静态检查,未执行真实服务 E2E 或浏览器网络 E2E。
459
484
  - 证据边界:JS 使用 Node 与 fake-indexeddb;真实浏览器、macOS、真实双域设备 E2E,以及实填 64 MiB/RSS 压力未验,详见[方案 §15](../../../docs/AUN文档/AUN事件订阅发布方案.md#15-轻量服务与单实例使用边界)。