@agentunion/fastaun-browser 0.5.0 → 0.5.1

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 (116) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/_packed_docs/CHANGELOG-validators.md +144 -0
  3. package/_packed_docs/CHANGELOG.md +56 -0
  4. package/_packed_docs/INDEX.md +198 -181
  5. package/_packed_docs/KITE_DOCS_GUIDE.md +26 -23
  6. package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +4 -3
  7. package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +331 -0
  8. package/_packed_docs/protocol/08-AUN-E2EE-Group.md +296 -902
  9. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +64 -114
  10. package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +7 -1
  11. package/_packed_docs/protocol/16-/347/263/273/347/273/237/347/233/256/345/275/225/344/277/235/346/212/244/346/226/271/346/241/210.md +177 -0
  12. package/_packed_docs/protocol/README.md +2 -1
  13. package/_packed_docs/protocol/index.md +8 -3
  14. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +4 -252
  15. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +483 -457
  16. package/_packed_docs/sdk/09-collab-rpc-manual.md +581 -550
  17. package/_packed_docs/sdk/09-group-rpc-manual.md +248 -335
  18. package/_packed_docs/sdk/09-storage-rpc-manual.md +56 -19
  19. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +13 -13
  20. package/_packed_docs/sdk/INDEX.md +14 -14
  21. package/dist/bundle.js +1560 -1159
  22. package/dist/client/delivery.d.ts +13 -2
  23. package/dist/client/delivery.d.ts.map +1 -1
  24. package/dist/client/delivery.js +251 -46
  25. package/dist/client/delivery.js.map +1 -1
  26. package/dist/client/group-state.d.ts.map +1 -1
  27. package/dist/client/group-state.js +36 -14
  28. package/dist/client/group-state.js.map +1 -1
  29. package/dist/client/lifecycle.js +2 -2
  30. package/dist/client/lifecycle.js.map +1 -1
  31. package/dist/client/rpc-pipeline.d.ts +1 -0
  32. package/dist/client/rpc-pipeline.d.ts.map +1 -1
  33. package/dist/client/rpc-pipeline.js +166 -50
  34. package/dist/client/rpc-pipeline.js.map +1 -1
  35. package/dist/client/v2-e2ee.d.ts +14 -1
  36. package/dist/client/v2-e2ee.d.ts.map +1 -1
  37. package/dist/client/v2-e2ee.js +300 -121
  38. package/dist/client/v2-e2ee.js.map +1 -1
  39. package/dist/client.d.ts +5 -4
  40. package/dist/client.d.ts.map +1 -1
  41. package/dist/client.js +187 -46
  42. package/dist/client.js.map +1 -1
  43. package/dist/collab/client.d.ts +8 -0
  44. package/dist/collab/client.d.ts.map +1 -1
  45. package/dist/collab/client.js +12 -0
  46. package/dist/collab/client.js.map +1 -1
  47. package/dist/errors.d.ts +0 -20
  48. package/dist/errors.d.ts.map +1 -1
  49. package/dist/errors.js +8 -51
  50. package/dist/errors.js.map +1 -1
  51. package/dist/facades.d.ts +9 -4
  52. package/dist/facades.d.ts.map +1 -1
  53. package/dist/facades.js +192 -31
  54. package/dist/facades.js.map +1 -1
  55. package/dist/group-fs.d.ts +17 -0
  56. package/dist/group-fs.d.ts.map +1 -1
  57. package/dist/group-fs.js +54 -11
  58. package/dist/group-fs.js.map +1 -1
  59. package/dist/group-id.d.ts +9 -12
  60. package/dist/group-id.d.ts.map +1 -1
  61. package/dist/group-id.js +41 -63
  62. package/dist/group-id.js.map +1 -1
  63. package/dist/index.d.ts +4 -2
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +4 -1
  66. package/dist/index.js.map +1 -1
  67. package/dist/keystore/index.d.ts +2 -54
  68. package/dist/keystore/index.d.ts.map +1 -1
  69. package/dist/keystore/indexeddb-identity-store.d.ts +3 -0
  70. package/dist/keystore/indexeddb-identity-store.d.ts.map +1 -1
  71. package/dist/keystore/indexeddb-identity-store.js +65 -0
  72. package/dist/keystore/indexeddb-identity-store.js.map +1 -1
  73. package/dist/keystore/indexeddb-shared.d.ts +3 -17
  74. package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
  75. package/dist/keystore/indexeddb-shared.js +4 -47
  76. package/dist/keystore/indexeddb-shared.js.map +1 -1
  77. package/dist/keystore/indexeddb-token-store.d.ts +1 -64
  78. package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
  79. package/dist/keystore/indexeddb-token-store.js +45 -774
  80. package/dist/keystore/indexeddb-token-store.js.map +1 -1
  81. package/dist/logger.d.ts +2 -0
  82. package/dist/logger.d.ts.map +1 -1
  83. package/dist/logger.js +4 -0
  84. package/dist/logger.js.map +1 -1
  85. package/dist/storage/lowlevel.d.ts +9 -1
  86. package/dist/storage/lowlevel.d.ts.map +1 -1
  87. package/dist/storage/lowlevel.js +12 -1
  88. package/dist/storage/lowlevel.js.map +1 -1
  89. package/dist/storage/vfs.d.ts +22 -0
  90. package/dist/storage/vfs.d.ts.map +1 -1
  91. package/dist/storage/vfs.js +54 -0
  92. package/dist/storage/vfs.js.map +1 -1
  93. package/dist/tools/cross-sdk-agent.js +336 -49
  94. package/dist/tools/cross-sdk-agent.js.map +1 -1
  95. package/dist/transport.d.ts +2 -0
  96. package/dist/transport.d.ts.map +1 -1
  97. package/dist/transport.js +96 -3
  98. package/dist/transport.js.map +1 -1
  99. package/dist/types.d.ts +39 -56
  100. package/dist/types.d.ts.map +1 -1
  101. package/dist/v2/session/session.d.ts +2 -0
  102. package/dist/v2/session/session.d.ts.map +1 -1
  103. package/dist/v2/session/session.js +58 -22
  104. package/dist/v2/session/session.js.map +1 -1
  105. package/dist/v2/state/commitment.d.ts +1 -1
  106. package/dist/v2/state/commitment.d.ts.map +1 -1
  107. package/dist/v2/state/commitment.js +5 -3
  108. package/dist/v2/state/commitment.js.map +1 -1
  109. package/dist/validators.d.ts +35 -0
  110. package/dist/validators.d.ts.map +1 -0
  111. package/dist/validators.js +127 -0
  112. package/dist/validators.js.map +1 -0
  113. package/dist/version.d.ts +1 -1
  114. package/dist/version.js +1 -1
  115. package/package.json +1 -1
  116. package/_packed_docs/collab-gateway-boundary-test-report.md +0 -164
