@agentunion/fastaun 0.5.20 → 0.5.22

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 (128) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/_packed_docs/CHANGELOG.md +104 -0
  3. package/_packed_docs/INDEX.md +59 -34
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +59 -52
  5. package/_packed_docs/agent.md/working/AID/347/261/273/345/236/213-owner/345/205/263/347/263/273/344/270/216/346/215/242owner/347/274/226/346/216/222/346/226/271/346/241/210.md +530 -0
  6. package/_packed_docs/agent.md/working/AID/347/261/273/345/236/213-owner/345/205/263/347/263/273/345/256/214/346/225/264/350/256/276/350/256/241/344/270/216/345/256/236/346/226/275/350/256/241/345/210/222.md +685 -0
  7. package/_packed_docs/agent.md/working/agent.md-schema/344/270/216/347/255/276/345/217/221/351/252/214/347/255/276/346/265/201/347/250/213/346/276/204/346/270/205.md +349 -0
  8. package/_packed_docs/agent.md/working//346/234/254/345/234/260Docker/346/265/213/350/257/225Bug/346/270/205/345/215/225.md +40 -0
  9. 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 +307 -67
  10. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +41 -15
  11. package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +1433 -1392
  12. package/_packed_docs/protocol/08-AUN-E2EE.md +17 -12
  13. package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +30 -8
  14. package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/211.md +2 -0
  15. package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +33 -22
  16. package/_packed_docs/sdk/0.5.21-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +368 -0
  17. package/_packed_docs/sdk/0.5.21-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +350 -0
  18. package/_packed_docs/sdk/0.5.22-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +212 -0
  19. package/_packed_docs/sdk/0.5.22-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +199 -0
  20. package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +1 -1
  21. package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +5 -1
  22. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +64 -64
  23. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +4 -1
  24. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +42 -39
  25. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +163 -14
  26. package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +48 -47
  27. package/_packed_docs/sdk/09-group-rpc-manual.md +15 -2
  28. package/_packed_docs/sdk/09-message-rpc-manual.md +250 -160
  29. package/_packed_docs/sdk/09-storage-rpc-manual.md +64 -7
  30. package/_packed_docs/sdk/09-/345/207/255/350/257/201/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +73 -0
  31. package/_packed_docs/sdk/09-/347/273/204/347/273/207/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +90 -0
  32. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +33 -25
  33. package/_packed_docs/sdk/INDEX.md +67 -33
  34. package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +74 -57
  35. package/_packed_docs/sdk/Ownership2.1-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +312 -300
  36. package/_packed_docs/sdk/Ownership2.1-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +322 -382
  37. package/_packed_docs/sdk/Ownership2.1-TDD/345/210/206/351/230/266/346/256/265/345/256/236/346/226/275/350/256/241/345/210/222.md +708 -708
  38. package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +28 -20
  39. package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +190 -97
  40. package/_packed_docs/sdk//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +158 -127
  41. package/dist/agent-md-schema.js +6 -4
  42. package/dist/agent-md-schema.js.map +1 -1
  43. package/dist/agent-md.d.ts +22 -2
  44. package/dist/agent-md.js +92 -68
  45. package/dist/agent-md.js.map +1 -1
  46. package/dist/aid-store.d.ts +13 -0
  47. package/dist/aid-store.js +50 -15
  48. package/dist/aid-store.js.map +1 -1
  49. package/dist/auth.d.ts +1 -0
  50. package/dist/auth.js +22 -2
  51. package/dist/auth.js.map +1 -1
  52. package/dist/cert-utils.d.ts +1 -0
  53. package/dist/cert-utils.js +13 -0
  54. package/dist/cert-utils.js.map +1 -1
  55. package/dist/client/delivery.d.ts +87 -1
  56. package/dist/client/delivery.js +1387 -139
  57. package/dist/client/delivery.js.map +1 -1
  58. package/dist/client/group-state.js +3 -0
  59. package/dist/client/group-state.js.map +1 -1
  60. package/dist/client/rpc-pipeline.d.ts +4 -1
  61. package/dist/client/rpc-pipeline.js +149 -37
  62. package/dist/client/rpc-pipeline.js.map +1 -1
  63. package/dist/client/v2-e2ee.d.ts +12 -2
  64. package/dist/client/v2-e2ee.js +831 -304
  65. package/dist/client/v2-e2ee.js.map +1 -1
  66. package/dist/client.d.ts +26 -2
  67. package/dist/client.js +412 -68
  68. package/dist/client.js.map +1 -1
  69. package/dist/config.d.ts +4 -0
  70. package/dist/config.js +1 -0
  71. package/dist/config.js.map +1 -1
  72. package/dist/events.d.ts +18 -1
  73. package/dist/events.js +148 -9
  74. package/dist/events.js.map +1 -1
  75. package/dist/facades.d.ts +43 -1
  76. package/dist/facades.js +363 -7
  77. package/dist/facades.js.map +1 -1
  78. package/dist/group-fs.d.ts +1 -0
  79. package/dist/group-fs.js +37 -19
  80. package/dist/group-fs.js.map +1 -1
  81. package/dist/index.d.ts +5 -3
  82. package/dist/index.js +1 -1
  83. package/dist/index.js.map +1 -1
  84. package/dist/keystore/aid-db.d.ts +6 -1
  85. package/dist/keystore/aid-db.js +184 -42
  86. package/dist/keystore/aid-db.js.map +1 -1
  87. package/dist/keystore/index.d.ts +14 -0
  88. package/dist/keystore/local-token-store.d.ts +9 -1
  89. package/dist/keystore/local-token-store.js +79 -14
  90. package/dist/keystore/local-token-store.js.map +1 -1
  91. package/dist/org-protocol.d.ts +46 -0
  92. package/dist/org-protocol.js +802 -12
  93. package/dist/org-protocol.js.map +1 -1
  94. package/dist/ownership-v21.d.ts +36 -5
  95. package/dist/ownership-v21.js +168 -52
  96. package/dist/ownership-v21.js.map +1 -1
  97. package/dist/ownership-workflow.d.ts +24 -2
  98. package/dist/ownership-workflow.js +682 -41
  99. package/dist/ownership-workflow.js.map +1 -1
  100. package/dist/secret-store/file-store.js +84 -0
  101. package/dist/secret-store/file-store.js.map +1 -1
  102. package/dist/seq-tracker.d.ts +1 -0
  103. package/dist/seq-tracker.js +2 -2
  104. package/dist/seq-tracker.js.map +1 -1
  105. package/dist/storage/lowlevel.d.ts +6 -0
  106. package/dist/storage/lowlevel.js +24 -7
  107. package/dist/storage/lowlevel.js.map +1 -1
  108. package/dist/storage/read-cache.d.ts +70 -0
  109. package/dist/storage/read-cache.js +625 -0
  110. package/dist/storage/read-cache.js.map +1 -0
  111. package/dist/storage/vfs.d.ts +2 -0
  112. package/dist/storage/vfs.js +50 -15
  113. package/dist/storage/vfs.js.map +1 -1
  114. package/dist/tools/cross-sdk-agent.d.ts +86 -3
  115. package/dist/tools/cross-sdk-agent.js +758 -46
  116. package/dist/tools/cross-sdk-agent.js.map +1 -1
  117. package/dist/transport.d.ts +3 -0
  118. package/dist/transport.js +104 -46
  119. package/dist/transport.js.map +1 -1
  120. package/dist/types.d.ts +1 -0
  121. package/dist/v2/e2ee/encrypt-group.js +1 -0
  122. package/dist/v2/e2ee/encrypt-group.js.map +1 -1
  123. package/dist/v2/e2ee/encrypt-p2p.js +1 -0
  124. package/dist/v2/e2ee/encrypt-p2p.js.map +1 -1
  125. package/dist/v2/e2ee/types.d.ts +1 -0
  126. package/dist/version.d.ts +1 -1
  127. package/dist/version.js +1 -1
  128. package/package.json +1 -1
@@ -2,13 +2,15 @@
2
2
 
3
3
  本文把 [Ownership 协议定义 2.1](../protocol/Ownership协议定义2.1.md) 和 [SDK 编排指南 2.1](Ownership-SDK编排指南2.1.md) 落到现有实现。协议字段、SDK 消息及事件以这两份文档为准;本文定义组件职责、持久数据、提交边界和改造方式。实施顺序与失败用例见 [TDD 分阶段实施计划](Ownership2.1-TDD分阶段实施计划.md)。
4
4
 
