@agentunion/fastaun-browser 0.5.16 → 0.5.18

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 (83) hide show
  1. package/CHANGELOG.md +334 -258
  2. package/_packed_docs/CHANGELOG.md +334 -258
  3. package/_packed_docs/INDEX.md +36 -5
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +13 -5
  5. package/_packed_docs/agent.md/SCHEMA.md +52 -33
  6. 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 +1170 -1164
  7. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1215 -1213
  8. package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +95 -6
  9. package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -43
  10. package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +19 -4
  11. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +80 -17
  12. package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +25 -2
  13. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +69 -10
  14. package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +7 -4
  15. package/_packed_docs/sdk/09-group-rpc-manual.md +167 -35
  16. package/_packed_docs/sdk/09-message-rpc-manual.md +72 -42
  17. package/_packed_docs/sdk/09-storage-rpc-manual.md +48 -18
  18. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +16 -12
  19. package/_packed_docs/sdk/INDEX.md +14 -13
  20. package/dist/agent-md-schema.d.ts.map +1 -1
  21. package/dist/agent-md-schema.js +2 -0
  22. package/dist/agent-md-schema.js.map +1 -1
  23. package/dist/agent-md.d.ts +3 -1
  24. package/dist/agent-md.d.ts.map +1 -1
  25. package/dist/agent-md.js +13 -4
  26. package/dist/agent-md.js.map +1 -1
  27. package/dist/aid-store.d.ts +45 -0
  28. package/dist/aid-store.d.ts.map +1 -1
  29. package/dist/aid-store.js +231 -3
  30. package/dist/aid-store.js.map +1 -1
  31. package/dist/aid.d.ts +17 -1
  32. package/dist/aid.d.ts.map +1 -1
  33. package/dist/aid.js +49 -2
  34. package/dist/aid.js.map +1 -1
  35. package/dist/bundle.js +2763 -1591
  36. package/dist/cert-utils.d.ts.map +1 -1
  37. package/dist/cert-utils.js +5 -3
  38. package/dist/cert-utils.js.map +1 -1
  39. package/dist/client/delivery.d.ts +19 -0
  40. package/dist/client/delivery.d.ts.map +1 -1
  41. package/dist/client/delivery.js +198 -12
  42. package/dist/client/delivery.js.map +1 -1
  43. package/dist/client/group-state.d.ts +4 -0
  44. package/dist/client/group-state.d.ts.map +1 -1
  45. package/dist/client/group-state.js +63 -0
  46. package/dist/client/group-state.js.map +1 -1
  47. package/dist/client/rpc-pipeline.d.ts.map +1 -1
  48. package/dist/client/rpc-pipeline.js +46 -5
  49. package/dist/client/rpc-pipeline.js.map +1 -1
  50. package/dist/client/v2-e2ee.d.ts +7 -1
  51. package/dist/client/v2-e2ee.d.ts.map +1 -1
  52. package/dist/client/v2-e2ee.js +918 -463
  53. package/dist/client/v2-e2ee.js.map +1 -1
  54. package/dist/client.d.ts.map +1 -1
  55. package/dist/client.js +73 -14
  56. package/dist/client.js.map +1 -1
  57. package/dist/facades.d.ts +7 -0
  58. package/dist/facades.d.ts.map +1 -1
  59. package/dist/facades.js +21 -0
  60. package/dist/facades.js.map +1 -1
  61. package/dist/group-fs.d.ts.map +1 -1
  62. package/dist/group-fs.js +8 -5
  63. package/dist/group-fs.js.map +1 -1
  64. package/dist/index.d.ts +3 -2
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +1 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/ownership-proof.d.ts +30 -0
  69. package/dist/ownership-proof.d.ts.map +1 -0
  70. package/dist/ownership-proof.js +97 -0
  71. package/dist/ownership-proof.js.map +1 -0
  72. package/dist/storage/vfs.d.ts +1 -0
  73. package/dist/storage/vfs.d.ts.map +1 -1
  74. package/dist/storage/vfs.js +68 -5
  75. package/dist/storage/vfs.js.map +1 -1
  76. package/dist/tools/cross-sdk-agent.js +34 -3
  77. package/dist/tools/cross-sdk-agent.js.map +1 -1
  78. package/dist/transport.js +34 -34
  79. package/dist/types.d.ts +16 -1
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/version.d.ts +1 -1
  82. package/dist/version.js +1 -1
  83. package/package.json +13 -13