@@ -44,25 +44,31 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
44
44
 
45
45
  ### Group ID 格式与规范化
46
46
 
47
- `group_id` 是群组的全网唯一标识,前缀 `g-` 为 Group 保留前缀。普通 AID 的本地名称不得以 `g-` 开头,避免与群 ID 混淆。短形式必须以 `g-` 开头,总长度 6 到 16 字符;`g-` 后面的 slug 为 4 到 14 位,只能使用小写字母和数字。
47
+ `group_id` 是群组的全网唯一标识,前缀 `g-` 为 Group 保留前缀(legacy 格式)。普通 AID 的本地名称不得以 `g-` 开头,避免与群 ID 混淆。
48
48
 
49
- 服务端必须接受以下三种输入形式,并在内部统一为 canonical group_id:
49
+ **支持的 base 格式**(不含域名部分):
50
+ - **Legacy 格式**: `g-[a-z0-9]{4,32}` — 以 `g-` 开头,后接 4 到 32 位小写字母或数字
51
+ - **新格式**: `[a-z0-9]{5,}` — 5 位或更多小写字母或数字,无上限
52
+ - **Group name 格式**: `[a-z0-9][a-z0-9_-]{3,63}` — 4 到 64 个字符,可包含下划线和短横线
53
+
54
+ 服务端必须接受以下输入形式,并在内部统一为 canonical group_id:
50
55
 
51
56
  | 输入形式 | 用途 | canonical 结果 |
52
57
  |----------|------|----------------|
53
- | `g-{slug}` | 本地域内简写别名 | 若本域 issuer 为 `issuer-domain`,规范化为 `g-{slug}.issuer-domain` |
54
- | `g-{slug}@issuer-domain` | 跨域传播兼容形式 | 规范化为 `g-{slug}.issuer-domain` |
55
- | `g-{slug}.issuer-domain` | canonical 形式 | 保持为 `g-{slug}.issuer-domain` |
58
+ | `{base}` | 本地域内简写(base 为上述任一格式) | 若本域 issuer 为 `issuer-domain`,规范化为 `group.issuer-domain/{base}` |
59
+ | `{base}@issuer-domain` | 跨域传播兼容形式 | 规范化为 `group.issuer-domain/{base}` |
60
+ | `{base}.issuer-domain` | canonical 形式 | 规范化为 `group.issuer-domain/{base}` |
61
+ | `group.issuer-domain/{base}` | 新 canonical 形式 | 保持为 `group.issuer-domain/{base}` |
56
62
 
57
63
  规范化规则:
58
64
 
59
- - `group_id` 比较、数据库存储、成员归属、权限校验、E2EE AAD / 签名输入均必须使用 canonical group_id
60
- - 输入必须先 trim 并转换为小写;`@issuer-domain` 形式仅作为兼容输入,进入内部前必须转换为 `.issuer-domain`。
61
- - 本域内客户端可以提交 `g-{slug}` 简写;服务端按本域 `AUN_ISSUER_DOMAIN` 解析为 canonical group_id。没有本域 issuer 配置时,简写保持为 `g-{slug}`。
65
+ - `group_id` 比较、数据库存储、成员归属、权限校验、E2EE AAD / 签名输入均必须使用 canonical group_id(`group.{issuer}/{base}` 格式)。
66
+ - 输入必须先 trim 并转换为小写;`@issuer-domain` `.issuer-domain` 形式仅作为兼容输入,进入内部前必须转换为 `group.{issuer}/{base}`。
67
+ - 本域内客户端可以提交 `{base}` 简写;服务端按本域 `AUN_ISSUER_DOMAIN` 解析为 canonical group_id。没有本域 issuer 配置时,简写保持为 `{base}`。
62
68
  - 跨域消息、邀请传播、日志和协议响应应使用 canonical group_id,避免远端误把短 ID 当成本域群。
63
69
  - `group.create` 可以指定 `group_id`;指定时必须满足上述格式且未被占用,被占用时返回错误。未指定时由服务端自动分配。
64
- - 自动生成的群 ID 使用 `g-` 加随机小写十六进制短 slug,服务端必须通过唯一约束或等效机制保证 canonical group_id 唯一;发现碰撞时重新生成。
65
- - 在 `group.{issuer-domain}` 这类已携带 issuer 的公开 HTTP 主机下,生成的群链接 path 应使用本域简写,例如 `https://group.issuer-domain/g-abc123` 或 `https://group.issuer-domain/g-abc123/invite/ic-xxx`。
70
+ - 自动生成的群 ID 使用随机小写十六进制短字符串(长度 14),服务端必须通过唯一约束或等效机制保证 canonical group_id 唯一;发现碰撞时重新生成。
71
+ - 在 `group.{issuer-domain}` 这类已携带 issuer 的公开 HTTP 主机下,生成的群链接 path 应使用本域简写,例如 `https://group.issuer-domain/{base}` 或 `https://group.issuer-domain/{base}/invite/ic-xxx`。
66
72
 
67
73
  ### 10.2.3 群分发模式(dispatch_mode)
68
74
 
@@ -147,7 +153,7 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
147
153
  | 参数 | 类型 | 必填 | 说明 |
148
154
  |------|------|:----:|------|
149
155
  | `name` | string | ✅ | 群组名称 |
150
- | `group_id` | string | ❌ | 自定义群 ID,短形式必须以 `g-` 开头且总长度 6 16 字符;不提供则服务端自动生成;已被占用时返回错误 |
156
+ | `group_id` | string | ❌ | 自定义群 ID,支持 legacy 格式 `g-[a-z0-9]{4,32}` 或新格式 `[a-z0-9]{5,}` group name 格式 `[a-z0-9][a-z0-9_-]{3,63}`;不提供则服务端自动生成;已被占用时返回错误 |
151
157
  | `visibility` | string | ❌ | `"public"` / `"private"`,默认由服务配置决定 |
152
158
  | `description` | string | ❌ | 群组描述 |