5
+ 普通 `agent.md` 的基础读取、验签、上传与显式 pending 恢复不以前置 Ownership 共识、owner Storage 或关系状态为条件。普通正文更新须原样保留当前原件中全部关系材料的字段存在性、类型和值,并遵守本人签名和原 ETag/CAS;材料无效或依赖不可用不能阻断这种更新。增删改关系字段继续执行当前双文件授权核验,不能借普通名片入口清除或替换 owner 锁。
6
+
5
7
  实施前代码基线为 2026-10-10 工作区,Git HEAD 为 `1f03bf2d`;该工作区存在尚未提交的实现,不能将基线等同于纯净的 0.5.18 tag。范围是 Python、Node TypeScript、Browser JavaScript、Go 四套 SDK,现有 Go NS、Storage,以及已由测试证明必需的 CA / Gateway 通用适配。下文“现有”“拟新增”描述实施前定位及设计意图;实际实现、验证结果和剩余项以 [实施账本第 13 节](Ownership2.1-TDD分阶段实施计划.md#13-2026-10-10-实施账本) 为准。
6
8
 
7
9
  ## 1. 设计边界
8
10
 
9
11
  通用 Ownership 2.1 排除 `group/org`:其 owner 来自专属服务的创建、解散、转移事实,不创建 owner.md、通用关系版本、锁、NS Ownership 账本或审批任务。通用 Facade 在副作用前直接返回 `not_applicable`、`retryable=false`,共识 `status/code=not_applicable`,不自动转调用其它方法。新 SDK 的实体名片分支以权威类型和生命周期为准;owner 必填、禁止通用 ownership/proof/release,实体私钥主签、owner token 上传并可选 owner 附签,上传校验实体当前证书代际及完整文件原字节;NS 旧客户端实体 token 与当前实体自签的受限旧格式入口见 [协议 §2.5](../protocol/Ownership协议定义2.1.md#25-grouporg-名片的实体主签与-owner-上传)。
10
12
 
11
- 实体 fresh GET 同时携带 X-AUN-Ownership-Check: 1、Cache-Control: no-cache 和 X-AUN-Signature-Format: multi-v1,触发 NS 绕 LRU 全块新鲜验证,仍为 not_applicable、不进入通用账本;GET/HEAD 按 multi-v1 协商完整/首签表示,返回对应 ETag;current/stale、权威 owner/指纹与 missing/unavailable 边界遵循协议 §2.5。verified 下载全块验证历史证书及原始字节,不因当前 owner 或代际变化拒绝历史有效文件,历史成功不代表当前权限。上传仍新鲜校验当前生命周期及证书,不扩展 gateway.resolve。
13
+ 实体 fresh GET 同时携带 X-AUN-Ownership-Check: 1、Cache-Control: no-cache 和 X-AUN-Signature-Format: multi-v1,触发 NS 绕 LRU 全块新鲜验证,仍为 not_applicable、不进入通用账本;GET/HEAD 按 multi-v1 协商完整/首签表示,返回对应 ETag;current/stale、权威 owner/指纹与 missing/unavailable 边界遵循协议 §2.5。verified 下载全块验证历史证书及原始字节,不因当前 owner 或代际变化拒绝历史有效文件,历史成功不代表当前权限。上传仍新鲜校验当前生命周期及证书,不扩展 gateway.resolve。独立 AIDStore 的实体上传接线存在语言差异:Python/Go 须显式注入权威 entity owner resolver;TS/JS 默认通过 fresh NS 与 PKI 核对当前 owner 和实体证书指纹,不能假定四端均自动调用实体服务。
12
14
 
13
15
  旧实体文件按历史读取规则保留;历史 relation/evidence/checkpoint 元数据不参与当前关系判定,也不是普通名片可用性的前置条件。当前实体上传按权威类型、生命周期、当前证书及新 Schema 验收。
14
16
 
@@ -65,7 +67,7 @@ flowchart TB
65
67
  | D2 | 原关系有效时,sub 不能清除 owner、只删 statement、改为 human 或 self-owner 来绕过锁。 |
66
68
  | D3 | 只有有效 release、权威删除,或原 owner 指定目标的有效 transfer_owner 能改变受保护关系。 |
67
69
  | D4 | 当前声明版本无声明为 0;绑定由双方明确选择一致正版本,SDK 默认当前可见基数加一、无声明时为 1;转移强制 v+1。release/删除不递增,清理后不保留独立历史版本上界。 |
68
- | D5 | NS 只在本地数据库事务中以 CAS 原子提交完整 `agent.md`;owner 的 `owner.md` 由其 Storage 独立条件提交。验收失败不保存候选文件,恢复只依据两份文件、事务提交结果和 CAS 条件。 |
70
+ | D5 | NS 在本地数据库事务中以 CAS 提交完整 `agent.md`;owner 的 `owner.md` 由其 Storage 独立条件提交。sub-first 未锁绑定可用 Stage 保存待确认原件及 CAS 绑定的 pending 标记,不能据此授权;owner-first 先 fresh 确认无锁并发布 owner 原件,sub 同意后直接条件提交,不使用 Stage。稳定关系仍须双文件 fresh 验收。转移验收失败不保存目标候选。 |
69
71
  | D6 | owner 文件操作前重新核对当前完整原文、摘要和存在性;不增加 Storage 路径修订或 ABA 检测机制。 |
70
72
  | D7 | 故障、无效签名、缓存 404、旧备份不能解释为解绑或无锁。 |
71
73
  | D8 | SDK 审批只表达业务意图;任务、消息 ACK、ready 和 confirmed 提示不能替代 NS 验收。 |
@@ -109,7 +111,7 @@ NS 下列路径以 [Go 服务根目录](../../../extensions/services/nameservice
109
111
  | `internal/httpserver/agentmd_cache.go` | 当前名片缓存。 | 继续供普通展示;不能作为最终授权依据。 |
110
112
  | `internal/httpserver/sync.go` | 现有 sync_agent_md 是 SDK 拉取名片快照。 | 保留原用途;另实现 NS 提交后的 Storage 副本同步,不借该接口代上传。 |
111
113
  | `internal/httpserver/router.go`:`applyBrowserCORS` | 当前 expose headers 没有 ownership 三个响应头。 | 允许浏览器读取协议、关系版本和锁头,保留现有预检处理。 |
112
- | `cmd/nameservice-go/main.go` | 已装配 CA、Gateway 等 resolver。 | 装配 Storage 当前对象查询、agent.md CAS 恢复检查和副本同步 worker。 |
114
+ | `cmd/nameservice-go/main.go` | 已装配 CA、Gateway 等 resolver。 | 分别装配关系变更的 Storage/当前证书核验和名片同步 worker;可信 Org 分类回填完成后,CA normal 不再额外查询 Org 判负。 |
113
115
 
114
116
  ### 2.3 Storage 及周边服务
115
117
 
@@ -118,13 +120,13 @@ Storage 下列路径以 [Go 服务根目录](../../../extensions/services/storag
118
120
  | 现有文件 / 方法 | 当前能力与缺口 | 修改方式 |
119
121
  | --- | --- | --- |
120
122
  | `internal/service/service.go`:`PutObject`、`CreateUploadSession`、`CompleteUpload` | 已有 overwrite、expected_version 及提交时版本判断。 | 沿用既有完整文件原子发布,owner 更新不得先删后建。 |
121
- | 同文件:`DeleteObject`、`deleteResolvedObject`、`FSRemove` | 沿用既有删除能力。 | SDK 清理前核对当前 NS 与本任务完整 owner 原件,不增加删除条件接口。 |
123
+ | 同文件:`DeleteObject`、`deleteResolvedObject`、`FSRemove` | `DeleteObject` 增加可选 `expected_version`,与对象版本检查在原子删除时执行;省略保持既有无条件行为。 | Ownership 清理带最后读取且已核对任务原件的当前对象版本;版本条件不匹配或 CAS 竞争返回 `-32009`,SDK 停止,不转为无条件删除。 |
122
124
  | 同文件:`HeadObject`、`FSStat` | 现有对象查询。 | 补不经正负缓存的权威查询及明确的路径不存在结果;故障和恢复未完成单独失败。 |
123
125
  | 同文件:FSRename、FSCopy、MoveObject、DeleteFolder、BatchDelete、SetVisibility、CheckAccess 等 | 多种目录、路径和授权入口。 | 在最终解析路径后统一执行 owner.md 保护,覆盖父目录、移动、软链、挂载及批量操作。 |
124
126
  | `internal/service/handlers.go`、`internal/contracts/methods.go`、`internal/rpc/request_context.go` | 通用 Storage/FS 契约、路由与请求认证上下文。 | 贯穿新增条件和权威结果;NS 镜像授权只认经过认证的服务身份。 |
125
127
  | `internal/cleanup/`、`internal/collab/service.go` | 自动清理和其它文件修改通路。 | 不允许自动清理或第三方修改间接删除规范 owner.md;保护下沉至公共写入路径。 |
126
128
 
127
- Auth、CA、Message、Gateway 默认复用。只有测试证明现有身份、证书状态或可信服务上下文不能满足上述契约时,才修改相应适配点;不新增 ownership 关系 RPC、审批 RPC 或服务端消息类型。
129
+ Auth、Message、Gateway 保留既有通信和认证通路。R02 的权威类型由 CA 持久保存可信 Org 分类及回填完成标记:仅认证的 Org 服务可登记,Org 恢复分页回填全部生命周期记录(含 dissolved),全部成功后提交完成标记;创建先登记,失败时保守保留分类,初签/rekey 不覆盖它。回填完成后 NS 对 CA normal 不再查询 Org;未完成时继续保守核对,不能将 Org 故障降为 normal。Org 仍使用 signing 证书,分类不包含 owner 关系事实。
128
130
 
129
131
  ## 3. 持久模型
130
132
 
@@ -160,7 +162,7 @@ step 表达“本端接下来做什么”,不组合成三方状态笛卡尔积
160
162
 
161
163
  实现采用每任务记录及记录修订,读取、比较和写入在本端数据库事务内完成;审批决定与待发送项一次保存。现有普通 metadata getter 不能区分读取失败和空值时,增加专用于任务的错误返回及条件更新能力,不改变其它 metadata 使用者的语义。自定义存储不满足该能力时,2.1 有副作用的编排不可用。
162
164
 
163
- 起始证据统一保存 `base_agent_md={exists,raw,sha256,etag,statement|null}` 与 `base_owner_md={exists,raw,sha256}`。非空 statement 完整相同的普通正文更新不替代关系,尚未签署的本方候选使用新鲜读取的原 ETag;已持久保存的签名字节重试仍沿用其原 CAS,不刷新条件。起始无声明时完整 agent 原文变化则停止旧审批。owner 写前和清理前重读当前完整原文、摘要及存在性,不增加远端条件字段。 base_owner_md 对应 base_agent_md.statement 所指当前/最后 owner 的文件;无 statement 时没有当前 owner 事实,本地可省略或使用空标记;bind/transfer 目标 owner 写前原件在待发布文件中另存并复读,不替代原 owner 基线。
165
+ 起始证据统一保存 `base_agent_md={exists,raw,sha256,etag,statement|null}` 与 `base_owner_md={exists,raw,sha256}`。非空 statement 完整相同的普通正文更新不替代关系,尚未签署的本方候选使用新鲜读取的原 ETag;已持久保存的签名字节重试仍沿用其原 CAS,不刷新条件。起始无声明时完整 agent 原文变化则停止旧审批。owner 写前和清理前重读当前完整原文、摘要及存在性;发布沿用保存的原 Storage `expected_version`;删除先精确核对本任务原件,再以最后读取到的当前对象 `version` 作为 `expected_version`,该删除发生冲突即停止,不换新版本盲重试。 base_owner_md 对应 base_agent_md.statement 所指当前/最后 owner 的文件;无 statement 时没有当前 owner 事实,本地可省略或使用空标记;bind/transfer 目标 owner 写前原件在待发布文件中另存并复读,不替代原 owner 基线。
164
166
 
165
167
  ## 4. 文件层实现
166
168
 
@@ -217,7 +219,7 @@ owner.md 不具备名片必填的 name/type/version,不能直接复用“必
217
219
  | 权威读取 | 沿用现有 Storage/FS 权威查询与完整正文读取,绕过正负缓存;核对请求 owner、bucket、规范 path、exists、sha256 和完整原文。服务身份由认证通道核对,不相信自报字段。 |
218
220
  | 路径不存在 | 明确当前路径不存在;DB 故障、路由 404、无权读取、恢复未完成必须失败,不能返回 exists=false。 |
219
221
  | 创建 / 替换 | 沿用现有 overwrite 和 expected_version;SDK 先核对保存的起始存在性、完整原文和摘要,不增加 Storage 条件字段。 |
220
- | 删除 | 沿用既有删除接口;删除前重新核对当前 NS 与本任务完整 owner 原件,后续文件出现时停止。 |
222
+ | 删除 | 删除前重新核对当前 NS 与本任务完整 owner 原件,携带最后读取且已核对任务原件的当前对象版本作为 `expected_version` 原子删除;后续文件出现或版本冲突时停止,不追随新版本重试。 |
221
223
  | 上传 session | 创建 session 时固化路径和条件,CompleteUpload 真正发布前再检查;force/overwrite 不能覆盖 ownership 文件的必需条件。 |
222
224
  | 原子发布 | 规范文件使用独立上传临时对象,complete 沿用 create 返回的同一 session_id,核对会话申请者/目标/期限并验证完整内容后原子替换;失败时规范路径仍指向旧完整文件。 |
223
225
 
@@ -241,23 +243,25 @@ NS 复制名片使用可信服务身份,仅允许写 `owner_aid=sub_aid, bucke
241
243
 
242
244
  ### 6.1 同一 sub_aid 的处理路径
243
245
 
244
- 新鲜关系检查和名片写入口复用同一验收逻辑;普通读取不强制检查当前关系。
246
+ 新鲜关系检查和改变关系材料的名片写入口复用同一验收逻辑;普通读取和完整保留关系材料的正文更新不强制检查当前关系。普通更新先比较已存和候选中的完整关系材料,再按自身签名及原 ETag/CAS 提交;owner 网络读取不持有最终提交锁,提交时重新核对同一 agent.md 快照,关系依赖迟缓不能占用普通正文更新的锁。
245
247
 
246
248
  1. 按 sub_aid 串行读取当前 agent.md 和 CAS,区分不存在与数据库错误。
247
249
  2. 从已存原文确定原 owner/版本,不用候选新 owner 判断旧关系。
248
250
  3. 核验当前 owner.md 的签名、路径、身份、版本和完整原文;匹配 release/权威删除返回 released,无效或不可用不授 owner 权限。
249
- 4. GET/HEAD 返回原字节和关系投影,不存额外关系事实。PUT 校验上传身份、原 CAS、完整候选及适用绑定/转移材料。
251
+ 4. GET/HEAD 返回原字节和关系投影。PUT 校验上传身份、原 CAS、完整候选及适用绑定/转移材料;sub-first 未锁绑定的 Stage PUT 可以先保存待确认原件,返回 pending/unlocked,不授 owner 权限。owner-first 的 sub 带原条件直接 PUT,NS fresh 复核后原子验收并锁定。
250
252
  5. 最终重新读取 owner 原文和存在性,复核 agent 原 ETag、证书及转移期限;材料变化或超时不能沿用旧结果。
251
- 6. 短数据库事务比较原 CAS,原子提交完整 sub 自签文件;失败回滚本次名片提交。
252
- 7. 提交后刷新缓存并同步副本;响应丢失不撤销已提交文件。
253
+ 6. 短数据库事务比较原 CAS,原子提交完整 sub 自签文件;待确认绑定的 fresh 验收保留原字节并清除 pending 标记。失败不建立稳定关系,不撤销已可靠暂存的原件。
254
+ 7. 提交后刷新缓存;Stage pending 原件已是 NS 当前权威名片,但仅在 fresh 验收清除 pending 后同步 Storage 副本。响应丢失不撤销已提交文件。
253
255
 
254
256
  候选失败不撤销 owner.md 的当前 release。NS 不修改或重签 sub 文件,也不持久化独立释放代际。
255
257
 
258
+ 待确认流程使用 `ownership_pending(sub_aid, document_sha256, document_updated_at, relation_version, owner_sha256)`,与当前名片 CAS 一起持久化。owner 文件仍缺失或摘要未相对暂存快照改变时保持 pending;本轮匹配 declare 验签及复读通过后才建立锁,sub 可离线。此表不是稳定关系、审批决定或释放历史的授权账本;原件被替换后旧审批及清理依据失效。请求/响应头及服务端能力要求见 [协议 §3.3](../protocol/Ownership协议定义2.1.md#33-读取并发与接口)。
259
+
256
260
  ### 6.2 关系转换表
257
261
 
258
262
  | 当前材料 | 处理 | 结果 |
259
263
  | --- | --- | --- |
260
- | 无有效关系,当前可见版本 v(无声明为 0) | 双方明确签署一致正版本并按原 CAS 提交;SDK 默认 v+1、无声明时为 1。 | 匹配时 consensus/locked;NS 不独立强制绑定上界,不齐不保存候选。 |
264
+ | 无 owner 锁,当前可见版本 v(无声明为 0) | 双方明确签署一致正版本;SDK 默认 v+1、无声明时为 1。sub-first 可 Stage 候选,再由 owner 发布 declare;owner-first 必须先 fresh 确认无锁,由 owner 条件发布 declare,再由 sub 同意并直接条件提交。 | sub-first 待确认为 pending/unlocked,公共共识 single_sided;owner-first 直接提交经 fresh 验收后 consensus/locked。NS 不独立强制绑定上界。 |
261
265
  | 原 owner 有效 declare | 正文更新保留 owner 和完整 statement。 | 版本不变,ETag 可变。 |
262
266
  | 有效 transfer_owner | 转移须匹配目标、v+1、期限及目标双文件。 | 直接提交目标 sub 自签文件。 |
263
267
  | transfer_owner 过期 | 不转移,继续核验旧关系。 | 不自动释放。 |
@@ -305,23 +309,23 @@ Storage 当前完整原文复核与 NS 提交之间没有跨服务一致快照
305
309
 
306
310
  | Facade | 调用的内部工作 | 本端应用责任 |
307
311
  | --- | --- | --- |
308
- | bindOwneraid | 保存 sub 发起任务,发送 bind.request;owner 同意后由 owner declareSubaid,再由 sub declareOwneraid。 | sub 发起即表达本端意愿;owner 处理审批。 |
309
- | bindSubaid | 保存 owner 发起任务,等待 sub 同意,然后同上推进。 | owner 发起;sub 明确同意或拒绝。 |
310
- | acceptOwnershipRequest | 对已有请求持久保存决定、回复,并仅推进已经满足审批和权威前置条件的步骤。 | 按界面或代码策略决定,未决定保持等待。 |
311
- | rejectOwnershipRequest | 持久保存拒绝并回复,结束该待审批任务。 | 只用于尚未作决定的审批;不通过拒绝回滚已发布文件。 |
312
+ | bindOwneraid | fresh 检查无锁和 Stage 能力;保存 sub 同意和原件,Stage 上传后发送 bind.request;owner 同意后发布 declare,fresh 验收原候选。 | sub 发起即表达本端意愿;owner 处理审批,候选可靠暂存后 sub 可离线。 |
313
+ | bindSubaid | fresh 检查无锁;保存并条件发布 owner.md 后发送 bind.request;sub fresh 验签并同意后直接条件提交 agent.md,NS fresh 验收。 | owner 发起;sub 明确同意或拒绝,无 bind.accept/owner.ready 往返。 |
314
+ | acceptOwnershipRequest | 对已有请求持久保存决定;sub-first owner 回复可通知 sub 后发布声明,owner-first sub 同意后直接提交名片,不要求 accept 往返。 | 按界面或代码策略决定,未决定保持等待。 |
315
+ | rejectOwnershipRequest | 持久保存拒绝并回复;sub 恢复精确原件/CAS 匹配的未锁候选清理。 | 只用于尚未作决定的审批;不能借拒绝回滚已验收或已替换关系。 |
312
316
  | releaseSubaid | 发布 release → 新鲜确认 → 通知 sub 自签清理 → 条件清理旧文件。 | 不等待 sub 在线,任务目标版本为被释放声明的当前版本。 |
313
317
  | transferSubaid | 收齐新 owner 与 sub 同意 → transferOwneraid → 新 owner declareSubaid → sub declareOwneraid。 | 只有原 owner 可发起,两个接收角色均参与意向审批。 |
314
318
  | checkOwnershipConsensus | 调用第 4.3 节的统一检查器。 | 展示结果或触发业务执行端自己的新鲜授权。 |
315
319
 
316
320
  发起方法先查询权威现状固定起始版本,在发送消息、发布文件或删除等副作用前保存任务,返回 operation_id 与本端进度,结果由本地事件继续通知。面向应用只导出这些方法和必要类型,五个文件方法不导出。Python/Go 采用本语言命名习惯,但语义和消息 action 保持一致。
317
321
 
318
- 内部编排器与消息处理器推进同一任务;禁止收到 owner.ready 后再调用 bindOwneraid 创建第二个任务。普通名片更新仍使用现有名片 API,但必须完整保留锁定的关系字段。
322
+ 内部编排器与消息处理器推进同一任务;sub-first 及 transfer 的历史 ready 通知不得再次创建绑定任务,owner-first 无需 owner.ready。普通名片更新仍使用现有名片 API,但必须完整保留锁定的关系字段。
319
323
 
320
324
  普通 `agent` 注册的 owner 可选;指定 owner 时,owner 意图先与 SDK 生成的固定 operation_id 一起持久保存;初始名片不写 owner 或旧 proof,并以条件创建提交。连接后用该 ID 进入绑定编排,响应丢失或重连都读取原任务,不另建操作、不默认批准;未指定 owner 时只初始化普通名片,不创建关系任务。NS 不可用时保留已有意图;已有关系或未知旧待上传文件不能由初始化路径覆盖。Group/Org 身份准备不生成通用注册意图;创建自动 owner 绑定,owner 持有实体材料,用实体私钥主签并以本人 token 上传,可选追加本人附签。专属 pending 保存实体命名空间、固定 owner、实体证书指纹、原完整多签文件及原 CAS,恢复不补造条件或跨 owner/rekey 代际重签。
321
325
 
322
326
  普通显式上传与注册初始化分别保存待办。普通名片候选在本地 schema 和外层签名验证通过后、首次远端 preflight 前,先独立保存到既有元数据的私有 `local_draft_content`,不覆盖已确认的远端 content/ETag;自有且持有本地私钥的身份默认 resolve 优先返回该稿,标记 unverified、in_sync=false、source.agent_md_fetched=false。显式 download/forceRefresh 仍读取远端权威内容并保留草稿,只有服务端确认对应候选提交成功才清稿。重连不自动重传普通失败稿,普通注册 initial 失败稿同样需要应用显式重试;即使存在普通 pending 也不隐式 PUT。Ownership 2.1 任务及注册意图的既有恢复不能替代失败稿的显式重试。取得可靠 NS 原条件后,仍在 PUT 前持久保存完整签名字节、原 If-Match/If-None-Match 及关系快照;显式重试既有 pending 时先核原条件,缺失则保留原元数据及原错误,不因远端同字节而清除。2.1 正文更新核对原 owner、完整 statement、relation_version 和 lock。已有普通 legacy owner/proof 或 2.0 关系仅允许更新正文,完整保留 owner、ownership、ownership_proof、ownership_release 的存在性、类型和值;新 metadata 和外签执行当前规则,不自动迁入 2.1。该分支持久保存原全文、摘要、原 ETag 及完整关系快照,重试核对 base/candidate/remote 和原条件;全文及提交 ETag 均对应原提交时只观察确认,否则仅按仍成立的原条件重传原 blob,不刷新 CAS、不重签、不补造上下文。其它缺原上下文的旧待办仅允许版本 0 / unlocked 的初始关系;实际关系变更由对应 Ownership 任务恢复。
323
327
 
324
- Group/Org 名片失败稿及 pending 保留实体命名空间中的完整多签原文、原 CAS、固定 owner 和实体证书指纹,由应用显式重试,post-connect/重连不隐式 PUT。重试先验证完整原件及当前 owner、状态和证书代际,原条件完整且同代际原文/ETag 已确认提交时只观察完成。转移、rekey 或解散后停止旧代际待办,不更换身份、指纹或条件重签。取消实体 V2 授权后,不再保存、刷新或检查其额外授权及过期窗口;普通文件签名与当前证书检查保留。专属 create/transfer 自身 checkpoint 恢复机制不变。
328
+ Group/Org 名片失败稿及 pending 保留实体命名空间中的完整多签原文、原 CAS、固定 owner 和实体证书指纹,由应用显式重试,post-connect/重连不隐式 PUT。重试先验证完整原件及当前 owner、状态和证书代际,原条件完整且同代际原文/ETag 已确认提交时只观察完成。转移、rekey 或解散后停止旧代际待办,不更换身份、指纹或条件重签。新 SDK 现代上传不再保存、刷新或检查额外 V2 授权及过期窗口;旧 V2 兼容入口仍按协议 §2.5 校验;普通文件签名与当前证书检查保留。专属 create/transfer 自身 checkpoint 恢复机制不变。
325
329
 
326
330
  ### 7.2 转移的默认编程顺序
327
331
 
@@ -396,6 +400,8 @@ sub 收到 release 通知时,只有在持久历史中找到本人明确 accept
396
400
 
397
401
  ### 8.1 崩溃点与恢复依据
398
402
 
403
+ 本地任务 revision CAS、NS 原 ETag 条件和 Storage 原 expected_version 各自保护不同资源;分别为 `persistence_unavailable`、HTTP `412/conflict` 与 RPC `-32009/conflict`,不能混用或互换条件。恢复先 fresh 读取 NS 与 Storage 完整原文、SHA、ETag/version,再与本任务持久审批、原签名字节及原条件比较:完整目标精确成立才幂等确认,网络未知保留原 operation,真实内容或关系变化停止旧任务。普通任务保存不自动合并或刷新 revision;后续恢复重读持久任务,不用旧内存态续写;单份同 SHA 文件不保证所有冲突路径自动恢复。清理仅条件删除本任务原件,不更新版本追删。分类和限制见 [开发与移植指南 §10.3](Ownership2.1-SDK开发与移植指南.md#103-cas-冲突分类与恢复边界)。
404
+
399
405
  | 中断点 | 已经稳定的事实 | 恢复动作 |
400
406
  | --- | --- | --- |
401
407
  | 已保存请求,尚未发送 | 关系未变,任务已存在。 | 核对原声明完整原文、摘要、目标与原 CAS,重发相同消息。 |
@@ -409,9 +415,9 @@ sub 收到 release 通知时,只有在持久历史中找到本人明确 accept
409
415
  | NS 已保存名片,副本同步或旧文件清理失败 | 已提交的完整 agent.md 保持;当前关系仍按双材料核验。 | 分别补齐当前副本、按本任务原件核对后清理。 |
410
416
  | 转移授权过期或被有效撤回 | 旧关系仍受保护,除非 NS 已提交转移。 | 新鲜确认;未提交则停止旧任务,不自动延长授权。 |
411
417
 
412
- 共识检查从首次 NS GET 发出前开始计算整体 30 秒窗口,覆盖首读、证书/Storage 验证和末读;材料变化或超时返回可重试 unavailable。fresh HTTP 携带 no-cache 并禁止自动跟随重定向。收到 sub.cleaned 时,在持久接收前核对任务固定的原声明、清理原件、ETag/全文摘要和原 CAS;字段已清空时当前关系为 unbound/0,通知不能替代文件与任务核验。
418
+ 共识检查从首次 NS GET 发出前开始计算整体 30 秒窗口,覆盖首读、证书/Storage 验证和末读;材料变化或超时返回可重试 unavailable。fresh HTTP 携带 no-cache 并禁止自动跟随重定向。收到 sub.cleaned 时,按任务固定上下文新鲜核对当前 NS 完整原文、ETag 和全文摘要;字段已清空时可记录当前 unbound/0 的清理观察。通知或观察进度不能证明本任务执行提交,也不能替代首次完成 release 所需的原件及原 CAS 关联核验。
413
419
 
414
- Group/Org 名片失败稿及 pending 保留实体命名空间中的完整多签原文、原 CAS、固定 owner 和实体证书指纹,由应用显式重试,post-connect/重连不隐式 PUT。重试先验证完整原件及当前 owner、状态和证书代际,原条件完整且同代际原文/ETag 已确认提交时只观察完成。转移、rekey 或解散后停止旧代际待办,不更换身份、指纹或条件重签。取消实体 V2 授权后,不再保存、刷新或检查其额外授权及过期窗口;普通文件签名与当前证书检查保留。专属 create/transfer 自身 checkpoint 恢复机制不变。
420
+ Group/Org 名片失败稿及 pending 保留实体命名空间中的完整多签原文、原 CAS、固定 owner 和实体证书指纹,由应用显式重试,post-connect/重连不隐式 PUT。重试先验证完整原件及当前 owner、状态和证书代际,原条件完整且同代际原文/ETag 已确认提交时只观察完成。转移、rekey 或解散后停止旧代际待办,不更换身份、指纹或条件重签。新 SDK 现代上传不再保存、刷新或检查额外 V2 授权及过期窗口;旧 V2 兼容入口仍按协议 §2.5 校验;普通文件签名与当前证书检查保留。专属 create/transfer 自身 checkpoint 恢复机制不变。
415
421
 
416
422
  重连恢复先读取 NS/Storage,再考虑待发消息、写入和删除。一次持久保存的 step 不能证明远端副作用已经发生,远端的新版本也不能被旧 step 覆盖。
417
423
 
@@ -445,6 +451,8 @@ Ownership 2.1 只以 sub 的 agent.md 和 owner 的 owner.md 为关系事实。N
445
451
 
446
452
  ### 9.2 旧实现的安全隔离
447
453
 
454
+ 0.5.20、0.5.19 及更早任务按原格式及原有协议边界兼容;保留原 operation、有效审批、原签名字节和原提交条件,不能因缺少后增本地字段而一律停止或新建任务。历史适配、绑定容错和无参数 reset 的完整范围见 [编排指南第 8 节](Ownership-SDK编排指南2.1.md#8-崩溃与响应丢失后的恢复)。reset 只归档当前身份发起的未完成任务,保留原记录和远端文件,迟到消息不能复活。 旧 Owner 候选尚未发布时,原 `expected_revision` 必须有权威证据精确匹配,不能用当前 version 替代;服务未提供旧 revision 证据时保留原件及任务并返回 unavailable。目标已提交但任务仍待恢复时,只有本地原始签名候选与当前双方共识精确匹配才确认完成;缺少这些证据不能从当前网络补造历史原件或提交条件。
455
+
448
456
  SDK 的旧 `aun.ownership.v1` 消息、proof 工具和 metadata 不能改名后自动转成新任务。保留必要的旧材料读取与错误提示;2.1 处理器不执行旧 proof、证书托管、代签、代上传或自动 rekey 链路。
449
457
 
450
458
  NS 保留 legacy owner/proof 原保护;普通名片入口允许原样保留旧关系材料、自签及 CAS 更新正文,不自动迁入 2.1。旧 SDK 的注册、绑定、转移、查询和解绑另由隔离的 legacy RPC、Auth JSONL 与 operation ID 兼容流程承载,只激活旧 `ownership_proof`;不写 2.1 双文件,不产生 2.1 lock/version/consensus。缺新 Header 或旧 operation ID 均不得成为覆盖已存现代声明的通路。
@@ -1,173 +1,266 @@
1
1
  # 凭证与组织服务 SDK 应用集成指南
2
2
 
3
- > 适用版本:四套 AUN SDK `0.5.19`,组织服务协议 `0.8`。
4
- >
5
- > 本文面向使用 SDK 的应用开发者。它描述当前代码已经提供的本地协议助手、facade 和服务端闭环;字段级冻结契约以 [组织服务 0.8 详细设计](../../../extensions/services/docs/org/0.8/17-凭证与组织服务详细设计.md) 为准。`14-App接入.md` 是产品界面设计,`11-RPC与SDK.md` 仍包含提出稿方法面,不能单独作为当前实现清单。
3
+ Org `0.8`,SDK `0.5.19` 基线及 `0.5.22` 工作区增量(未发布)。下文使用 Node TS;字段见 [Credential RPC](09-凭证服务RPC手册.md)/[Org RPC](09-组织服务RPC手册.md),内部实现见 [移植指南](凭证与组织服务SDK开发与移植指南.md)。
6
4
 
7
5
  ## 1. 先确认交付边界
8
6
 
9
- SDK 提供两类入口:
7
+ `client.credential` 处理凭证,`client.org` 处理组织/成员及请求准备。业务走 Gateway service-plane,Kernel 只做诊断;带 CID 的 credential.status 是业务查询。先确认服务已部署。
10
8
 
11
- | 入口 | 作用 | 当前可用方法 |
12
- |---|---|---|
13
- | `credential` | 创建、离线验签、完整验证、登记、吊销、状态和吊销列表 | `register`、`revoke`、`status`、`revocationList` |
14
- | `org` | 组织生命周期、成员、组织侧凭证状态、审计、授权检查和请求准备 | 以服务 manifest 与本指南第 5 节为准 |
15
-
16
- Credential 和 Org 是业务服务;`credential.register/revoke/status`(携带 `credential_cid` 时)/`credential.revocationList` 及组织业务 RPC 均经 Gateway service-plane 调用,Kernel 只承载控制面生命周期和 health/status 诊断,不承载凭证、成员或权限业务 RPC。四端 facade 存在不表示目标服务已经部署。探活应使用部署探针或受控的控制面诊断接口;不要把 `credential.status` 一概当作探活:携带 `credential_cid` 的 `credential.status` 是业务状态查询,走 service-plane。服务缺失、证书不可用、数据库不可用时,不能把本地 helper 成功当作服务端授权成功。
17
-
18
- 当前服务端明确保留但尚未实现的入口只有 `org.resource.create`、`org.task.create`、`org.host.add`、`org.workflow.create`;Python 和 Go 仍暴露对应子 facade 以保持统一入口,调用这四个方法时服务端返回业务码 `NOT_IMPLEMENTED`。其它 `org.resource.*`、`org.task.*`、`org.host.*`、`org.workflow.*` 方法不在当前 dispatcher 中,调用时按 JSON-RPC `Method not found` 处理。TS/JS 可通过 `client.call` 访问这些方法,结果遵循同一规则。
9
+ 保留的 org.resource.create/task.create/host.add/workflow.create 返回 NOT_IMPLEMENTED,其他未注册方法返回 Method not found。
19
10
 
20
11
  ## 2. 运行前准备
21
12
 
22
- 应用需要准备:
23
-
24
- 1. 一个已登录的 AUN `AUNClient` 和当前 AID。请求的认证主体来自当前会话,不能用 `from` 参数冒充另一个主体。
25
- 2. 颁发者或组织实体的本地私钥、证书和证书指纹。SDK 的 signer 至少提供 `aid`、`certPem`、`certFingerprint` 和 `sign`。
26
- 3. 一个按证书指纹返回受信 X.509 证书的 resolver。resolver 可返回 PEM、DER 字节,或严格标准 Base64 DER。
27
- 4. 完整验证所需的状态、成员关系和 Ownership resolver。验证失败、状态未知或 resolver 不可用都按拒绝处理。
28
- 5. 若创建或转让组织,使用 `AIDStore` 保存组织实体的私钥和证书。组织服务不保存组织私钥,转让也不能把旧私钥复制给新 owner。
29
-
30
- 连接认证、AIDStore 和 token 生命周期沿用现有 SDK 文档;本文只覆盖凭证和组织业务。
13
+ 准备已连接客户端、本人 signer 和可信证书/状态 resolver;状态未知不授权。ownerSigner/memberSigner 属于当前会话,orgSigner 是 owner 本地组织实体身份;创建/转让使用固定持久 AIDStore。服务 target 使用 credential.{issuer}/org.{issuer},已签材料固定原请求和成员。
31
14
 
32
15
  ## 3. 凭证的应用流程
33
16
 
34
17
  ### 3.1 创建并保留完整凭证
35
18
 
36
- 凭证是签名对象 `aun-cap/1`。应用只向 `credential.create` 传入未签名字段和颁发者 signer;SDK 会补 `cid`、签发时间、根凭证默认字段和签名。`credential.sub` 必须是真正持有并使用凭证的 AID,不能改成 owner、代理人或服务 AID。
19
+ ```mermaid
20
+ flowchart LR
21
+ A[issuer 创建并签署 CAP] --> B[登记完整凭证]
22
+ B --> C[验证服务登记回执]
23
+ C --> D[交付 holder]
24
+ D --> E[每次请求完整 Verify]
25
+ E -->|全部检查通过| F[执行业务]
26
+ ```
37
27
 
38
28
  ```ts
39
- const credential = await client.credential.create({
40
- sub: holderAid, aud: [serviceAid], exp, key_version: signer.certFingerprint,
41
- cap: [{ ns: 'files', action: 'read', resource: '/reports', constraints: [] }]
42
- }, signer);
29
+ const credential = client.credential.create({
30
+ sub: holderAid, aud: [serviceAid], exp, key_version: issuerSigner.certFingerprint,
31
+ cap: [{ ns: 'files', action: 'read', resource: '/reports', constraints: [] }],
32
+ }, issuerSigner);
43
33
  ```
44
34
 
45
- 成员角色凭证不要手工拼装。先创建或取得完整 `membership_binding`,再调用 `org.member.createCredential`(Python/Go 为 `create_credential`/`CreateCredential`);helper 会固定 `iss`、`sub`、`aud`、`role.*` 能力和 `ext` 成员绑定字段,并拒绝冲突覆盖。
35
+ sub 是实际 holder;保存完整签名对象。成员 CAP 用 org.member.createCredential(binding, orgSigner, options),不手工拼装角色字段。
46
36
 
47
37
  ### 3.2 选择正确的验证级别
48
38
 
49
- `verifySignature` 只验证凭证结构、签名、证书指纹和可选时间/受众。它适合展示或接收前的快速预检,不能得出“当前请求有权执行”的结论。
39
+ `verifySignature` 仅做结构、证书指纹和签名预检,可选时间/受众;执行授权使用完整 `verify`:
50
40
 
51
- 完整 `verify` 必须提供:
41
+ ```ts
42
+ const checked = client.credential.verify(credential, {
43
+ ...trustedResolvers, ...actualRequest,
44
+ audience: serviceAid, subject: holderAid, rootIssuer: issuerAid,
45
+ ns: 'files', action: 'read', resource: '/reports',
46
+ });
47
+ ```
52
48
 
53
- - `audience`、实际 `subject`、`ns/action/resource`;
54
- - 实际 `method/target/params/request_id/nonce/request_binding`;
55
- - `resolveCertificate`;
56
- - 根/父凭证状态 resolver。存在 `parent` 时,父链必须使用受信强 `resolveStatusProof` resolver 返回的完整状态 proof,不能把原始 RPC 响应或字符串 `active` 当作父链证明。resolver 必须预先验证 Credential 服务签名、服务证书信任链和当前撤销状态,并确认 proof 对应实际查询的 `request_id`、nonce 和 target;SDK 再检查 proof 字段、CID/hash、状态及证明时间窗;
57
- - 成员凭证的当前 `membershipBinding` 和 `resolveMembershipStatus`;
58
- - 代表调用的 `actor`、`for`、`representationProof`、当前 Ownership resolver 和 actor 状态 resolver。
49
+ actualRequest 含真实 method/target/params/requestId/nonce/requestBinding。trustedResolvers 提供可信证书和当前状态;父链强 resolveStatusProof 须先验服务签名/信任/撤销及原查询,再由 SDK 核对 CID、全文 hash 和时间窗,不能返回裸 active。
59
50
 
60
- 完整验证依次检查签名、时间、audience、父链收窄、当前状态、能力约束、请求绑定、成员 binding 和代表关系。返回的 `signature_valid=true` 不覆盖任何后续检查;`CREDENTIAL_STATUS_UNKNOWN`、`CREDENTIAL_REQUEST_BINDING_INVALID`、`MEMBERSHIP_STATE_INVALID` 和 `ROLE_ACCESS_DENIED` 均应停止副作用操作。
51
+ 成员另传当前 membershipBinding/resolveMembershipStatus;代表调用另传 actor/for/representationProof 及当前 Ownership/actor 状态。任一步失败即停。
61
52
 
62
53
  ### 3.3 登记、回执和吊销
63
54
 
64
- Credential Service 只接受完整已签名凭证,不提供公开 `credential.prepare`。登记流程是:
55
+ registrationParams 为持久保存的完整请求:原 request_id/nonce、registrar_aid、credential、request_binding;转交另含 issuer 登记授权。SDK 无 credential.prepare,按 [RPC 手册](09-凭证服务RPC手册.md#credentialregister) 准备。
56
+
57
+ ```ts
58
+ import { isJsonObject } from '@agentunion/fastaun';
59
+ const registered = await client.credential.register(registrationParams);
60
+ if (!isJsonObject(registered)) throw new Error('登记响应无效');
61
+ client.credential.verifyRegistrationReceipt(
62
+ registered.registrationReceipt, credential, registrationParams,
63
+ resolveCertificate, credentialServiceAid,
64
+ );
65
+ ```
65
66
 
66
- 1. 颁发者直接调用 `credential.register`,或签署 `registration_authorization` 让指定服务转交。
67
- 2. 检查返回的 `registrationReceipt`:服务签名、`service_aid`、`registrar_aid=credential.iss`、CID、完整凭证摘要、原 `request_id`/nonce、状态和有效期必须全部匹配。
68
- 3. Org 入组最终化前再次验证回执。登记成功不等于成员已经 `active`。
69
- 4. 失败补偿使用原 CID、原操作上下文和明确吊销授权调用 `credential.revoke`;`NOT_FOUND` 或未知状态不能当作补偿完成。
67
+ 回执须匹配服务/issuer、CID/全文 hash、原请求、状态和有效期;Org 验回执并最终化后成员才 active。
70
68
 
71
- `credential.register`、`credential.revoke`、携带 `credential_cid` 的 `credential.status` 及 `credential.revocationList` 请求都必须携带 `request_id`、nonce 和 `request_binding`,绑定真实 method、target、参数摘要和时间窗。`credential.revocationList` 没有单一凭证目标,其 `request_binding.credential_cid` 固定为空字符串;`params_hash` 仍覆盖 `issuer_aid`、`cursor`、`limit`、`since_event_seq` 等全部业务参数。除该列表方法外,凡要求 `request_binding` 的 Credential 业务请求都必须绑定非空凭证 CID。状态 proof 有独立 `asOf/proofExpiresAt` 窗口;父链状态 proof 还必须包含 `credential_hash`、`request_id`、nonce、target、responder 和签名。状态未知时应用不得放行写操作。`revocationList` 用于增量补齐吊销事件,断序或证明过期时暂停受影响凭证的副作用操作。
69
+ ```ts
70
+ const result = await client.credential.revoke(revocationParams);
71
+ ```
72
+
73
+ revocationParams 含原 CID、吊销授权/原因及本次绑定。仅明确 revoked 算完成;NOT_FOUND/unknown 不算。原 method/request ID/摘要幂等恢复,不能换 ID。所有 Credential 请求绑定方法、服务、参数、请求及时间窗;仅 revocationList 的 CID 为空。
72
74
 
73
75
  ## 4. 组织成员流程
74
76
 
75
77
  ### 4.1 组织创建
76
78
 
77
- 创建组织需要两个身份:当前会话 owner signer,以及本地生成并保存的组织实体 signer。创建入口按 SDK 分别为 Python `client.org.lifecycle.create`、TypeScript/JavaScript `client.createOrg`、Go `client.CreateOrg`;TypeScript/JavaScript 的生命周期 facade 在提供 `aidStore` 时会转入高层创建流程,否则直接调用 `org.lifecycle.create`。按创建流程提供完整 binding、CAP 和授权材料,并完成实体主签、当前 owner token 上传的组织名片发布;低层请求应先用各端的 `org.prepareRequest`/`org.prepare_request` 准备,再调用对应 facade。
79
+ ```mermaid
80
+ flowchart LR
81
+ A[owner 会话和持久 AIDStore] --> B[生成并保存组织实体身份]
82
+ B --> C[准备 owner binding、CAP 和登记授权]
83
+ C --> D[Org 登记 CAP、验回执并创建组织]
84
+ D --> E[实体主签,owner token 上传名片]
85
+ ```
86
+
87
+ ```ts
88
+ const created = await ownerClient.createOrg(
89
+ { org_id: orgAid, name: '协作组织' }, { aidStore: ownerStore },
90
+ );
91
+ ```
78
92
 
79
- 组织名片使用 `aid=org_id`、`type=org`、当前 `owner` 和实体证书指纹。实体私钥生成主签并显式 signer_aid=org_id,当前 owner 以本人 token 上传,无需实体登录;可选一个或多个当前 owner 附签,存在就必须全块验证,取消实体额外 V2 上传授权。现代实体指纹严格匹配,Org 不开放旧实体上传;通用 Ownership facade 对组织实体返回 not_applicable。文件签验与 HTTP 多签协商见 [Ownership 应用指南](Ownership2.1-SDK应用集成指南.md#34-通用签验与多签名片) 及 [API 手册](06-API手册.md#通用-sign--verify)。
93
+ 组织名片实体主签、owner token 上传,含当前 owner/实体指纹,附签存在则全验。组织不走通用 Ownership 绑定,名片待办与创建结果分开。
80
94
 
81
95
  ### 4.2 申请加入与邀请
82
96
 
83
- 申请模式:
97
+ ```mermaid
98
+ sequenceDiagram
99
+ participant M as 成员 App
100
+ participant O as owner/管理员 App
101
+ participant G as Org 服务
102
+ participant C as Credential 服务
103
+ alt 成员申请
104
+ M->>G: join:成员签 binding
105
+ G-->>O: 待审批
106
+ O->>G: approveJoin:同条款组织签名、CAP、登记授权
107
+ else 组织邀请
108
+ O->>G: invite:每个目标独立 binding/CAP/登记授权
109
+ G-->>M: 原邀请材料
110
+ M->>G: inviteAccept:保留原材料,补目标成员签名
111
+ end
112
+ G->>C: 登记成员 CAP
113
+ C-->>G: 签名回执
114
+ G->>G: 验回执并最终化成员
115
+ G-->>M: active 与完整成员包
116
+ ```
117
+
118
+ 成员申请:
119
+
120
+ ```ts
121
+ const joinParams = memberClient.org.prepareRequest('org.member.join', {
122
+ org_id: orgAid, member_type: 'human', requested_role: 'member', terms,
123
+ }, orgServiceAid, memberSigner);
124
+ const application = await memberClient.org.member.join(joinParams);
125
+ ```
126
+
127
+ 审批端的 applicationBinding/terms 取原申请响应 application 内的 membership_binding/terms;ownerCredentials 为审批者当前 binding/CAP:
84
128
 
85
- 1. 成员创建 `membership_binding`,由成员 signer 签 `member_signature`。
86
- 2. owner/admin 对同一不可变条款签 `org_signature`,并准备完整成员 CAP 和登记授权。
87
- 3. 调用 `org.member.approveJoin`;服务登记 CAP、验证回执,然后完成成员关系。
129
+ ```ts
130
+ const binding = ownerClient.org.member.signBinding(applicationBinding, orgSigner, 'org');
131
+ const approval = ownerClient.org.prepareRequest('org.member.approveJoin', {
132
+ org_id: orgAid, terms, membership_binding: binding, credentials: ownerCredentials,
133
+ }, orgServiceAid, ownerSigner, { orgSigner });
134
+ await ownerClient.org.member.approveJoin(approval);
135
+ ```
88
136
 
89
- 邀请模式:
137
+ 邀请端复用原 invitation 的组织、binding、terms、CAP 模板和登记授权:
90
138
 
91
- 1. 组织 signer 为每个目标 AID 创建独立 binding、nonce、request ID 和 `org_signature`。
92
- 2. 目标成员签 `member_signature` 后调用 `org.member.inviteAccept`。
93
- 3. 服务完成登记和最终化。每个目标的 binding、CAP 和授权包不得互换。
139
+ ```ts
140
+ const accepted = memberClient.org.prepareRequest(
141
+ 'org.member.inviteAccept', invitation, orgServiceAid, memberSigner,
142
+ );
143
+ await memberClient.org.member.inviteAccept(accepted);
144
+ ```
94
145
 
95
- `org.member.join`/`inviteAccept` 的首次入组均使用以 `membership_id`、原 `request_id` 和 nonce 绑定的专用 admission request binding,不带 `credential_cid`,也不要求已有 active 成员 CAP。本人直接调用和代表调用都必须由目标成员私钥提供 `member_signature`;仅当 `for != signer.aid` 代表另一个目标时,才由认证 actor signer 签 admission representation proof,并通过当前 ownership/status 校验。本人直接 `inviteAccept` 复用邀请保存的组织签名、CAP 模板和登记授权,SDK 不重签或重造这些材料。owner 的代表证明不能替代目标成员签名,也不能把 `credential.sub` 改成 owner。
146
+ 首次入组绑定 membership_id 和原 request ID/nonce,不带 CID/已有 CAP。本人和代表均须目标成员签名;for≠signer.aid 另验代表证明和当前 Ownership/actor 状态。
96
147
 
97
148
  ### 4.3 查询、状态变更与续期
98
149
 
99
- 成员状态优先于角色和能力:`banned`/`ended` 拒绝授权,`frozen` 拒绝普通写操作但允许离职收尾,`offboarding` 只允许收尾动作。应用显示成员状态应使用 `org.member.get` 返回的签名 `membership_status`,不要仅凭历史 binding 或 CAP 状态判断当前成员资格。
150
+ ```mermaid
151
+ flowchart LR
152
+ A[同一成员关系,准备新 binding/CAP/登记授权] --> B[renewCredential:旧 CID+当前版本 CAS]
153
+ B --> C[登记新 CAP 并验回执]
154
+ C -->|成功| D[提交新成员版本,再撤旧 CAP]
155
+ C -->|失败| E[仅补偿撤新 CAP]
156
+ D --> F[立即保存完整新成员包]
157
+ ```
158
+
159
+ renewalMaterial 含旧 CID、expected_version、双签新 binding、terms、新 CAP/登记授权及当前调用授权:
100
160
 
101
- 成员离职/移除的正常顺序是 `leave` 或 `kick` → `offboard(confirm)` → 持久化 `ended` → 吊销本组织明确拥有撤销权限的成员 CAP → 删除 active projection。失败时保留后台续跑记录。
161
+ ```ts
162
+ const renewal = memberClient.org.prepareRequest(
163
+ 'org.member.renewCredential', renewalMaterial, orgServiceAid, memberSigner,
164
+ );
165
+ await memberClient.org.member.renewCredential(renewal);
166
+ const current = await memberClient.credential.current(memberCredential);
167
+ ```
168
+
169
+ 续期保持原成员关系,响应后立即持久完整成员包,credential.current 无需等事件。长期凭证 READY 后及在线每60秒扫描,显式短期凭证不自动续期。
102
170
 
103
- 原关系内换发使用 `org.member.renewCredential`:提交旧 CID、当前版本、完整新 binding、组织签名 CAP 和登记授权;新 CAP 登记并确认后才撤旧 CAP,失败只撤新 CAP。不要把 renew 当成重新加入,也不要给旧 CAP 全局豁免。
171
+ 当前资格看签名 membership_status:banned/ended 拒绝,frozen 禁普通写,offboarding 仅收尾。离职按 leave/kick→offboard→ended→撤有权吊销的 CAP→清 active projection,失败续跑。
104
172
 
105
173
  ## 5. 组织请求与跨设备代表
106
174
 
107
175
  ### 5.1 统一请求准备
108
176
 
109
- 需要业务授权或 request binding 的请求应调用 `prepareRequest`/`prepare_request`/`PrepareRequest`,不论它是读还是写。`org.member.list`、`org.member.get`、`org.credential.getStatus` 属于受保护业务读取,必须提供当前成员 binding 和对应 CAP,并准备 AAD、`request_binding` 与 `client_signature`。公开组织的 `org.lifecycle.list/get` 按可见性规则处理;`org.health/status` 是控制面诊断路径。首次 `org.member.join` 和 `org.member.inviteAccept` 无论本人还是代表调用,都使用 membership binding 中的 `request_id`/nonce 和 `membership_id` 专用 admission `request_binding`,不带 `credential_cid`;本人调用不需要 admission representation proof,也不要求已有 active 成员 CAP,`inviteAccept` 复用邀请保存的组织签名、CAP 模板和登记授权。只有代表目标节点(`for != signer.aid`)才生成 admission representation proof,并通过当前 ownership/status 校验。准备函数负责:
177
+ ```mermaid
178
+ flowchart LR
179
+ A[业务参数+本次授权包] --> B[prepareRequest:原 ID/nonce、AAD、request binding]
180
+ B --> C[必要时补代表证明]
181
+ C --> D[RPC 管线生成外层 client_signature]
182
+ D --> E[Gateway service-plane]
183
+ E --> F[服务独立重算签名、摘要和当前权限]
184
+ ```
110
185
 
111
- - 自动生成或复用 `request_id`、nonce;锚定入组流程时必须与 binding 一致;
112
- - 为所有 `org.*` 请求加入 `aad.org_id` 并拒绝不匹配的已有 AAD;仅 `org.lifecycle.list` 及 health/status 路径允许 `org_id:null`,`org.member.list` 仍必须绑定具体 `org_id`;
113
- - 生成 `request_binding`,其 `params_hash` 覆盖真实业务参数、AAD 和授权包,排除 `request_binding`、`client_signature`、`_` 前缀字段,并排除 `credentials.representation_proof` 避免循环;
114
- - 在需要时生成 membership binding、member CAP、registration authorization 和 representation proof;已有签名或 binding 冲突直接拒绝,不重写原材料。
186
+ 受保护读取也须准备请求,例如查询自己的成员状态:
115
187
 
116
- 随后把返回 params 原样交给 `client.call` 或对应 facade。客户端 RPC 管线会为 `org.*` 自动生成 `client_signature`;应用不要把该字段提前复制到另一个请求,也不要改写已准备的摘要。
188
+ ```ts
189
+ const params = memberClient.org.prepareRequest('org.member.get', {
190
+ org_id: orgAid, member_aid: memberSigner.aid, credentials: memberCredentials,
191
+ }, orgServiceAid, memberSigner);
192
+ const member = await memberClient.org.member.get(params);
193
+ ```
194
+
195
+ 准备后原样发送,RPC 管线补 client_signature。受保护读取也需当前 binding/CAP;公开 lifecycle.get/list 按可见性处理。AAD 绑定 org_id,仅 lifecycle.list/health/status 可为 null。
117
196
 
118
197
  ### 5.2 代表操作
119
198
 
120
- `for` 是业务目标,不是认证身份。当前会话 actor 代表另一个 AID 时,SDK 必须绑定:`from`、`for`、`represented`、实际服务 target、method、params_hash、nonce 和时间窗;使用已有 CAP 的代表请求绑定 credential CID,首次入组 admission 请求绑定 `membership_id`。服务端还要通过受信 Ownership 和 actor 状态 resolver 确认 actor 当前有权代表目标;封禁、状态未知或 resolver 缺失均拒绝。
199
+ 参数增加 for: holderAid,授权包仍属 holder。prepareRequest 绑定双方、方法、服务、摘要和时间窗;首次 admission 绑定 membership_id,其他代表绑定 CID。owner 不能替代目标成员签名。
121
200
 
122
201
  ### 5.3 服务事件
123
202
 
124
- Credential/Org 事件先独立验证 responder、目标 AID、时间窗、服务证书和签名,再进入 SDK 去重/handler。去重键包含 responder、event_id 和当前 AID;事件过期、证书不可信或未知凭证事件不能触发本地授权更新。
203
+ SDK 验服务、接收 AID、证书、签名和时间窗后去重;撤销同步如下:
204
+
205
+ ```mermaid
206
+ flowchart LR
207
+ A[撤销推送/已签列表页] --> B[验签及身份/连接代次复核]
208
+ B --> C[按 authority、CID 保留最大 event_seq]
209
+ C --> D[持久保存快照]
210
+ D --> E[后续授权检查使用]
211
+ ```
212
+
213
+ 单条推送不推进分页,旧页不覆盖新证据,本地缺 CID 不证明有效。连接后一小时首次兜底拉列表,之后每小时;重连重新计时,与60秒凭证扫描独立。
125
214
 
126
215
  ## 6. 所有权转让与实体材料
127
216
 
128
- 转让不是一次普通 RPC:
217
+ ```mermaid
218
+ sequenceDiagram
219
+ participant O as 原 owner
220
+ participant N as 目标 owner SDK
221
+ participant G as Org 服务
222
+ participant CA as CA
223
+ O->>G: transfer:当前授权请求
224
+ G-->>N: transfer proposal
225
+ N->>N: 签接受材料,持久保存新 P-256 私钥与 checkpoint
226
+ N->>G: transferAccept stage=rekey
227
+ G->>CA: 复核代际并提交新公钥
228
+ CA-->>G: 新实体证书
229
+ G-->>N: pending_finalization 与新证书
230
+ N->>N: 导入证书,重签新旧 owner binding/CAP
231
+ N->>G: stage=finalize,独立持久 request ID
232
+ G->>G: 新 owner 生效,旧 owner 降 member,撤旧 CAP
233
+ N->>N: 新实体主签,owner token 上传名片
234
+ ```
129
235
 
130
- 1. 目标 owner 在本地持久生成新的 P-256 私钥。
131
- 2. `transferAccept(stage=rekey)` 提交新 SPKI 公钥和旧 owner 降级预检材料。
132
- 3. 服务返回新证书和 `pending_finalization`;目标 owner 导入新证书。
133
- 4. 用新实体 signer 重签双方 binding/CAP,准备新的登记授权,以独立请求标识调用 `stage=finalize`。
134
- 5. 成功后原 owner 降为 member,旧 CAP 持久吊销;新 owner 重新上传实体名片。
236
+ 原 owner 准备并调用 org.lifecycle.transfer;目标验证 proposal,用 signTransferAcceptance 签接受字段。transferParams 保留这些字段、原 transfer_id、双方完整成员材料及授权包:
135
237
 
136
- 四端高层流程会把输入摘要、proposal、阶段 params 和私钥 checkpoint 保存到本地。恢复时 transfer ID、owner、输入摘要、公钥和阶段上下文必须一致;材料变化返回 conflict,不发新 RPC。服务断线不应重新生成另一把 key 或重复创建另一份 proposal。
238
+ ```ts
239
+ const transferred = await targetClient.completeOrgTransfer(
240
+ transferParams, { aidStore: targetStore },
241
+ );
242
+ ```
243
+
244
+ 恢复沿用原 transfer ID、输入、阶段参数和私钥;缺 key 报 persistence_unavailable,材料变化报 conflict,TS/JS 精确完成态可重放。详见 [移植 §6](凭证与组织服务SDK开发与移植指南.md#6-高层实体身份和转让编排)。
137
245
 
138
- 解散高层入口以当前 signer 和调用方提供的当前成员 binding/CAP 准备业务授权请求,补齐 request ID、nonce、AAD 和 `request_binding`,核验已有请求绑定并保留原成员材料。仅在服务确认 `dissolved` 后,四端记录当前实体证书指纹失效并清理创建/转让 checkpoint、待上传名片和当前设备/slot 恢复状态;保留磁盘私钥,已加载的 AID/signer 不追溯失效,后续 `AIDStore.load` 拒绝该证书。创建或转让后的名片待办保存完整多签原文、原 CAS、固定 owner 与实体证书指纹,由应用显式重试,重连不自动 PUT。重试核对当前生命周期与证书代际,原条件完整且同代际全文/ETag 已证明提交时只观察完成;转移、rekey 或解散后停止旧待办,不换身份、字节或条件重签。专属 create/transfer 自身 checkpoint 恢复机制不变。取消额外 V2 授权及其过期窗口,组织成员 binding/CAP 签名规则不变。
246
+ 解散用 client.dissolveOrg(params, { aidStore }),提供当前 binding/CAP;确认 dissolved 后才失效本地证书并清恢复状态,保留磁盘私钥。名片失败稿保留完整多签、固定 owner/代际和原 CAS,仅显式重试,重连不 PUT;代际变化停止旧待办。
139
247
 
140
248
  ## 7. 四端入口速查
141
249
 
142
- | 能力 | Python | TypeScript | JavaScript | Go |
143
- |---|---|---|---|---|
144
- | 凭证 facade | `client.credential` | `client.credential` | `client.credential` | `client.Credential()` |
145
- | 组织 facade | `client.org` | `client.org` | `client.org` | `client.Org()` |
146
- | 请求准备 | `org.prepare_request` | `org.prepareRequest` | `org.prepareRequest` | `org.PrepareRequest` |
147
- | binding | `create_binding/sign_binding` | `createBinding/signBinding` | `createBinding/signBinding` | `CreateBinding/SignBinding` |
148
- | 成员 CAP | `create_credential` | `createCredential` | `createCredential` | `CreateCredential` |
149
- | 完整验证 | `credential.verify` | `credential.verify` | `credential.verify` | `Credential().Verify` |
150
- | 转让签名 | `sign_transfer_acceptance` | `signTransferAcceptance` | `signTransferAcceptance` | `SignTransferAcceptance` |
250
+ | 能力 | Python | TS/JS | Go |
251
+ | --- | --- | --- | --- |
252
+ | 业务入口 | client.credential/org | client.credential/org | client.Credential()/Org() |
253
+ | 请求准备 | org.prepare_request | org.prepareRequest | Org().PrepareRequest |
254
+ | 组织创建/转让 | org.lifecycle.create/transfer_accept | createOrg/completeOrgTransfer | CreateOrg/CompleteOrgTransfer |
151
255
 
152
- Python RPC helper 是 async;浏览器 JS 的密码学 helper 返回 Promise;Node.js TypeScript helper 同步;Go 返回 `(value, error)`。协议字段和错误码必须保持一致,不能把语言异步差异写入 wire 格式。
256
+ Node TS 协议 helper 同步,浏览器密码 helper 为 Promise;Python RPC async/协议 helper 同步,Go 返回 value/error。文件 AIDStore.sign/verify 的 TS/JS 均须 await。
153
257
 
154
258
  ## 8. 错误与重试
155
259
 
156
- - 只重试读请求,或同一 `request_id`、同一 method、同一摘要的幂等重试。
157
- - `CREDENTIAL_IDEMPOTENCY_KEY_REUSE`、签名错误、权限拒绝、binding 冲突和成员状态拒绝不重试。
158
- - `CREDENTIAL_STATUS_UNKNOWN`、服务不可用、数据库不可用可在状态窗口内重试,但重试前重新确认 resolver 和证书;不要降级为 allow。
159
- - 记录 CID、receipt_id、membership_id、request_id 和摘要即可;不把私钥、token 或完整凭证写入普通日志。
160
- - RPC 成败看结构化 error/exit code,不解析展示文本。
260
+ 仅重试读取或原 method/request ID/摘要不变的幂等操作。签名/权限/binding/状态/幂等冲突不盲重试;未知暂缓副作用,创建补偿遇幂等冲突停自动补偿。
161
261
 
162
- ## 9. 验收清单
262
+ 跨期恢复只确认原期限内已持久且已发送的既成结果,不重登记/重签。无原回执时只保存 issuer 结果,holder 交付仍需原有效回执,边界见 [移植 §4.2](凭证与组织服务SDK开发与移植指南.md#42-登记授权和回执)。
163
263
 
164
- 应用上线前至少验证:
165
-
166
- - 离线签名预检与完整 Verify 的分界;父链强 status proof;成员状态和代表状态未知均拒绝;
167
- - 登记回执的服务签名、CID/hash、registrar、request_id/nonce 和有效期;失败补偿能得到明确 revoked 结果;
168
- - join 和 invite 的双方签名、每目标独立 binding、首次 admission 的 target signature;
169
- - client signature、AAD、request binding 的摘要重算与跨语言向量一致;
170
- - transfer rekey/finalize 断线恢复、私钥 checkpoint、旧 owner 降级和名片重新上传;
171
- - 服务未部署、服务证书无效、Credential 状态未知、组织数据库不可用时均 fail-closed。
264
+ ## 9. 验收清单
172
265
 
173
- 相关协议、共同向量和服务验收见 [组织服务 0.8 详细设计](../../../extensions/services/docs/org/0.8/17-凭证与组织服务详细设计.md)、[TDD 实施计划](../../../extensions/services/docs/org/0.8/18-凭证与组织服务TDD实施计划.md) 和 [四 SDK 对齐变更清单](../../python/CHANGES_FOR_PARITY.md)。
266
+ 覆盖完整 Verify、回执、双签入组、受保护读取、撤销乱序/重启、续期完整包、转让两阶段丢响应。运行见 [测试指南](../aun测试运行指南.md),版本边界见 [四端对齐清单](../../python/CHANGES_FOR_PARITY.md)。