@@ -62,9 +62,14 @@ store := aun.NewAIDStore(aunPath, encryptionSeed, aun.AIDStoreOptions{
62
62
 
63
63
  | Python | TS/JS | Go | 说明 |
64
64
  |--------|-------|----|------|
65
- | `load(aid)` | `load(aid)` | `Load(aid)` | 从本地加载 AID |
66
- | `register(aid)` | `register(aid)` | `Register(ctx, aid)` | 注册并落盘证书和私钥 |
67
- | `list()` | `list()` | `List()` | 列出本地 AID |
65
+ | `load(aid)` | `load(aid)` | `Load(aid)` | 从本地加载 AID |
66
+ | `register(aid)` | `register(aid)` | `Register(ctx, aid)` | 注册并落盘证书和私钥 |
67
+ | `register({aid, type, owner?, ...})` | `register({aid, type, owner?, ...})` | `RegisterWithOptions(ctx, params)` | 新 AID 的类型/owner 注册编排 |
68
+ | `bind_aid(params)` | `bindAid(params)` | `BindAID(ctx, params)` | 已有证书的 legacy/unbound 关系绑定 |
69
+ | `get_aid_binding_status(aid)` | `getAidBindingStatus(aid)` | `GetAIDBindingStatus(ctx, aid)` | 查询绑定状态 |
70
+ | `resume_aid_binding(operation_id)` | `resumeAidBinding(operation_id)` | `ResumeAIDBinding(ctx, operationID, aid...)` | 查询 operation 并恢复激活 |
71
+ | `change_owner(params)` | `changeOwner(params)` | `ChangeOwner(ctx, params)` | 三方换 owner 编排 |
72
+ | `list()` | `list()` | `List()` | 列出本地 AID |
68
73
  | `exists(aid)` | `exists(aid)` | `Exists(ctx, aid)` | 远端存在性检查 |
69
74
  | `resolve(aid, opts=None)` | `resolve(aid, opts?)` | `Resolve(ctx, aid, opts...)` | 拉证书并缓存;默认下载 agent.md,可用 `skip_agent_md` / `skipAgentMd` 跳过 |
70
75
  | `upload_agent_md(aid, content=None)` | `uploadAgentMd(aid, content?)` | `UploadAgentMD(ctx, aid, content...)` | 发布本地 AID 的 agent.md;签名后使用该 AID 的 access_token 上传 |
@@ -74,7 +79,40 @@ store := aun.NewAIDStore(aunPath, encryptionSeed, aun.AIDStoreOptions{
74
79
  | `renew_cert(aid)` / `rekey(aid)` | `renewCert(aid)` / `rekey(aid)` | `RenewCert(ctx, aid)` / `Rekey(ctx, aid)` | 证书运维 |
75
80
  | `change_seed(old, new)` | `changeSeed(old, new)` | `ChangeSeed(old, new)` | 本地密钥保护种子迁移 |
76
81
 
77
- Python、TS/Node 与 Go 的 `AIDStore` 本地方法返回 Result 包装;浏览器 JS 因 IndexedDB / WebCrypto 约束返回 `Promise<Result>`。联网方法在 TS/JS 中均返回 `Promise<Result>`;Go 形态为 `Result[T]`,字段为 `Ok` / `Data` / `Error`。
82
+ Python、TS/Node 与 Go 的 `AIDStore` 本地方法返回 Result 包装;浏览器 JS 因 IndexedDB / WebCrypto 约束返回 `Promise<Result>`。联网方法在 TS/JS 中均返回 `Promise<Result>`;Go 形态为 `Result[T]`,字段为 `Ok` / `Data` / `Error`。
83
+
84
+ 新身份使用 `register({ aid, type, owner? })`:SDK 先签发 AID 证书,再通过 `auth.aid_register_*` 完成关系登记;不要对新身份先普通注册后调用 `bindAid`。`bind_aid` / `bindAid` / `BindAID` 用于已有证书且关系为 `legacy_unbound` 或 `unbound` 的 AID 绑定或重绑,不创建新证书。
85
+
86
+ ### Owner 关系注册与绑定
87
+
88
+ SDK 同时保留两条明确的高层路径:
89
+
90
+ | 场景 | 高层入口 | 服务端流程 | 是否签发证书 |
91
+ |------|----------|------------|:------------:|
92
+ | 新 AID | `register({aid, type, owner?, agent_md?, idempotency_key?})` / `RegisterWithOptions` | `auth.aid_register_prepare` → `submit` → 发布带 proof 的 `agent.md` → `activate` | 是 |
93
+ | 已有 legacy/unbound AID | `bind_aid` / `bindAid` / `BindAID` | `auth.aid_bind_prepare` → `submit` → 发布带 proof 的 `agent.md` → `activate` | 否 |
94
+
95
+ `register(aid)` / `Register(ctx, aid)` 保持兼容语义:只创建或恢复证书并上传普通 `agent.md`,不会创建 owner 关系。新建非 `human` AID 必须在新注册入口提供 owner;`human` 不得提供 owner;只有 `agent` 可以使用 self-owner(`owner == aid`)。外部 owner 需要 subject 和 owner 两份签名,self-owner 只需要 subject 签名。
96
+
97
+ Auth 关系类型可接受 `org`,但当前 CA/Name Service 只实现 `signing` 与 `group_identity` 证书用途;`org_identity` 尚未实现,SDK 不应把组织身份证书映射或组织专用 agent.md 签名描述为可用能力。
98
+
99
+ 新注册和绑定完成 `prepare` 后,SDK 将服务端返回的 `proof_id`、`fact_hash`、`statement_hash` 及签名封套写入 `ownership_proof`,并用 `owner_operation_id` 上传 `agent.md`;普通 `uploadAgentMd` 不能改变已激活关系。operation 有效期为 7 天,证书在 pending/失败/过期期间仍可登录和通信。
100
+
101
+ 状态可通过 `get_aid_binding_status` / `auth.aid_register_status` / `auth.owner_relation_status` 查询,通过 `resume_aid_binding` 或 `aid_operation_get` 在进程重启后恢复。常见状态为 `legacy_unbound`、`pending`、`proof_pending`、`agent_md_pending`、`active`、`not_applicable`、`unbound`、`unusable`、`expired`。
102
+
103
+ ### Ownership proof 约定
104
+
105
+ 四端 SDK 使用同一组 UTF-8 canonical bytes(对象键按字典序、无空格):
106
+
107
+ ```text
108
+ fact = canonical_json({"subject_aid": subject, "owner_aid": owner})
109
+ statement = canonical_json({"proof_id": proof_id, "subject_aid": subject, "owner_aid": owner})
110
+ signing_bytes = UTF-8("AUN-AID-OWNER-RELATION-V1;") || statement
111
+ ```
112
+
113
+ AID 先规范化为 ASCII 小写;`proof_id` 必须是 UUID v4;`fact_hash` 是 `SHA-256(fact)`,`statement_hash` 是 `SHA-256(signing_bytes)`,均为小写十六进制。签名封套只有 `cert_fingerprint`(`sha256:<64 hex>`)和严格 Base64 的 `signature`。`owner_signature` 对外部 owner 必需,对 self-owner 必须省略。
114
+
115
+ `change_owner` 由当前 owner 发起,`expected_relation_version` 用于 CAS;提交 `old_owner_signature`、subject signature 和 new owner signature 后,subject 发布新 proof 并激活。成功后 `relation_version` 递增,旧 owner 的 Storage ACL 撤销但数据保留,新 owner 的 ACL 重新创建。
78
116
 
79
117
  ### Result 类型
80
118
 
@@ -238,11 +276,17 @@ await client.close()
238
276
  ### RPC
239
277
 
240
278
  ```python
241
- result = await client.call("message.send", {
242
- "to": "bob.agentid.pub",
243
- "payload": {"type": "text", "text": "hello"},
244
- })
245
- ```
279
+ result = await client.call("message.send", {
280
+ "to": "bob.agentid.pub",
281
+ "device_id": "bob-phone",
282
+ "ttl": 300,
283
+ "payload": {"type": "text", "text": "hello"},
284
+ })
285
+ ```
286
+
287
+ `message.send` 可选传入目标 `device_id`,非空时只投递该设备;`to_device_id` 仅为兼容别名,规范字段优先。目标无效时发送失败且不会退化为全设备投递。这里的 `device_id` 是接收目标,`message.pull` / `message.ack` 的同名字段则表示当前消费设备。
288
+
289
+ `ttl` 单位为秒:缺省或 `<=0` 保持持久化;正数钳制到 1–3600 秒,只存于消息服务内存且不分配持久 `seq`。四个 SDK 自动维护 volatile 游标、去重及 ACK;返回和事件中的 `storage`、`volatile_cursor`、`created_at`、`expires_at` 可用于识别此类消息。
246
290
 
247
291
  常用 meta RPC 直接透传:
248
292
 
@@ -328,10 +372,12 @@ headers = client.get_protected_headers()
328
372
 
329
373
  | 能力 | Python | TS/JS | Go | 说明 |
330
374
  |------|--------|-------|----|------|
331
- | Storage VFS | `client.storage` | `client.storage` | `client.Storage()` | 类 POSIX 文件操作;上传自动选择 inline / session / 秒传,下载自动选择 inline / ticket;支持 `touch`、`find`、`du`、`df`、ACL/token/软链/挂载门面 |
375
+ | Storage VFS | `client.storage` | `client.storage` | `client.Storage()` | 类 POSIX 文件操作;上传自动选择 inline / session / 秒传并统一 Content-Type,下载自动选择 inline / ticket;支持 `touch`、`find`、`du`、`df`、ACL/token/软链/挂载门面 |
332
376
  | Collab | `client.collab` | `client.collab` | `client.Collab()` | 版本化文档、标签、`gc` / `reflog` / `revert` |
333
377
  | Group FS | `client.group.fs` | `client.group.fs` | `client.Group().FS()` | POSIX 风格群文件系统;`ls/find/stat/lstat/mkdir/rm/cp/mv/df/mount/umount`,以及 `set_acl/remove_acl/get_acl/list_acl` 角色 ACL 门面,上传下载数据面由 SDK 编排 |
334
378
 
379
+ 四个 SDK 的 Storage VFS 与 Group FS 上传门面在未显式指定 `content_type` / `contentType` 时,先按实际字节识别 PNG、JPEG、GIF、BMP、WebP、PDF、gzip、ZIP、MP4、JSON、HTML 和 UTF-8 文本,再回退文件扩展名及 `application/octet-stream`。session 上传会把同一 MIME 值用于 create session、HTTP PUT 的 `Content-Type` 和 complete;session 响应中的其它 header 会保留,Content-Type 会替换为该 MIME。OSS 预签名 URL 会校验签名头,应用绕过 VFS 时缺少或改写该请求头可能直接收到 OSS 403。
380
+
335
381
  群文件系统路径统一使用 `group_aid:/...`,成员数据区使用 `group_aid:/memberdata/{member_ref}/...`。SDK 不拼接真实 storage 路径,`memberdata` 到成员 `group_data/{group_aid}` 的映射只在服务端完成。群自有区写入允许当前 `group_aid` 证书签名;成员角色中 `owner/admin` 默认可写群自有区,`member` 默认不可写。`owner/admin` 可通过 `group.fs.set_acl` 对特定业务目录授予 `role:member` 的 `rw` 权限,用于后续群协作场景;`rw` 只允许创建/写入,不授予删除、移动、重命名权限。`rwd` 是 storage 内部权限位,SDK/RPC 对外按 POSIX 视图显示为 `rwx`,不给删除/移动/重命名权限时只使用 `rw`。`.group/` 是系统控制目录,默认给 `owner/admin` 写权限,用于群公告、群规则、入群要求附件,不能向 `role:member` 授权。老群如果缺少 `.group/` 默认 ACL,group 服务会在该群首次被 RPC 访问时 best-effort 触发 namespace/ACL lazy repair;ACL 同步全部成功后才记录本进程已检查,失败会在后续访问继续重试。JS 浏览器版上传中 `string` 默认表示文本内容,Node 本地路径需显式 `sourceType: "path"`、`localPath: true` 或 `local:` 前缀;Python/TS/Go 默认把 `string` 当本地路径。
336
382
 
337
383
  ### 消息与群组门面
@@ -348,6 +394,17 @@ headers = client.get_protected_headers()
348
394
  `message.history` 和 `group.history` 使用 `before_seq` 排他上界向左翻页,下一页直接使用响应的 `next_before_seq`。History 只读,不推进实时 A/T/H、不 ACK、不触发实时消息事件。实时 Push 的最新页同步完全由 SDK 内部自动执行,再按 A/T/H 决定是否补一页 Forward;没有需要应用调用的 Tail 方法或参数。
349
395
 
350
396
  消息回调只提供页级语义:单个 Tail/Forward 响应页内按 seq 升序、同 seq 最多一次;跨 Push/Tail/Forward 页可能重复或乱序。A/T/H 不能用于判断某条消息是否已经回调。全局去重与排序不是 SDK 业务逻辑保证;应用仓库应以 `(namespace, message_id)` 做唯一键,并按 `seq` 排序。SDK 的进程内折叠仅是 best-effort 优化。
397
+
398
+ **群成员管理与状态方法**:
399
+
400
+ | 语义 | Python | TS/JS | Go |
401
+ |------|--------|-------|----|
402
+ | 屏蔽/取消屏蔽 | `block()` / `unblock()` | `block()` / `unblock()` | `Block()` / `Unblock()` |
403
+ | 获取屏蔽列表 | `get_blocklist()` | `getBlocklist()` | `GetBlocklist()` |
404
+ | 上报自己的群内状态 | `report_status()` | `reportStatus()` | `ReportStatus()` |
405
+ | 获取所有成员状态 | `get_member_statuses()` | `getMemberStatuses()` | `GetMemberStatuses()` |
406
+
407
+ 屏蔽与禁言相互独立且可以同时设置。屏蔽成员仍可向群发送消息,但不接收群消息;禁言成员不能向群发送消息,但仍可接收。群主转让是两阶段流程:旧群主先生成授权并调用 `group.transfer_owner`,新群主 SDK 收到 `owner_transfer_rekey_pending` 后生成新群密钥并调用 `group.complete_transfer`。四个 SDK 会在新群主在线或重连恢复时自动尝试第二阶段,也保留 `completeTransfer`(Python 为 `complete_transfer`,Go 为 `CompleteTransfer`)供显式恢复;发起调用返回 `pending_rekey`,不表示转让已经完成。
351
408
 
352
409
  **群查询方法**:`GroupFacade` 提供三个查询方法,适用不同场景:
353
410
 
@@ -746,6 +803,8 @@ sub.unsubscribe()
746
803
  | `push.offline_message` | Push Server 收到离线唤醒批次;普通终端无需订阅 |
747
804
  | `storage.object_changed` | Storage 对象变更事件透传 |
748
805
 
806
+ `message.received` 的应用层消息保留 `sender_device_id`,表示发送方设备;需要只回复原设备时,将该值作为下一次 `message.send.device_id`。volatile 消息还保留 `storage="volatile"`、`volatile_cursor`、`created_at`、`expires_at`,不含持久 `seq`;内部 slot 不会暴露给应用。
807
+
749
808
  ### delivery.changed
750
809
 
751
810
  `delivery.changed` 是 Python、Go、JavaScript 和 TypeScript SDK 统一提供的本地事件,用于通知应用层一批消息已经完成交付,可以从业务仓库刷新相关会话 UI。它不替代 `message.received` / `group.message_created`:应用仍应逐条处理和持久化原消息事件,再把 `delivery.changed` 作为批量刷新信号。
@@ -29,10 +29,13 @@ AUNError
29
29
  Result 格式:
30
30
 
31
31
  ```python
32
- loaded = store.load("alice.agentid.pub")
33
- if not loaded["ok"]:
34
- print(loaded["error"]["code"], loaded["error"]["message"])
35
- ```
32
+ loaded = store.load("alice.agentid.pub")
33
+ if not loaded["ok"]:
34
+ print(loaded["error"]["code"], loaded["error"]["message"])
35
+ print(loaded.error.cause)
36
+ ```
37
+
38
+ Python `ErrorInfo.cause` 保存 SDK 捕获到的本地原始异常,供诊断或异常类型判断使用。它不会进入 `ErrorInfo.to_dict()` / `Result.to_dict()`,因此不能通过 `loaded["error"]["cause"]` 读取,也不会进入序列化结果。
36
39
 
37
40
  异常属性:
38
41
 
@@ -38,13 +38,19 @@
38
38
  | [group.get_members](#groupget_members) | 获取成员列表 |
39
39
  | [group.kick](#groupkick) | 踢出成员 |
40
40
  | [group.leave](#groupleave) | 主动退群 |
41
- | [group.set_role](#groupset_role) | 设置角色 |
42
- | [group.transfer_owner](#grouptransfer_owner) | 转让群主 |
43
- | [group.bind_group_aid](#groupbind_group_aid) | 为匿名群绑定群身份 |
41
+ | [group.set_role](#groupset_role) | 设置角色 |
42
+ | [group.transfer_owner](#grouptransfer_owner) | 转让群主 |
43
+ | [group.complete_transfer](#groupcomplete_transfer) | 完成群主转让与群身份换钥 |
44
+ | [group.bind_group_aid](#groupbind_group_aid) | 为匿名群绑定群身份 |
44
45
  | [group.renew_group_aid](#grouprenew_group_aid) | 轮换群身份密钥 |
45
- | [group.ban](#groupban) | 封禁成员 |
46
- | [group.unban](#groupunban) | 解封成员 |
47
- | [group.get_banlist](#groupget_banlist) | 获取封禁列表 |
46
+ | [group.ban](#groupban) | 封禁成员 |
47
+ | [group.unban](#groupunban) | 解封成员 |
48
+ | [group.get_banlist](#groupget_banlist) | 获取封禁列表 |
49
+ | [group.block](#groupblock) | 屏蔽成员接收群消息 |
50
+ | [group.unblock](#groupunblock) | 取消屏蔽 |
51
+ | [group.get_blocklist](#groupget_blocklist) | 获取屏蔽列表 |
52
+ | [group.report_status](#groupreport_status) | 上报自己的群内状态 |
53
+ | [group.get_member_statuses](#groupget_member_statuses) | 获取群成员状态列表 |
48
54
 
49
55
  ### 入群流程
50
56
 
@@ -161,7 +167,9 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
161
167
 
162
168
  ### group.create
163
169
 
164
- 创建群组。调用者自动成为 owner。支持创建命名群(传入 `group_name` + `public_key`)。新建群主标识以 `group_aid` 为准;`group_id` 仅作为兼容字段保留。
170
+ 创建群组。调用者自动成为 owner。支持创建命名群(传入 `group_name` + `public_key`)。新建群主标识以 `group_aid` 为准;`group_id` 仅作为兼容字段保留。
171
+
172
+ 四种 SDK 的高层建群接口均支持崩溃恢复。命名群在 RPC 前持久化群密钥,并按 `group_name + public_key` 重放已提交结果;匿名群在 RPC 前持久化群密钥和创建上下文,重试会取回同一数字群并继续 `group_aid` 证书绑定与 `agent.md` 上传。群记录、群主成员、成员索引、入群设置、首个 `group.changed` 事件及匿名创建映射由服务端在同一数据库事务提交;证书服务和存储服务不参与该数据库事务,由 SDK pending 状态和服务端幂等重放恢复。
165
173
 
166
174
  **参数**:
167
175
 
@@ -347,7 +355,7 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
347
355
 
348
356
  ### group.suspend
349
357
 
350
- 暂停群组。暂停期间不能发送消息。需要 **admin 及以上**权限。
358
+ 暂停群组。暂停期间 owner/admin 可以继续通过 `group.send`、`group.v2.send` 和 `group.thought.put` 发言;member 禁止发言,入群、邀请、申请审批等准入操作继续拒绝。需要 **admin 及以上**权限。
351
359
 
352
360
  **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`)
353
361
 
@@ -530,26 +538,72 @@ SDK 发起 `group.*` 调用时会把传入的 `group_id` / `groupId` / `group_ai
530
538
  }
531
539
  ```
532
540
 
533
- ### group.transfer_owner
534
-
535
- 转让群主。需要 owner 权限。原 owner 转为 admin。
541
+ ### group.transfer_owner
542
+
543
+ 发起两阶段群主转让。需要 owner 权限;该调用只记录待换钥状态,不会立即变更群主。新群主完成 `group.complete_transfer` 后,原 owner 才转为 admin。
536
544
 
537
545
  **参数**:
538
546
 
539
547
  | 参数 | 类型 | 必填 | 说明 |
540
- |------|------|------|------|
541
- | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
542
- | `new_owner` | string | 是 | 新群主 AID(也接受 `aid`) |
548
+ |------|------|------|------|
549
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
550
+ | `group_aid` | string | 否 | 群身份;高层 SDK 会查询并补齐 |
551
+ | `new_owner` | string | 是 | 新群主 AID(也接受 `aid`) |
552
+ | `transfer_auth` | object | 是 | 旧群主使用当前 group_aid 私钥签名的授权,包含 `nonce`、`issued_ms`、`signature` |
543
553
 
544
554
  **响应**:
545
555
 
546
556
  ```json
547
- {
548
- "group": { ... },
549
- "old_owner": "alice.agentid.pub",
550
- "new_owner": "bob.agentid.pub"
551
- }
552
- ```
557
+ {
558
+ "status": "pending_rekey",
559
+ "requires_ca_rekey": true,
560
+ "complete_rpc": "group.complete_transfer",
561
+ "group": { ... },
562
+ "group_id": "team.agentid.pub",
563
+ "group_aid": "team.agentid.pub",
564
+ "old_owner": "alice.agentid.pub",
565
+ "new_owner": "bob.agentid.pub",
566
+ "pending_owner_transfer": {
567
+ "status": "pending_rekey",
568
+ "old_owner": "alice.agentid.pub",
569
+ "new_owner": "bob.agentid.pub",
570
+ "group_aid": "team.agentid.pub",
571
+ "transfer_auth": { ... }
572
+ }
573
+ }
574
+ ```
575
+
576
+ 四语言 SDK 会在新群主在线收到 `owner_transfer_rekey_pending` 事件,或重连发现本地 pending 状态时自动尝试完成转让。发起方的高层转让方法返回上述 `pending_rekey`,不会等待新群主完成。Python / TypeScript / JavaScript 门面需要传入 `aid_store` / `aidStore` 才执行签名编排;Go 的高层发起入口为 `AUNClient.StartGroupTransfer`,`GroupFacade.TransferOwner` 当前是原始 RPC 门面。
577
+
578
+ ### group.complete_transfer
579
+
580
+ 由 pending 中的新群主完成群身份换钥和所有权切换。成功后响应状态为 `transferred`,新群主成为 owner,原群主转为 admin。
581
+
582
+ **参数**:
583
+
584
+ | 参数 | 类型 | 必填 | 说明 |
585
+ |------|------|------|------|
586
+ | `group_id` | string | 是 | 群组标识;兼容字段,值语义为目标态 `group_aid` |
587
+ | `group_aid` | string | 否 | 群身份;高层 SDK 会查询并补齐 |
588
+ | `public_key` | string | 是 | 新 group_aid 公钥 DER base64(SPKI 格式) |
589
+ | `curve` | string | 否 | 曲线名称,默认 `P-256` |
590
+ | `transfer_accept` | object | 是 | 新群主使用自身 AID 私钥签名的接受证明,包含 `nonce`、`issued_ms`、`signature` |
591
+
592
+ **响应**:
593
+
594
+ ```json
595
+ {
596
+ "status": "transferred",
597
+ "group": { ... },
598
+ "group_id": "team.agentid.pub",
599
+ "group_aid": "team.agentid.pub",
600
+ "old_owner": "alice.agentid.pub",
601
+ "new_owner": "bob.agentid.pub",
602
+ "aid_cert": { "cert": "-----BEGIN CERTIFICATE-----..." }
603
+ }
604
+ ```
605
+
606
+ 高层 SDK 会生成并暂存新群身份密钥,签名 `transfer_accept`,成功后导入新的 group_aid 身份;重复提交同一已完成转让时,服务端可幂等返回已完成结果。
553
607
 
554
608
  ### group.bind_group_aid
555
609
 
@@ -704,7 +758,7 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
704
758
  }
705
759
  ```
706
760
 
707
- ### group.get_banlist
761
+ ### group.get_banlist
708
762
 
709
763
  获取封禁列表。需要 **admin 及以上**权限。
710
764
 
@@ -728,10 +782,88 @@ aun-group-aid-renew-v1|{group_id}|{group_aid}|{sha256(old_public_key)}|{sha256(n
728
782
  "total": 1,
729
783
  "page": 1,
730
784
  "size": 200
731
- }
732
- ```
733
-
734
- ---
785
+ }
786
+ ```
787
+
788
+ 禁言与屏蔽是两个独立状态,可以同时设置。禁言成员仍能接收群消息,但不能发送;屏蔽成员仍能发送群消息,但不再收到该群的实时消息 Push、离线消息 Push、Pull 或 E2EE wrap。
789
+
790
+ ### group.block
791
+
792
+ 屏蔽成员接收群消息。owner/admin 可以屏蔽其权限范围内的成员;所有成员都可以屏蔽自己。屏蔽只影响接收,不影响该成员向群内发送消息,也不改变已有禁言状态。
793
+
794
+ **参数**:`group_id`(string,必填;兼容字段,值使用目标态 `group_aid`),`subject` 或 `aid`(string,必填;传入自己的 AID 即可屏蔽自己),`reason`(string,可选)。
795
+
796
+ **响应**:
797
+
798
+ ```json
799
+ {
800
+ "group_id": "g-abc123.agentid.pub",
801
+ "group_aid": "g-abc123.agentid.pub",
802
+ "block": {
803
+ "group_id": "g-abc123.agentid.pub",
804
+ "subject": "bob.agentid.pub",
805
+ "blocked_by": "alice.agentid.pub",
806
+ "reason": "暂不接收群消息",
807
+ "created_at": 1234567890000
808
+ }
809
+ }
810
+ ```
811
+
812
+ ### group.unblock
813
+
814
+ 取消屏蔽。owner/admin 可以取消其权限范围内成员的屏蔽;所有成员都可以取消自己的屏蔽。取消屏蔽不改变禁言状态。
815
+
816
+ **参数**:`group_id`(string,必填),`subject` 或 `aid`(string,必填;传入自己的 AID 即可取消自己的屏蔽)。
817
+
818
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "subject": "bob.agentid.pub", "status": "removed" }`
819
+
820
+ ### group.get_blocklist
821
+
822
+ 获取群屏蔽列表。需要 **admin 及以上**权限。
823
+
824
+ **参数**:`group_id`(string,必填)
825
+
826
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "items": [ ... ], "total": 1, "page": 1, "size": 1 }`
827
+
828
+ 每个条目包含 `group_id`、`subject`、`blocked_by`、`reason` 和 `created_at`。
829
+
830
+ ### group.report_status
831
+
832
+ 上报当前成员在指定群内的在线状态和工作状态。调用者只能上报自己的状态;`updated_at` 由服务端记录。消息发送成功后,服务端独立维护该成员的 `last_message_at` 和 `last_payload_type`。
833
+
834
+ **参数**:`group_id`(string,必填),`online_status`(string,必填),`work_status`(string,必填)。
835
+
836
+ **响应**:`{ "group_id": "g-abc123.agentid.pub", "group_aid": "g-abc123.agentid.pub", "status": { ... } }`
837
+
838
+ ### group.get_member_statuses
839
+
840
+ 查询群内所有成员状态。调用者必须是群成员。响应始终以数组返回,并包含尚未上报状态的成员。
841
+
842
+ **参数**:`group_id`(string,必填)
843
+
844
+ **响应**:
845
+
846
+ ```json
847
+ {
848
+ "group_id": "g-abc123.agentid.pub",
849
+ "group_aid": "g-abc123.agentid.pub",
850
+ "items": [
851
+ {
852
+ "group_id": "g-abc123.agentid.pub",
853
+ "aid": "alice.agentid.pub",
854
+ "online_status": "online",
855
+ "work_status": "busy",
856
+ "updated_at": 1234567890000,
857
+ "last_message_at": 1234567890123,
858
+ "last_payload_type": "text"
859
+ }
860
+ ]
861
+ }
862
+ ```
863
+
864
+ `online_status` 和 `work_status` 是成员上报值;未上报时为空字符串。`last_message_at` 为该成员在此群最后一条成功发送消息的时间,`last_payload_type` 为该消息的 `payload.type`;没有历史消息时分别为 `0` 和空字符串。
865
+
866
+ ---
735
867
 
736
868
  ## 入群流程
737
869
 
@@ -1113,7 +1245,7 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
1113
1245
 
1114
1246
  ### group.send
1115
1247
 
1116
- 发送群消息。需要 member 权限。
1248
+ 发送群消息。需要 member 权限。群为 `suspended` 时仅 owner/admin 可以发送,member 会被拒绝。
1117
1249
 
1118
1250
  群消息的持久化 `mention_mode` 来自群设置,取值为 `"disabled"` / `"mention-only"`;服务端会写入消息对象并在 pull / push 中返回。运行时是否广播全员或分发给值班 Agent,由响应中的 `dispatch` / `message_dispatch` 描述。V2 加密消息把快照放在既有 `envelope_json` 元数据中,不改变 `per_device` 投递列。
1119
1251
 
@@ -1179,7 +1311,7 @@ SDK 观察到 `_meta.group_indexes` 只记录远端 etag,不会自动覆盖本
1179
1311
 
1180
1312
  ### group.thought.put
1181
1313
 
1182
- 写入某个发送者针对一个群上下文的思考内容。该内容不是普通群消息:服务端不分配消息 `seq`,不广播,不进入 `group.pull`,不需要 ack,也不持久化;只在内存中保留当前 head。
1314
+ 写入某个发送者针对一个群上下文的思考内容。该内容不是普通群消息:服务端不分配消息 `seq`,不广播,不进入 `group.pull`,不需要 ack,也不持久化;只在内存中保留当前 head。群为 `suspended` 时仅 owner/admin 可以写入,member 会被拒绝。
1183
1315
 
1184
1316
  SDK 调用时必须走群组 E2EE。应用层传入明文 `payload`,SDK 会加密成 V2 `e2ee.group_encrypted` 信封、补齐 `thought_id` / `timestamp`,并附加 `client_signature`。裸 WebSocket 客户端若绕过 SDK,至少必须自行完成 V2 envelope、`sender_signature`、AAD 和 state commitment 生成;`client_signature` 按 Gateway 连接级身份语义携带。
1185
1317
 
@@ -1502,7 +1634,7 @@ SDK Group FS 门面使用票据执行 HTTP GET 并校验 sha256。应用自行
1502
1634
 
1503
1635
  ### group.fs.create_upload_session
1504
1636
 
1505
- 创建上传会话。参数同 `check_upload`。响应包含 `upload_url`、`session_id`、可选 `headers`。SDK 使用该 URL 执行 HTTP PUT。
1637
+ 创建上传会话。参数同 `check_upload`。响应透传 Storage session 字段并增加 Group FS 路径视图,包含 `upload_url`、`content_type`、`size_bytes` 等;当前 Storage 服务不返回 `session_id` 或 `headers`。四个 SDK 的 Group FS 门面会按实际字节识别 MIME,并在 session、HTTP PUT 与 complete 中保持 `Content-Type` 一致;若 session 返回 headers,SDK 保留其它 header 并替换其中的 Content-Type,避免 OSS 签名不一致导致 403。
1506
1638
 
1507
1639
  ### group.fs.complete_upload
1508
1640
 
@@ -1805,8 +1937,9 @@ SDK 交付给应用层的群事件信封字段统一放在 `envelope`。0.5.x
1805
1937
  | `member_added` | 成员加入 |
1806
1938
  | `member_left` | 成员退出 |
1807
1939
  | `member_removed` | 成员被踢出 |
1808
- | `role_changed` | 角色变更 |
1809
- | `owner_transferred` | 群主转让 |
1940
+ | `role_changed` | 角色变更 |
1941
+ | `owner_transfer_rekey_pending` | 群主转让已发起,等待新群主完成群身份换钥 |
1942
+ | `owner_transferred` | 群主转让 |
1810
1943
  | `rules_updated` | 规则更新 |
1811
1944
  | `announcement_updated` | 公告更新 |
1812
1945
  | `join_requested` | 收到入群申请 |
@@ -1817,8 +1950,10 @@ SDK 交付给应用层的群事件信封字段统一放在 `envelope`。0.5.x
1817
1950
  | `invite_code_created` | 邀请码创建 |
1818
1951
  | `invite_code_used` | 邀请码使用 |
1819
1952
  | `invite_code_revoked` | 邀请码撤销 |
1820
- | `member_banned` | 成员封禁 |
1821
- | `member_unbanned` | 成员解封 |
1953
+ | `member_banned` | 成员封禁 |
1954
+ | `member_unbanned` | 成员解封 |
1955
+ | `member_blocked` | 成员被屏蔽 |
1956
+ | `member_unblocked` | 成员取消屏蔽 |
1822
1957
  | `suspended` | 群组暂停 |
1823
1958
  | `resumed` | 群组恢复 |
1824
1959
  | `dissolved` | 群组解散 |
@@ -2017,6 +2152,3 @@ Group 服务定义了以下专用错误码(-33xxx 段):
2017
2152
  | -33009 | Resource request not found | 检查 request_id |
2018
2153
 
2019
2154
  > SDK 客户端将 -33001 映射为 `GroupNotFoundError`,-33002~-33003 映射为 `GroupStateError`,其余映射为 `GroupError`。未识别的错误码 fallback 到 `AUNError`。
2020
-
2021
-
2022
-