153
159
  | `metadata` | object | ❌ | 自定义元数据 |
@@ -176,13 +182,20 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
176
182
  }
177
183
  ```
178
184
 
179
- ### `group.get`
180
-
181
- 查询群组信息。需要是群成员。
182
-
183
- **参数**:`group_id` (string, 必填)
184
-
185
- **响应**:`{ "group": { ... } }`
185
+ ### `group.get_info`
186
+
187
+ 查询群组信息。默认返回公开平铺字段;需要成员信息、状态或 E2EE 字段时,通过 `required` 声明所需字段并由服务端鉴权。
188
+
189
+ **参数**:
190
+
191
+ | 参数 | 类型 | 必填 | 说明 |
192
+ |------|------|:----:|------|
193
+ | `group_id` | string | ✅ | 群组 ID 或 group AID |
194
+ | `required` | string[] | ❌ | 可选值:`member` / `state` / `e2ee` / `avatar` |
195
+
196
+ **响应**:平铺对象。默认字段包含 `found`、`group_id`、`group_aid`、`name`、`visibility`、`status`、`description`、`member_count`、`created_at`。
197
+
198
+ > `group.get` 和 `group.info` 已合并到 `group.get_info`;`group.get_info` 默认行为等价于原公开信息查询。
186
199
 
187
200
  ### `group.update`
188
201
 
@@ -208,23 +221,8 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
208
221
 
209
222
  **响应**:`{ "query": "...", "items": [ ... ], "total": 3 }`
210
223
 
211
- ### `group.get_public_info`
212
-
213
- 查询公开群组信息,无需是成员。仅限 `visibility=public` 的群组。
214
224
 
215
- **参数**:`group_id` (string, 必填)
216
-
217
- **响应**:`{ "group": { ... } }`
218
-
219
- ### `group.get_stats`
220
-
221
- 获取群组统计信息。需要 admin 及以上权限。
222
-
223
- **参数**:`group_id` (string, 必填)
224
-
225
- **响应**:`{ "group_id": "g-abc123.agentid.pub", "stats": { ... } }`
226
-
227
- ### `group.suspend`
225
+ ### `group.suspend`
228
226
 
229
227
  暂停群组,暂停期间不能发送消息。需要 admin 及以上权限。
230
228
 
@@ -475,22 +473,6 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
475
473
 
476
474
  **响应**:`{ "group_id": "g-abc123.agentid.pub", "results": [ ... ] }`
477
475
 
478
- ### `group.get_join_requirements`
479
-
480
- 获取入群要求配置。
481
-
482
- **参数**:`group_id` (string, 必填)
483
-
484
- **响应**:`{ "group_id": "g-abc123.agentid.pub", "requirements": { "mode": "approval", "question": "...", ... } }`
485
-
486
- ### `group.update_join_requirements`
487
-
488
- 更新入群要求配置。需要 admin 及以上权限。
489
-
490
- **参数**:`group_id` (必填), `mode` / `question` / `auto_approve_patterns` / `max_pending` (可选)
491
-
492
- **响应**:`{ "group_id": "g-abc123.agentid.pub", "requirements": { ... } }`
493
-
494
476
  ### `group.create_invite_code`
495
477
 
496
478
  创建邀请码。需要 owner/admin 权限,或群规则允许成员邀请。
@@ -532,69 +514,37 @@ Group 服务是 AUN 协议的应用层扩展,提供多人群组通信能力。
532
514
 
533
515
  ---
534
516
 
535
- ## 10.8 公告与规则
536
-
537
- ### `group.get_announcement`
538
-
539
- 获取群公告。需要是群成员。
540
-
541
- **参数**:`group_id` (string, 必填)
542
-
543
- **响应**:`{ "group_id": "g-abc123.agentid.pub", "announcement": { ... } }`
544
-
545
- ### `group.update_announcement`
546
-
547
- 更新群公告。需要 admin 及以上权限。
548
-
549
- **参数**:`group_id` (必填), `content` (string, 必填,上限默认 4000 字符), `attachments` (array, 可选)
550
-
551
- ### `group.get_rules`
552
-
553
- 获取群规则(可见性设置、加入模式等)。
554
-
555
- **参数**:`group_id` (string, 必填)
556
-
557
- ### `group.update_rules`
558
-
559
- 更新入群要求。需要 admin 及以上权限。
560
-
561
- **参数**:
562
-
563
- | 参数 | 类型 | 必填 | 说明 |
564
- |------|------|:----:|------|
565
- | `group_id` | string | | 群组 ID |
566
- | `mode` | string | ❌ | `"open"` / `"approval"` / `"invite_only"` / `"closed"` |
567
- | `question` | string | ❌ | 入群问题 |
568
- | `auto_approve_patterns` | array | ❌ | 自动批准正则列表 |
569
- | `max_pending` | integer | ❌ | 最大待审批数 |
570
-
571
- ---
572
-
573
- ## 10.9 群文件系统
574
-
575
- 群文件系统统一使用 `group.fs.*`。群路径采用 `group_aid:/path` 或 `https://{group_aid}/path`,也可在 RPC 参数中同时传 `group_id` 与裸路径。群自有区包括 `announce`、`public`、`archive`;成员数据区为 `memberdata/{member_ref}`,服务端映射到成员自己的 `groupdata/{group_id}` 存储根。
576
-
577
- 群自有区写入必须满足双身份规则:连接身份 `_auth.aid` 是群 owner,签名身份 `_auth.client_signature_aid` 是当前 `group_aid`。`group_aid` 私钥由群主持有,gateway 仅允许 `group.fs.*` 出现签名身份与连接身份不一致。成员数据区写入只允许对应成员本人。
578
-
579
- | 方法 | 说明 |
580
- |------|------|
581
- | `group.fs.ls` | 列出目录 |
582
- | `group.fs.find` | 查找节点 |
583
- | `group.fs.stat` | 查看节点 |
584
- | `group.fs.lstat` | 查看链接本身 |
585
- | `group.fs.df` | 查看群文件系统用量 |
586
- | `group.fs.create_download_ticket` | 创建下载票据,SDK 使用票据执行数据面下载 |
587
- | `group.fs.mkdir` | 创建目录 |
588
- | `group.fs.rm` | 删除节点 |
589
- | `group.fs.cp` | group→group 远程复制;本地上传/下载由 SDK 数据面编排 |
590
- | `group.fs.mv` | group→group 远程移动 |
591
- | `group.fs.check_upload` | 上传前检查 |
592
- | `group.fs.create_upload_session` | 创建上传会话 |
593
- | `group.fs.complete_upload` | 完成上传 |
594
- | `group.fs.mount` | 挂载成员数据区 |
595
- | `group.fs.umount` | 卸载成员数据区 |
596
-
597
- 逐方法 SDK 参数以 `docs/sdk/09-group-rpc-manual.md` 为准,详细设计见 `docs/aun-fs/group-fs/`。
517
+ ## 10.8 群文件系统
518
+
519
+ 群文件系统统一使用 `group.fs.*`。群路径采用 `group_aid:/path` 或 `https://{group_aid}/path`,也可在 RPC 参数中同时传 `group_id` 与裸路径。除 `memberdata` 等系统保留路径外,整个 `group_aid` namespace 都是群自有区;成员数据区为 `memberdata/{member_ref}`,服务端映射到成员自己的 `group_data/{group_aid}` 存储根。
520
+
521
+ `memberdata` 是 Group FS 视图层的虚拟系统目录,根节点和成员槽位根不得被普通文件操作删除、覆盖或重命名;成员槽位下的子路径写入只允许对应成员本人通过 `group.fs.*` 完成。完整保护规则见 [16-系统目录保护方案.md](16-系统目录保护方案.md)。
522
+
523
+ 群自有区写权限由角色 ACL 决定:当前 `group_aid` 证书签名可写;`role:owner` 默认可写;`role:admin` 只有在 group owner 通过 `group.fs.set_acl` 显式授权后才可写。授权、撤销和查询的是 `role:admin` 角色策略,不与某个 admin 成员绑定;成员升降级、退群、踢出不会联动 ACL。成员数据区写入只允许对应成员本人。角色 ACL 对外使用 POSIX 权限位,删除权限显示为 `x`。
524
+
525
+ | 方法 | 说明 |
526
+ |------|------|
527
+ | `group.fs.ls` | 列出目录 |
528
+ | `group.fs.find` | 查找节点 |
529
+ | `group.fs.stat` | 查看节点 |
530
+ | `group.fs.lstat` | 查看链接本身 |
531
+ | `group.fs.df` | 查看群文件系统用量 |
532
+ | `group.fs.create_download_ticket` | 创建下载票据,SDK 使用票据执行数据面下载 |
533
+ | `group.fs.set_acl` | owner 授予群自有区 `role:admin` 写 ACL |
534
+ | `group.fs.remove_acl` | owner 撤销群自有区 `role:admin` 写 ACL |
535
+ | `group.fs.get_acl` | owner 查询群自有区角色 ACL |
536
+ | `group.fs.list_acl` | owner 查询群自有区角色 ACL(别名) |
537
+ | `group.fs.mkdir` | 创建目录 |
538
+ | `group.fs.rm` | 删除节点 |
539
+ | `group.fs.cp` | group→group 远程复制;本地上传/下载由 SDK 数据面编排 |
540
+ | `group.fs.mv` | group→group 远程移动 |
541
+ | `group.fs.check_upload` | 上传前检查 |
542
+ | `group.fs.create_upload_session` | 创建上传会话 |
543
+ | `group.fs.complete_upload` | 完成上传 |
544
+ | `group.fs.mount` | 挂载成员数据区 |
545
+ | `group.fs.umount` | 卸载成员数据区 |
546
+
547
+ `group.fs.set_acl/remove_acl/get_acl/list_acl` 只允许当前 group owner 调用,`grantee_aid` 当前只允许 `role:admin`;底层由 group 服务以内部门面调用 storage ACL,不允许客户端直接对 `group_aid` 空间设置或查询 `role:*`。逐方法 SDK 参数以 `docs/sdk/09-group-rpc-manual.md` 为准,详细设计见 `docs/aun-fs/group-fs/`。
598
548
 
599
549
  ---
600
550
 
@@ -741,7 +691,7 @@ Group 服务通过 `event/group.*` 事件推送变更通知给相关 AID。
741
691
  - **消息 seq 单调递增**:per-group 粒度,确保顺序一致性,`ack_seq` 仅增不减。
742
692
  - **事件 seq 独立计数**:`event_seq` 与 `message_seq` 独立;消息增量拉取使用 `group.pull`,事件增量拉取使用 `group.pull_events`。
743
693
  - **duty 模式**:`duty_mode` 非 `"none"` 且 `duty_human_message_policy = "dispatch"` 时,消息先推送给当班成员处理,回复后再广播;`group.pull` 始终可拉取全量消息。
744
- - **群文件系统写边界**:群自有区仅 owner 可写且必须使用 `group_aid` 签名;成员数据区仅对应成员可写。
694
+ - **群文件系统写边界**:群自有区允许当前 `group_aid` 签名、默认 `role:owner`、以及 owner 显式授权后的 `role:admin` 写入;成员数据区仅对应成员可写。
745
695
  - **在线状态**:通过 `group.get_online_members` 查询当前在线成员列表。
746
696
 
747
697
 
@@ -247,7 +247,9 @@ Storage 服务是 AUN 协议的应用层扩展,提供对象存储能力。负
247
247
 
248
248
  ### 11.5.4 ACL / token / 可见性
249
249
 
250
- 统一权限求值顺序(硬顺序,不可调换):① 公开位(`set_visibility`/`is_public`,仅读)→ ② token(`issue_token` 签发,scope 到路径)→ ③ 路径前缀 ACL(`set_acl`,最近祖先匹配,权限位 `r`/`w`/`rw`/`rwx`)→ ④ 角色(群内)→ ⑤ owner → ⑥ 拒绝 `EACCES`。方法:`storage.set_acl` / `remove_acl` / `list_acl` / `set_visibility` / `check_access`(非抛错探测)/ `issue_token` / `revoke_token` / `list_tokens`。
250
+ 统一权限求值顺序(硬顺序,不可调换):① 公开位(`set_visibility`/`is_public`,仅读)→ ② token(`issue_token` 签发,scope 到路径)→ ③ 路径前缀 ACL(`set_acl`,最近祖先匹配,权限位 `r`/`w`/`rw`/`rwx`)→ ④ 角色(群内)→ ⑤ owner → ⑥ 拒绝 `EACCES`。方法:`storage.set_acl` / `remove_acl` / `list_acl` / `set_visibility` / `check_access`(非抛错探测)/ `issue_token` / `revoke_token` / `list_tokens`。
251
+
252
+ AID storage 的 ACL 面向具体 AID,主要用于写/删除授权;撤销写授权使用 `storage.remove_acl`。读权限不通过 AID ACL 直接下发,应用应使用 `storage.create_share_link` / `storage.get_by_share` 间接读取,撤销读分享使用 `storage.revoke_share_link`。`role:*` 伪主体只允许可信 group 内部门面管理;普通客户端不得直接对 `group_aid` 空间设置或删除角色 ACL,群自有区 `role:admin` 写授权统一由 `group.fs.set_acl/remove_acl` 管理。
251
253
 
252
254
  ### 11.5.5 卷与配额
253
255
 
@@ -257,6 +259,10 @@ Storage 服务是 AUN 协议的应用层扩展,提供对象存储能力。负
257
259
 
258
260
  Storage 通过 CA 的 `aid_type` 字段(`normal`/`group`)识别群命名空间。命中 `aid_type=group` 且挂载路径落在 `/memberdata/` 时,放宽 owner 校验,改为调 `group.check_membership` RPC 实时校验成员身份 + 路径约束(mount_path 第一级 == requester_aid)。详见 `10-Group-子协议.md` 与 `docs/aun-fs/topics/group-space.md`。
259
261
 
262
+ 成员个人 Storage 内的 `group_data` 是系统级真实存储根,Storage 服务端必须对普通 `storage.*` / `storage.fs.*` 请求隐藏并拒绝直接写入、删除、重命名或挂载;`aun fs` / Storage VFS 只呈现服务端返回结果,不新增保护逻辑。`group_data` 只能由可信 `group.fs.*` 内部上下文间接访问,占用的空间仍必须计入真实 owner AID 的 Storage 配额。完整规则见 [16-系统目录保护方案.md](16-系统目录保护方案.md)。
263
+
264
+ POSIX VFS 写侧包含 `storage.fs.touch`:它可创建 0 字节文件或刷新已有文件、目录、软链的修改时间,支持 `parents`、`no_create`、`mtime` 和 `follow_symlinks`。这是普通 AID storage 的 VFS 能力;群自有区仍应通过 `group.fs.*` 面进入。
265
+
260
266
  ### 11.5.7 collab 协作编排
261
267
 
262
268
  协作层 `collab.*`(版本化文档 + 目录快照)的编排已并入 Storage 服务进程,handler 与 `storage.*` 并列注册,以调用者身份直调 storage 原语,授权下沉 storage ACL,无特权通道。方法清单与语义见 SDK 手册 `docs/sdk/09-collab-rpc-manual.md`。
@@ -0,0 +1,177 @@
1
+ # 16. 系统目录保护方案
2
+
3
+ ## 16.1 目标
4
+
5
+ `memberdata` 与 `group_data` 是 Group FS 与 Storage 协作使用的系统级目录名。它们不能被当作普通用户目录处理,否则会造成权限绕过、视图层与真实存储层混淆、误删成员数据和配额统计失真。
6
+
7
+ 本方案定义两个目录名的保护规则:
8
+
9
+ - `memberdata`:Group FS 视图层的虚拟协议目录。
10
+ - `group_data`:Storage 真实层的内部协议根目录。
11
+
12
+ 外部用户、SDK、CLI 和普通 `storage.*` / `storage.fs.*` RPC 只能看到业务语义,不应把真实存储根作为应用目录树入口。`group_data` 的存在不是保密目标;保护目标是目录树不展示系统根、普通写入不能绕过 `group.fs.*` 授权路径。
13
+
14
+ ## 16.2 目录分层
15
+
16
+ | 名称 | 所在层 | 示例 | 性质 | 对外可见性 |
17
+ | --- | --- | --- | --- | --- |
18
+ | `memberdata` | Group FS 视图层 | `group_aid:/memberdata/alice.aid/logs/a.md` | 虚拟目录和成员槽位边界 | 在 Group FS 中可见;普通 Storage 面不因目录名隐藏,但写保护 |
19
+ | `group_data` | Storage 真实层 | `member_aid:/group_data/{group_aid}/logs/a.md` | 内部真实存储根 | 普通 Storage 目录树隐藏;读/下载不刻意隐藏;写保护 |
20
+
21
+ `memberdata/{member_ref}` 映射到 `member_aid:/group_data/{group_aid}`。SDK 和 CLI 不得拼接 `group_data`;服务端 group 模块负责视图路径解析,storage 模块负责真实路径保护和配额统计。
22
+
23
+ ## 16.3 总体原则
24
+
25
+ 1. `memberdata` 根和成员槽位不是普通目录,不能被普通文件操作破坏。
26
+ 2. `memberdata` 不是隐藏目录;保护重点是禁止普通 Storage 写入 group AID 命名空间下的 `memberdata/...`。
27
+ 3. `group_data` 是保留真实根,普通 Storage 目录树浏览不展示它,普通 Storage 写入、删除、重命名、挂载、授权和状态变更必须拒绝。
28
+ 4. `group_data` 的对象读取、下载 ticket 和 URL 生成不因路径名被刻意隐藏,但仍必须按普通 read ACL、token、private、owner 规则鉴权。
29
+ 5. `group_data` 占用的空间必须计入真实 owner AID 的 Storage 配额。
30
+ 6. 隐藏和保护只改变可见性与入口,不改变数据归属、配额归属和审计归属。
31
+ 7. 成员数据写入只允许成员本人通过 `group.fs.*` 写自己的槽位子路径。
32
+ 8. `group.fs.*` 不允许删除 `memberdata` 根、成员槽位根或对应的 `group_data/{group_aid}` 根。
33
+
34
+ ## 16.4 `memberdata` 保护规则
35
+
36
+ `memberdata` 在 Group FS 视图中表现为虚拟目录和成员槽位边界。普通 Storage 面不因为路径名是 `memberdata` 而隐藏读、stat 或列表结果;但 group AID 命名空间下的 `memberdata/...` 不能被普通 Storage 写入口直接创建、修改、删除或替换。
37
+
38
+ ### 16.4.1 允许行为
39
+
40
+ | 操作 | 路径 | 结果 |
41
+ | --- | --- | --- |
42
+ | `stat/lstat` | `group_aid:/memberdata` | 返回虚拟目录节点 |
43
+ | `ls` | `group_aid:/memberdata` | 返回成员槽位虚拟节点列表 |
44
+ | `stat/lstat` | `group_aid:/memberdata/{member_ref}` | 返回成员槽位节点 |
45
+ | `ls/find/df` | `group_aid:/memberdata/{member_ref}` | 通过 group 服务映射到成员真实 `group_data/{group_aid}` |
46
+ | `mkdir/cp/mv/rm` | `group_aid:/memberdata/me/path` | 成员本人可操作自己的槽位子路径 |
47
+ | `cp` 下载 | `group_aid:/memberdata/{member_ref}/path` | 合法群成员按读权限下载 |
48
+
49
+ ### 16.4.2 拒绝行为
50
+
51
+ | 操作 | 路径 | 要求 |
52
+ | --- | --- | --- |
53
+ | `mkdir/rm/mv/cp` | `group_aid:/memberdata` | 必须拒绝 |
54
+ | `rm/mv/cp` 覆盖槽位 | `group_aid:/memberdata/{member_ref}` | 必须拒绝,不能删除或替换槽位根 |
55
+ | 写他人槽位 | `group_aid:/memberdata/{other}/path` | 必须拒绝 |
56
+ | 普通 Storage 写 group 空间 `memberdata/...` | `group_aid:/memberdata/...` | 必须拒绝,禁止绕过 group.fs;普通读/列表不因目录名隐藏 |
57
+ | 普通挂载到槽位子路径 | `memberdata/{aid}/subdir` | 必须拒绝,只允许精确槽位根挂载语义 |
58
+
59
+ `rm group_aid:/memberdata/{member_ref}` 不得解释为删除成员真实数据。若需要解除成员槽位挂载,应使用明确的 `group.fs.umount` 或等价控制面语义。
60
+
61
+ ## 16.5 `group_data` 保护规则
62
+
63
+ `group_data` 是成员个人 Storage 内的内部协议根,用于承载该成员在某群的成员数据。它不是普通应用目录。
64
+
65
+ ### 16.5.1 普通 Storage 面行为
66
+
67
+ 普通 `storage.*`、`storage.fs.*`、`aun fs` 和 Storage VFS 对 `group_data` 的处理分三类:
68
+
69
+ - 目录树浏览类入口必须隐藏:`storage.fs.list/find/stat/lstat/resolve/df`、`list_objects`、`list_prefixes`、`list_children`、`get_folder` 等在浏览 owner 目录结构时不得展示 `group_data` 根或其子树;直接指向 `group_data/...` 的树视图请求应返回 not found。
70
+ - 读/下载类入口不刻意隐藏:`get_object`、`head_object`、`get_object_url`、`create_download_ticket`、`check_access(read)` 不应仅因路径位于 `group_data/...` 而返回 not found;它们仍按普通 read ACL、token、private、owner 和群成员读代理规则鉴权。
71
+ - 写入和状态变更类入口必须拒绝:`put_object`、`append_object`、`set_object_meta`、`delete_object`、`check_upload`、`create_upload_session`、`complete_upload`、`mkdir`、`copy`、`move`、`rename`、`remove`、`delete`、`symlink`、`mount`、`set_acl`、`remove_acl`、`set_visibility`、`issue_token`、`revoke_token` 等作用于 `group_data` 或其子路径时必须拒绝,除非请求来自可信 `group.fs.*` 内部授权路径,或来自 `collab.*` 对 `.collab-versions` / `.collab-snapshots` 等协作内部对象的受控写入。
72
+
73
+ `df owner:/` 的总量必须包含 `group_data` 占用;`df owner:/group_data/...` 属于目录树 scoped 浏览,普通请求应返回 not found。
74
+
75
+ 上述隐藏和拒绝由服务端 storage RPC 强制实现;CLI、SDK VFS 和其他客户端只呈现服务端返回结果,不要求实现独立的系统目录识别或保护分支。
76
+
77
+ 对外错误建议:目录树隐藏返回 not found;写入和状态变更拒绝返回权限错误。调试模式或内部审计日志可以记录 reserved path 拒绝原因。
78
+
79
+ ### 16.5.2 Group FS 内部访问
80
+
81
+ 可信 `group.fs.*` 内部调用可以访问 `group_data/{group_aid}`:
82
+
83
+ - `_internal_caller_id == "group.fs"`。
84
+ - `_trusted_internal_caller_id == "group"`。
85
+ - `_group_fs_group_aid` 必须与 `group_data/{group_aid}` 根一致。
86
+ - `_group_fs_storage_owner_aid` 必须是成员 AID。
87
+ - `_group_fs_storage_bucket` 与当前 bucket 匹配。
88
+ - `_group_fs_storage_path` 必须覆盖当前真实路径 scope。
89
+ - 写操作要求 `_group_fs_actor_aid == _group_fs_storage_owner_aid`。
90
+ - 读操作要求 actor 是合法群成员,跨域读取必须通过 group 代理上下文校验。
91
+
92
+ group.fs 内部访问也不能删除 `group_data/{group_aid}` 根本身,只能操作根以下的业务子路径。
93
+
94
+ `collab.*` 只能在已解析的 `collab_root=group_aid:/memberdata/{member_aid}/...` 范围内写入协作内部对象;协作写授权通过 `collab.set_acl/remove_acl` 面向具体 AID 管理,不允许客户端直接调用 `storage.set_acl/remove_acl` 操作 `group_data`。
95
+
96
+ ## 16.6 配额与计费
97
+
98
+ `group_data` 内的所有对象、目录元数据和派生 blob 引用必须计入真实 owner AID 的 Storage 配额。
99
+
100
+ 规则如下:
101
+
102
+ 1. `member_aid:/group_data/{group_aid}/...` 的大小计入 `member_aid`,不计入 `group_aid`。
103
+ 2. group owner、admin 或其他成员通过 group.fs 读取成员数据,不改变配额归属。
104
+ 3. group.fs 上传到 `memberdata/me/...` 时,写前配额检查使用成员本人的 quota。
105
+ 4. `df group_aid:/memberdata/{member_ref}` 可以返回成员槽位视图,但其中 quota 字段必须明确表示真实 owner 是 `member_aid`。
106
+ 5. 普通 `aun fs df member_aid:/` 可以统计 `group_data` 占用,但默认不展示目录名;总量必须包含它。
107
+ 6. 群解散、成员退出或权限变化不会自动把 `group_data` 从配额中排除。
108
+
109
+ 这保证系统目录保护不会变成绕过个人存储限额的通道。
110
+
111
+ ## 16.7 生命周期与删除策略
112
+
113
+ | 场景 | 数据处理 |
114
+ | --- | --- |
115
+ | 成员退出或被踢出群 | 保留其个人 `group_data/{group_aid}` 数据;group.fs 不再允许群内其他成员访问 |
116
+ | 群解散 | 默认不删除成员个人 `group_data/{group_aid}` 数据 |
117
+ | 成员主动清理 | 必须通过明确的成员数据清理流程,不通过普通 Storage 路径暴露 `group_data` |
118
+ | 槽位卸载 | 只移除视图/挂载关系,不删除真实数据 |
119
+ | 管理员清理 | 必须有独立授权和审计,不复用普通文件删除语义 |
120
+
121
+ 如果未来提供“清理某群成员数据”能力,应使用语义化 API,例如 `group.fs.purge_member_data` 或用户侧隐私清理入口,并要求二次确认、审计记录和配额变更事件。
122
+
123
+ ## 16.8 CLI / SDK / RPC 要求
124
+
125
+ ### CLI
126
+
127
+ - `aun fs` 的列表、访问错误和拒绝结果由 `storage.fs.*` 服务端返回决定,不新增专门的 `group_data` 保护逻辑。
128
+ - `aun group fs` 的 `memberdata` 视图和根/槽位根破坏性操作拒绝由 `group.fs.*` 服务端返回决定。
129
+ - 错误消息按通用错误映射呈现,不鼓励用户拼接真实路径。
130
+
131
+ ### SDK VFS
132
+
133
+ - Storage VFS 不新增 `group_data` 特判,继续调用普通 `storage.fs.*`。
134
+ - GroupFSVFS 只传 `group_aid:/memberdata/{member_ref}/...` 视图路径并调用 `group.fs.*`。
135
+ - 四语言 SDK 均不得包含 `memberdata -> group_data` 的客户端映射逻辑,也不得把系统目录保护实现前移到客户端。
136
+
137
+ ### RPC
138
+
139
+ - 普通 `storage.*` / `storage.fs.*` 对 reserved root fail-closed。
140
+ - `group.fs.*` 是唯一可间接访问成员数据的公开 RPC 面。
141
+ - storage 内部只信任服务端注入的 group_fs context,不信任客户端提交的同名字段,跨域 relay 时必须保持可信来源校验。
142
+
143
+ ## 16.9 审计与可观测性
144
+
145
+ Storage 应记录以下内部审计事件:
146
+
147
+ - 普通目录树入口隐藏 `group_data`。
148
+ - 普通读/下载入口访问 `group_data` 按 read 权限鉴权,不因目录名隐藏。
149
+ - 普通写入和状态变更入口访问 `group_data` 被拒绝。
150
+ - 普通入口写 group 空间 `memberdata` 被拒绝。
151
+ - group.fs 代理读取成员槽位。
152
+ - group.fs 成员本人写入槽位子路径。
153
+ - 尝试删除 `memberdata` 根、槽位根或 `group_data/{group_aid}` 根。
154
+
155
+ 审计记录应包含 requester、actor、group_aid、storage_owner_aid、operation、view_path、storage_path、decision 和 reason。普通用户可见错误不必暴露真实 storage_path。
156
+
157
+ ## 16.10 测试验收
158
+
159
+ 必须覆盖以下测试:
160
+
161
+ - 普通 storage 写 `group_data/{group_aid}/a.txt` 被拒绝。
162
+ - 普通 storage owner 对 `group_data/{group_aid}/a.txt` 的 `get_object/head_object/create_download_ticket/check_access(read)` 按普通读权限成功。
163
+ - 普通 storage `mkdir/rm/mv/cp/symlink/mount` 涉及 `group_data` 被拒绝。
164
+ - 普通 `ls/find/stat/lstat/resolve/list_children/list_objects/list_prefixes` 不返回 `group_data` 项或对子路径返回 not found,但 `df /` 总量包含其占用。
165
+ - 普通 Storage 读/list/stat `memberdata/...` 不因目录名隐藏;普通写 `memberdata/...` 被拒绝。
166
+ - `group.fs.cp local -> group_aid:/memberdata/me/a.txt` 成功,配额扣在成员 AID。
167
+ - `group.fs.rm group_aid:/memberdata/me/a.txt` 成功。
168
+ - `group.fs.rm group_aid:/memberdata/me` 被拒绝或转为非删除真实数据的卸载语义。
169
+ - 成员不能写他人 `memberdata/{other}`。
170
+ - 非成员不能通过 group.fs 读写任意 `memberdata` 槽位。
171
+ - 群解散或成员退出后,普通 Storage 仍不暴露 `group_data`,group.fs 访问按成员关系 fail-closed。
172
+
173
+ ## 16.11 与相关协议的关系
174
+
175
+ - Group 子协议负责定义 `memberdata` 视图、成员槽位权限和 `group.fs.*` 控制面。
176
+ - Storage 子协议负责定义 `group_data` 真实根保护、配额统计、普通 storage 面的目录树隐藏、读/下载鉴权和写保护行为。
177
+ - SDK 文档只描述 `memberdata` 视图路径,不暴露真实根作为应用开发入口。
@@ -40,7 +40,8 @@ AUN 是 ACP 协议的 2.0 版本,采用 WebSocket + JSON-RPC 2.0 定义 Agent
40
40
  | [06-服务协议.md](06-服务协议.md) | 业务层方法:message.* / meta.* / search.* / task.* / 跨域消息路由 / E2EE 摘要 / `pki.{issuer}` 与 `ct.{issuer}` 公开端点 |
41
41
  | [07-错误码与状态机.md](07-错误码与状态机.md) | 错误码分层汇总、各模式状态机、可重试/不可重试分类 |
42
42
  | [08-AUN-E2EE.md](08-AUN-E2EE.md) | 端到端加密安全层:密文格式、签名、防重放、prekey 管理(横跨三种模式) |
43
- | [08-AUN-E2EE-Group.md](08-AUN-E2EE-Group.md) | 群组 E2EE:Epoch Group Key、Membership Commitment、密钥分发与恢复 |
43
+ | [08-AUN-E2EE-Group.md](08-AUN-E2EE-Group.md) | 群组 E2EE V2:消息级密钥、逐设备密钥包裹、成员状态签名验证 |
44
+ | [16-系统目录保护方案.md](16-系统目录保护方案.md) | `memberdata` 与 `group_data` 的系统目录保护、`group_data` 目录树隐藏与读下载/写保护边界、Group FS 授权路径和配额归属 |
44
45
 
45
46
  ### 附录
46
47
 
@@ -17,12 +17,13 @@
17
17
  | 06 | [06-服务协议.md](06-服务协议.md) | 业务层:message.* / meta.* / search.* / task.* / group.* + 跨域消息路由 |
18
18
  | 07 | [07-错误码与状态机.md](07-错误码与状态机.md) | 错误码汇总、各模式状态机、重试分类 |
19
19
  | E2EE | [08-AUN-E2EE.md](08-AUN-E2EE.md) | 端到端加密安全层(横跨三种模式) |
20
- | E2EE-Group | [08-AUN-E2EE-Group.md](08-AUN-E2EE-Group.md) | 群组 E2EE:Epoch Group Key、Membership Commitment、密钥恢复 |
20
+ | E2EE-Group | [08-AUN-E2EE-Group.md](08-AUN-E2EE-Group.md) | 群组 E2EE V2:消息级密钥、逐设备密钥包裹、成员状态签名验证 |
21
21
  | 09 | [09-安全考虑.md](09-安全考虑.md) | 威胁模型、防护措施、升级安全、验签时序 |
22
22
  | 10 | [10-Group-子协议.md](10-Group-子协议.md) | `group.*` 群组管理、群消息、邀请码、资源共享、在线状态 |
23
23
  | 11 | [11-Storage-子协议.md](11-Storage-子协议.md) | `storage.*` 对象存储、大文件上传下载、预签名 URL |
24
24
  | 12 | [12-Stream-子协议.md](12-Stream-子协议.md) | `stream.*` 实时流式传输、WebSocket 推流、HTTP SSE 拉流、跨域拉流 |
25
25
  | 15 | [15-离线推送通知协议.md](15-离线推送通知协议.md) | `push.*` 离线推送、push_notify_aid 代理、事件通知 + 背压 ack、白名单与去重 |
26
+ | 16 | [16-系统目录保护方案.md](16-系统目录保护方案.md) | `memberdata` 与 `group_data` 的系统目录保护、目录树隐藏/读下载/写保护边界、配额归属和访问矩阵 |
26
27
 
27
28
  **附录**:A-术语表 | B-扩展性 | C-私钥管理 | D-Root CA 治理 | E-Root CA 准入 | F-Issuer CA 申请 | G-孤儿 AID | H-Auth 实现 | I-跨域消息路由 | J-客户端接入 | K-Agent Web | L-E2EE 实现 | M-JWT 实现
28
29
 
@@ -56,7 +57,8 @@
56
57
  | 群消息收发(group.send/pull) | 10 §10.5 |
57
58
  | 群成员权限(owner/admin/member) | 10 §10.2 |
58
59
  | 邀请码(group.create_invite_code) | 10 §10.7 |
59
- | 群文件系统(group.fs.*) | 10 §10.9 |
60
+ | 群文件系统(group.fs.*) | 10 §10.9 |
61
+ | 系统目录保护(memberdata / group_data) | 16 |
60
62
  | 对象存储(storage.*) | 11 |
61
63
  | 实时流传输(stream.*) | 12 |
62
64
  | 推流(WebSocket) | 12 §12.6 推流端点 |
@@ -106,7 +108,7 @@ Gateway 模式定位与职责、Gateway 发现机制、连接时序(auth.* →
106
108
  独立安全层,横跨三种连接模式。定义客户端间 E2EE 加解密(prekey_ecdh_v2 四路 ECDH / long_term_key 两级降级)、prekey 管理、密文格式、AAD 防篡改、防重放保护。无需在线协商。
107
109
 
108
110
  ### AUN-E2EE-Group
109
- 群组端到端加密规范。Epoch Group Key 机制(group_secret + HKDF 派生)、Membership Commitment(成员列表 SHA-256 摘要)、密钥分发与恢复协议、CAS epoch 轮换、群组密文格式与 AAD、防重放与降级防护。
111
+ 群组端到端加密规范(V2,当前唯一在用版本)。每条消息使用独立随机密钥,接收方按设备分别持有密钥包裹(wrap),不依赖群级共享对称密钥。成员状态通过签名版本链(state_version/state_chain)记录,接收方可据此检测状态分叉或篡改。群组密文格式、AAD 防篡改、防重放保护。
110
112
 
111
113
  ### 09-安全考虑
112
114
  威胁模型、传输层安全、认证安全、JWT 信任模型分析、连接升级安全(降级攻击/假地址注入/信令重放)、公开 AP 同步安全、证书轮换验签时序。
@@ -123,4 +125,7 @@ Gateway 模式定位与职责、Gateway 发现机制、连接时序(auth.* →
123
125
  ### 15-离线推送通知协议
124
126
  目标 AID 全部设备离线时的推送机制。push_notify_aid 作为普通客户端 AID 连接 Gateway,通过 `event/push.offline_message` 事件接收推送摘要(仅元数据,不含正文),处理后回 `push.ack` RPC 释放 in-flight 槽位(默认 max_in_flight=1 串行确认,30s 超时不重试)。聚合机制:同一 target_aid 60s 冷却期内合并为一条推送(unread_count++、senders 去重追加)。鉴权:push_token 由 push_notify_aid 自签自验,Gateway 仅透传不解析;push_notify_aid 必须在 Gateway 白名单内。跨域:推送由目标 AID 所属域的 Gateway 触发,push_notify_aid 必须与目标 AID 同域。
125
127
 
128
+ ### 16-系统目录保护方案
129
+ 定义 `memberdata` 与 `group_data` 的分层保护。`memberdata` 不是隐藏目录,但根和成员槽位根不可被普通文件操作破坏,group AID 命名空间下的普通 Storage 写入必须拒绝;`group_data` 是成员个人 Storage 内部真实根,Storage 服务端必须在目录树浏览中隐藏它,读/下载按普通 read 权限处理,写入、删除、重命名、挂载、授权和状态变更必须拒绝。文档同时规定 `group_data` 空间计入真实 owner AID 配额,group.fs 是可信授权写入路径,并给出访问矩阵、生命周期、审计和测试验收要求。
130
+
126
131