@agentunion/fastaun 0.5.25 → 0.5.27

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 (76) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/_packed_docs/CHANGELOG.md +41 -0
  3. package/_packed_docs/INDEX.md +22 -14
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +11 -6
  5. 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 +16 -1
  6. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +37 -9
  7. package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +20 -9
  8. package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +57 -12
  9. package/_packed_docs/cli//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241CLI/345/274/200/345/217/221/344/270/216/344/275/277/347/224/250/346/214/207/345/215/227.md +869 -0
  10. 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 +2 -2
  11. package/_packed_docs/sdk/0.5.27-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +408 -0
  12. package/_packed_docs/sdk/0.5.27-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +410 -0
  13. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +2 -2
  14. package/_packed_docs/sdk/09-/345/207/255/350/257/201/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +187 -73
  15. package/_packed_docs/sdk/09-/347/273/204/347/273/207/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +1 -1
  16. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +13 -9
  17. package/_packed_docs/sdk/INDEX.md +21 -13
  18. package/_packed_docs/sdk/agent.md/344/270/216group.index/347/232/204ETag/350/247/202/345/257/237/344/270/216/345/220/214/346/255/245/346/234/272/345/210/266.md +240 -0
  19. 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 +973 -266
  20. 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 +950 -242
  21. package/dist/agent-md-schema.js +1 -1
  22. package/dist/agent-md-schema.js.map +1 -1
  23. package/dist/agent-md.js +5 -0
  24. package/dist/agent-md.js.map +1 -1
  25. package/dist/aid.js +3 -3
  26. package/dist/aid.js.map +1 -1
  27. package/dist/auth.js +21 -19
  28. package/dist/auth.js.map +1 -1
  29. package/dist/cert-utils.d.ts +1 -1
  30. package/dist/cert-utils.js +4 -4
  31. package/dist/cert-utils.js.map +1 -1
  32. package/dist/client/lifecycle.d.ts +1 -1
  33. package/dist/client/lifecycle.js.map +1 -1
  34. package/dist/client/rpc-pipeline.js +8 -1
  35. package/dist/client/rpc-pipeline.js.map +1 -1
  36. package/dist/client/v2-e2ee.js +7 -0
  37. package/dist/client/v2-e2ee.js.map +1 -1
  38. package/dist/client.d.ts +12 -0
  39. package/dist/client.js +305 -29
  40. package/dist/client.js.map +1 -1
  41. package/dist/facades.d.ts +38 -0
  42. package/dist/facades.js +49 -5
  43. package/dist/facades.js.map +1 -1
  44. package/dist/index.d.ts +4 -0
  45. package/dist/index.js +3 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/keystore/local-identity-store.js +16 -1
  48. package/dist/keystore/local-identity-store.js.map +1 -1
  49. package/dist/keystore/local-token-store.js +16 -1
  50. package/dist/keystore/local-token-store.js.map +1 -1
  51. package/dist/org-protocol.d.ts +1 -0
  52. package/dist/org-protocol.js +39 -36
  53. package/dist/org-protocol.js.map +1 -1
  54. package/dist/ownership-v21.js +7 -7
  55. package/dist/ownership-v21.js.map +1 -1
  56. package/dist/register-flow.js +2 -2
  57. package/dist/register-flow.js.map +1 -1
  58. package/dist/semantic-facade.d.ts +176 -0
  59. package/dist/semantic-facade.js +611 -0
  60. package/dist/semantic-facade.js.map +1 -0
  61. package/dist/semantic-protocol.d.ts +810 -0
  62. package/dist/semantic-protocol.js +894 -0
  63. package/dist/semantic-protocol.js.map +1 -0
  64. package/dist/tools/cross-sdk-agent.d.ts +11 -1
  65. package/dist/tools/cross-sdk-agent.js +388 -7
  66. package/dist/tools/cross-sdk-agent.js.map +1 -1
  67. package/dist/transport.d.ts +1 -0
  68. package/dist/transport.js +28 -2
  69. package/dist/transport.js.map +1 -1
  70. package/dist/v2/e2ee/decrypt.d.ts +5 -0
  71. package/dist/v2/e2ee/decrypt.js +22 -2
  72. package/dist/v2/e2ee/decrypt.js.map +1 -1
  73. package/dist/version.d.ts +1 -1
  74. package/dist/version.js +1 -1
  75. package/package.json +2 -1
  76. package/src/certs/root.crt +13 -0
@@ -1,266 +1,973 @@
1
- # 凭证与组织服务 SDK 应用集成指南
2
-
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)。
4
-
5
- ## 1. 先确认交付边界
6
-
7
- `client.credential` 处理凭证,`client.org` 处理组织/成员及请求准备。业务走 Gateway service-plane,Kernel 只做诊断;带 CID 的 credential.status 是业务查询。先确认服务已部署。
8
-
9
- 保留的 org.resource.create/task.create/host.add/workflow.create 返回 NOT_IMPLEMENTED,其他未注册方法返回 Method not found。
10
-
11
- ## 2. 运行前准备
12
-
13
- 准备已连接客户端、本人 signer 和可信证书/状态 resolver;状态未知不授权。ownerSigner/memberSigner 属于当前会话,orgSigner 是 owner 本地组织实体身份;创建/转让使用固定持久 AIDStore。服务 target 使用 credential.{issuer}/org.{issuer},已签材料固定原请求和成员。
14
-
15
- ## 3. 凭证的应用流程
16
-
17
- ### 3.1 创建并保留完整凭证
18
-
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
- ```
27
-
28
- ```ts
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);
33
- ```
34
-
35
- sub 是实际 holder;保存完整签名对象。成员 CAP 用 org.member.createCredential(binding, orgSigner, options),不手工拼装角色字段。
36
-
37
- ### 3.2 选择正确的验证级别
38
-
39
- `verifySignature` 仅做结构、证书指纹和签名预检,可选时间/受众;执行授权使用完整 `verify`:
40
-
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
- ```
48
-
49
- actualRequest 含真实 method/target/params/requestId/nonce/requestBinding。trustedResolvers 提供可信证书和当前状态;父链强 resolveStatusProof 须先验服务签名/信任/撤销及原查询,再由 SDK 核对 CID、全文 hash 和时间窗,不能返回裸 active。
50
-
51
- 成员另传当前 membershipBinding/resolveMembershipStatus;代表调用另传 actor/for/representationProof 及当前 Ownership/actor 状态。任一步失败即停。
52
-
53
- ### 3.3 登记、回执和吊销
54
-
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
- ```
66
-
67
- 回执须匹配服务/issuer、CID/全文 hash、原请求、状态和有效期;Org 验回执并最终化后成员才 active。
68
-
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 为空。
74
-
75
- ## 4. 组织成员流程
76
-
77
- ### 4.1 组织创建
78
-
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
- ```
92
-
93
- 组织名片实体主签、owner token 上传,含当前 owner/实体指纹,附签存在则全验。组织不走通用 Ownership 绑定,名片待办与创建结果分开。
94
-
95
- ### 4.2 申请加入与邀请
96
-
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:
128
-
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
- ```
136
-
137
- 邀请端复用原 invitation 的组织、binding、terms、CAP 模板和登记授权:
138
-
139
- ```ts
140
- const accepted = memberClient.org.prepareRequest(
141
- 'org.member.inviteAccept', invitation, orgServiceAid, memberSigner,
142
- );
143
- await memberClient.org.member.inviteAccept(accepted);
144
- ```
145
-
146
- 首次入组绑定 membership_id 和原 request ID/nonce,不带 CID/已有 CAP。本人和代表均须目标成员签名;for≠signer.aid 另验代表证明和当前 Ownership/actor 状态。
147
-
148
- ### 4.3 查询、状态变更与续期
149
-
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/登记授权及当前调用授权:
160
-
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秒扫描,显式短期凭证不自动续期。
170
-
171
- 当前资格看签名 membership_status:banned/ended 拒绝,frozen 禁普通写,offboarding 仅收尾。离职按 leave/kick→offboard→ended→撤有权吊销的 CAP→清 active projection,失败续跑。
172
-
173
- ## 5. 组织请求与跨设备代表
174
-
175
- ### 5.1 统一请求准备
176
-
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
- ```
185
-
186
- 受保护读取也须准备请求,例如查询自己的成员状态:
187
-
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。
196
-
197
- ### 5.2 代表操作
198
-
199
- 参数增加 for: holderAid,授权包仍属 holder。prepareRequest 绑定双方、方法、服务、摘要和时间窗;首次 admission 绑定 membership_id,其他代表绑定 CID。owner 不能替代目标成员签名。
200
-
201
- ### 5.3 服务事件
202
-
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秒凭证扫描独立。
214
-
215
- ## 6. 所有权转让与实体材料
216
-
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
- ```
235
-
236
- 原 owner 准备并调用 org.lifecycle.transfer;目标验证 proposal,用 signTransferAcceptance 签接受字段。transferParams 保留这些字段、原 transfer_id、双方完整成员材料及授权包:
237
-
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-高层实体身份和转让编排)。
245
-
246
- 解散用 client.dissolveOrg(params, { aidStore }),提供当前 binding/CAP;确认 dissolved 后才失效本地证书并清恢复状态,保留磁盘私钥。名片失败稿保留完整多签、固定 owner/代际和原 CAS,仅显式重试,重连不 PUT;代际变化停止旧待办。
247
-
248
- ## 7. 四端入口速查
249
-
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 |
255
-
256
- Node TS 协议 helper 同步,浏览器密码 helper 为 Promise;Python RPC async/协议 helper 同步,Go 返回 value/error。文件 AIDStore.sign/verify 的 TS/JS 均须 await。
257
-
258
- ## 8. 错误与重试
259
-
260
- 仅重试读取或原 method/request ID/摘要不变的幂等操作。签名/权限/binding/状态/幂等冲突不盲重试;未知暂缓副作用,创建补偿遇幂等冲突停自动补偿。
261
-
262
- 跨期恢复只确认原期限内已持久且已发送的既成结果,不重登记/重签。无原回执时只保存 issuer 结果,holder 交付仍需原有效回执,边界见 [移植 §4.2](凭证与组织服务SDK开发与移植指南.md#42-登记授权和回执)。
263
-
264
- ## 9. 验收清单
265
-
266
- 覆盖完整 Verify、回执、双签入组、受保护读取、撤销乱序/重启、续期完整包、转让两阶段丢响应。运行见 [测试指南](../aun测试运行指南.md),版本边界见 [四端对齐清单](../../python/CHANGES_FOR_PARITY.md)。
1
+ # 凭证与组织服务 SDK 应用集成指南
2
+
3
+ Org `0.8`;本文对齐当前工作区四 SDK(包元数据 `0.5.27`),不据此声明扩展已发布。§3为结构化凭证,§4为语义凭证,§5—§7为组织流程。下文使用 Node TS;字段见 [Credential RPC](09-凭证服务RPC手册.md)/[Org RPC](09-组织服务RPC手册.md),内部实现见 [移植指南](凭证与组织服务SDK开发与移植指南.md)。
4
+
5
+ | 模式 | 版本 | 授权验收 |
6
+ | --- | --- | --- |
7
+ | 结构化凭证 | `aun-cap/1` | 非空 cap,按能力、约束、来源链与当前状态确定性验收 |
8
+ | 纯语义凭证 | `aun-cap/semantic-1` | cap=[],正文、确认元数据与业务复核 |
9
+ | 混合凭证 | `aun-cap/semantic-1` | 非空 cap 与正文限制取交集 |
10
+
11
+ ## 1. 先确认交付边界
12
+
13
+ `client.credential` 处理凭证,`client.org` 处理组织/成员及请求准备。业务走 Gateway service-plane,Kernel 只做诊断;带 CID 的 credential.status 是业务查询。先确认服务已部署。
14
+
15
+ 保留的 org.resource.create/task.create/host.add/workflow.create 返回 NOT_IMPLEMENTED,其他未注册方法返回 Method not found。
16
+
17
+ ## 2. 运行前准备
18
+
19
+ 准备已连接客户端、本人 signer 和可信证书/状态 resolver;状态未知不授权。ownerSigner/memberSigner 属于当前会话,orgSigner 是 owner 本地组织实体身份;创建/转让使用固定持久 AIDStore。服务 target 使用 credential.{issuer}/org.{issuer},已签材料固定原请求和成员。
20
+
21
+ ## 3. 结构化凭证接入
22
+
23
+ ### 3.1 非空约束与根凭证
24
+
25
+ ```mermaid
26
+ flowchart LR
27
+ A[issuer 确定主体、受众、能力与约束] --> B[create 签署完整根 CAP]
28
+ B --> C[登记并验服务回执]
29
+ C --> D{使用方式}
30
+ D -->|直接使用| E[holder 每次请求完整 Verify]
31
+ D -->|允许委托| F[根 holder 签署收窄的子 CAP]
32
+ F --> G[子 CAP 登记,交付新 holder]
33
+ G --> E
34
+ ```
35
+
36
+ 本节使用同域 CN 客户端 issuerClient/delegateClient/holderClient/relayClient;对应 signer 由各自真实身份提供。app.save 保存材料,app.structured 封装[普通状态证明](凭证与组织服务SDK开发与移植指南.md#65-普通状态证明的可信适配)及[普通 CRL](凭证与组织服务SDK开发与移植指南.md#66-普通-crl-分页与原子持久)适配,认证会话闭包中的 queryActorAid 固定为 holderAid。
37
+
38
+ ```ts
39
+ import { randomBytes as capRandomBytes, randomUUID as capRandomUUID } from 'node:crypto';
40
+ import { isJsonObject, type JsonObject } from '@agentunion/fastaun';
41
+ import { buildRequestBinding, canonicalJson as capCanonical,
42
+ digest as capDigest } from '../../ts/src/org-protocol.js';
43
+ const credentialServiceAid = 'credential.agentid.cn';
44
+ const capNow = Math.trunc(Date.now() / 1000);
45
+ ```
46
+
47
+ org-protocol.js 的相对路径是仓库参考实现;npm 应用按[移植指南 §5.4](凭证与组织服务SDK开发与移植指南.md#54-credential-request-binding)在应用适配层封装同一绑定规则。
48
+
49
+ ```ts
50
+ const rootCredential = issuerClient.credential.create({
51
+ sub: delegateSigner.aid, aud: [businessAid], delegate: true,
52
+ key_version: issuerSigner.certFingerprint,
53
+ cap: [{ ns: 'files', action: 'read', resource: '/reports', constraints: [
54
+ { type: 'max_value', field: 'rows', value: 100 },
55
+ { type: 'allowed_values', field: 'format', value: ['csv', 'json'] },
56
+ ] }],
57
+ }, issuerSigner);
58
+ await app.save('structured-root', rootCredential);
59
+ ```
60
+
61
+ cap 限定命名空间/动作/资源;constraints 绑定实际请求字段。本例根凭证使用证书截止时间作为 exp,进入长期管理记录;显式短期 exp 按签署时给定期限使用。
62
+
63
+ ### 3.2 根到子:委托收窄
64
+
65
+ ```mermaid
66
+ flowchart LR
67
+ A[根 sub 是本次子凭证签署者,根 delegate=true] --> B[固定 parent CID 与完整 proof_chain]
68
+ B --> C[受众、期限、能力、约束逐项收窄]
69
+ C --> D[create 签署子 CAP]
70
+ D --> E[完整 Verify 同时检查叶与全部父级]
71
+ ```
72
+
73
+ ```ts
74
+ const credential = delegateClient.credential.create({
75
+ sub: holderAid, aud: [businessAid], parent: rootCredential.cid,
76
+ proof_chain: [rootCredential], delegate: false,
77
+ exp: Math.min(Number(rootCredential.exp), capNow + 1800),
78
+ key_version: delegateSigner.certFingerprint,
79
+ cap: [{ ns: 'files', action: 'read', resource: '/reports', constraints: [
80
+ { type: 'max_value', field: 'rows', value: 10 },
81
+ { type: 'allowed_values', field: 'format', value: ['csv'] },
82
+ ] }],
83
+ }, delegateSigner);
84
+ ```
85
+
86
+ | 项目 | 根 → 子 |
87
+ | --- | --- |
88
+ | 主体链 | 子 iss=根 sub;子 sub=最终 holder |
89
+ | 能力与约束 | rows≤100 → rows≤10;csv/json → csv |
90
+ | 时间与受众 | 子窗口位于父窗口内,子 aud 属于父 aud |
91
+ | 来源链 | proof_chain 为直接 parent→root;最大深度 8 |
92
+ | 成员 CAP | 用 org.member.createCredential 创建,保留其专用成员绑定流程 |
93
+
94
+ ### 3.3 普通请求绑定、登记与回执
95
+
96
+ ```mermaid
97
+ sequenceDiagram
98
+ participant I as 签发者
99
+ participant R as 转交者
100
+ participant C as Credential 服务
101
+ I->>I: 固定原件、request_id、nonce 与请求参数
102
+ alt 签发者直接登记
103
+ I->>C: credential.register+request_binding
104
+ C-->>I: 登记回执
105
+ I->>I: 验服务签名、CID/全文 hash、原请求及窗口
106
+ else 转交登记
107
+ I->>I: 签登记授权,绑定原件 hash/转交者/原请求
108
+ I->>R: 完整原件、授权与固定请求
109
+ R->>C: credential.register+request_binding
110
+ C-->>R: 登记回执
111
+ R->>R: 验服务签名、CID/全文 hash、原请求及窗口
112
+ end
113
+ ```
114
+
115
+ 文内 credentialRequest 是应用封装,绑定前的 fields 已包含全部业务字段:
116
+
117
+ ```ts
118
+ function credentialRequest(method: string, credentialCid: string, fields: JsonObject): JsonObject {
119
+ const now = Math.trunc(Date.now() / 1000);
120
+ const input = { ...fields, request_id: capRandomUUID(),
121
+ nonce: capRandomBytes(32).toString('base64url') };
122
+ return { ...input, request_binding: buildRequestBinding(method, credentialServiceAid,
123
+ input, credentialCid, input.nonce, input.request_id, now, now + 300) as JsonObject };
124
+ }
125
+ ```
126
+
127
+ 根由原签发者直接登记:
128
+
129
+ ```ts
130
+ const rootRegistration = credentialRequest('credential.register', String(rootCredential.cid), {
131
+ registrar_aid: issuerSigner.aid, credential: rootCredential,
132
+ });
133
+ await app.save('structured-root-registration', rootRegistration);
134
+ const rootRegistered = await issuerClient.credential.register(rootRegistration);
135
+ if (!isJsonObject(rootRegistered)) throw new Error('登记响应无效');
136
+ issuerClient.credential.verifyRegistrationReceipt(rootRegistered.registrationReceipt,
137
+ rootCredential, rootRegistration, resolveCertificate, credentialServiceAid);
138
+ ```
139
+
140
+ 子凭证演示转交登记,registrar_aid 始终为子凭证签发者;先固定授权绑定的请求:
141
+
142
+ ```ts
143
+ const registrationCore = { request_id: capRandomUUID(), nonce: capRandomBytes(32).toString('base64url'),
144
+ registrar_aid: delegateSigner.aid, credential };
145
+ const authorizationCore = { ver: 'aun-credential-registration-authorization/1',
146
+ issuer_aid: delegateSigner.aid, credential_cid: credential.cid,
147
+ credential_hash: capDigest(credential), request_id: registrationCore.request_id,
148
+ nonce: registrationCore.nonce, target: credentialServiceAid, relay_aid: relaySigner.aid,
149
+ iat: capNow, exp: capNow + 300 };
150
+ const authorizationSignature = delegateSigner.sign(Buffer.from(capCanonical(authorizationCore)));
151
+ if (!authorizationSignature.ok) throw new Error('登记授权签名失败');
152
+ ```
153
+
154
+ ```ts
155
+ const registrationFields = { ...registrationCore, registration_authorization: {
156
+ ...authorizationCore, signature: { cert_fingerprint: delegateSigner.certFingerprint,
157
+ timestamp: capNow, signature: authorizationSignature.data.signature } } };
158
+ const registrationParams = { ...registrationFields, request_binding: buildRequestBinding(
159
+ 'credential.register', credentialServiceAid, registrationFields, String(credential.cid),
160
+ registrationCore.nonce, registrationCore.request_id, capNow, capNow + 300) as JsonObject };
161
+ await app.save('structured-child-registration', registrationParams);
162
+ const childRegistered = await relayClient.credential.register(registrationParams);
163
+ ```
164
+
165
+ ```ts
166
+ if (!isJsonObject(childRegistered)) throw new Error('登记响应无效');
167
+ relayClient.credential.verifyRegistrationReceipt(childRegistered.registrationReceipt,
168
+ credential, registrationParams, resolveCertificate, credentialServiceAid);
169
+ await app.save('structured-child-registration-result', childRegistered);
170
+ await app.transport.sendEncrypted(holderAid, { credential, registrationReceipt: childRegistered.registrationReceipt });
171
+ ```
172
+
173
+ resolveCertificate 预加载服务与原签署者的可信证书;证书信任/撤销按实际签署时点验证。原件、登记授权、request_id/nonce/绑定及回执一并保存。
174
+
175
+ ### 3.4 普通状态查询与强证明
176
+
177
+ ```mermaid
178
+ flowchart LR
179
+ A[叶 CAP 与直接 parent 到 root] --> B[每个 CID 独立 status 查询绑定]
180
+ B --> C[验证服务证书信任、撤销与证明签名]
181
+ C --> D[核对查询者、ID/nonce、服务、CID/全文 hash 和窗口]
182
+ D --> E[缓存本次已验证完整 proof]
183
+ E --> F[resolveStatusProof 提供给完整 Verify]
184
+ ```
185
+
186
+ ```ts
187
+ const checkedStatusProofs = new Map<string, Record<string, unknown>>();
188
+ for (const document of [credential, rootCredential]) {
189
+ const statusInput = credentialRequest('credential.status', String(document.cid), {
190
+ credential_cid: document.cid,
191
+ });
192
+ await app.save('structured-status:' + String(document.cid), statusInput);
193
+ const rawStatus = await holderClient.credential.status(statusInput);
194
+ checkedStatusProofs.set(String(document.cid), await app.structured.verifyStatus(
195
+ rawStatus, document, statusInput, credentialServiceAid));
196
+ }
197
+ ```
198
+
199
+ verifyStatus 委托[verifyStructuredStatus](凭证与组织服务SDK开发与移植指南.md#65-普通状态证明的可信适配),仅将已验真且 active 的完整 aun-credential-status/1 proof 放入 Map。proof.target 为真实查询者 holderAid,request_binding.target 为 Credential 服务。每次执行前重取或复核窗口内的证明。
200
+
201
+ ### 3.5 实际业务请求与完整 Verify
202
+
203
+ ```mermaid
204
+ flowchart LR
205
+ A[认证收件取得 actor 与实际业务参数] --> B[固定 method/target/CID/ID/nonce/窗口]
206
+ B --> C[预加载可信证书与全部 status proof]
207
+ C --> D[完整 Verify:签名、父链、能力、约束、请求绑定]
208
+ D --> E[成员/代表场景附加当前资格]
209
+ E --> F[按原业务键幂等执行并保存结果]
210
+ ```
211
+
212
+ ```ts
213
+ const operationMethod = 'reports.read';
214
+ const operation = { report: 'monthly', rows: 5, format: 'csv',
215
+ request_id: capRandomUUID(), nonce: capRandomBytes(32).toString('base64url') };
216
+ const operationNow = Math.trunc(Date.now() / 1000);
217
+ const operationBinding = buildRequestBinding(operationMethod, businessAid,
218
+ operation, String(credential.cid), operation.nonce, operation.request_id,
219
+ operationNow, operationNow + 300);
220
+ await app.save('structured-business-request', { ...operation, request_binding: operationBinding });
221
+ ```
222
+
223
+ 验收端从真实认证收件取得以下 operation、绑定与 holder 身份,预检与完整验收按用途选择:
224
+
225
+ ```ts
226
+ const signatureReport = holderClient.credential.verifySignature(credential, resolveCertificate);
227
+ const checked = holderClient.credential.verify(credential, {
228
+ audience: businessAid, subject: holderAid, rootIssuer: issuerSigner.aid,
229
+ ns: 'files', action: 'read', resource: '/reports',
230
+ method: operationMethod, target: businessAid, params: operation,
231
+ requestId: operation.request_id, nonce: operation.nonce, requestBinding: operationBinding,
232
+ resolveCertificate, resolveStatusProof: cid => checkedStatusProofs.get(cid),
233
+ });
234
+ ```
235
+
236
+ verifySignature 返回签名预检结果;业务执行使用完整 verify 的成功结果。约束字段从真实 params/units/clientIp 取得;rate_limit 使用应用事务限额端口 checkRateLimit。成员另传 membershipBinding/resolveMembershipStatus 与实际 orgSigner;代表调用另传 actor/for/representationProof 及当前 Ownership/actor 状态,见§5—§6。
237
+
238
+ ### 3.6 撤销、普通 CRL 分页与恢复
239
+
240
+ ```mermaid
241
+ flowchart TD
242
+ A[issuer 固定 revoke 原请求] --> B[经认证 RPC 撤销,检查 CID 与 revoked]
243
+ B --> C[保存结果与撤销序号]
244
+ C --> D[按 authority、原 cursor/since_event_seq 拉 CRL]
245
+ D --> E[验服务签名、原查询、窗口及事件递增]
246
+ E --> F[同事务合并撤销最大序号与页面进度]
247
+ F -->|next_cursor 非空| D
248
+ F -->|next_cursor 为空| G[保存本轮完成进度]
249
+ ```
250
+
251
+ 子凭证由其签发者发起撤销;转交登记所用 relay 不自动取得任意撤销权:
252
+
253
+ ```ts
254
+ const revocationParams = credentialRequest('credential.revoke', String(credential.cid), {
255
+ registrar_aid: delegateSigner.aid, credential_cid: credential.cid,
256
+ reason_code: 'grant_withdrawn', cascade: true,
257
+ });
258
+ await app.save('structured-revoke-input', revocationParams);
259
+ const revokeResult = await delegateClient.credential.revoke(revocationParams);
260
+ if (!isJsonObject(revokeResult) || revokeResult.credentialCid !== credential.cid
261
+ || revokeResult.status !== 'revoked') throw new Error('撤销结果无效');
262
+ await app.save('structured-revoke-result', revokeResult);
263
+ ```
264
+
265
+ ```ts
266
+ const crlProgress = await app.loadStructuredCrlProgress(credentialServiceAid);
267
+ let structuredCursor = crlProgress.cursor || String(crlProgress.since_event_seq);
268
+ ```
269
+
270
+ ```ts
271
+ do {
272
+ const crlInput = credentialRequest('credential.revocationList', '', { cursor: structuredCursor, limit: 100 });
273
+ await app.save('structured-crl:' + structuredCursor, crlInput);
274
+ const rawPage = await holderClient.credential.revocationList(crlInput);
275
+ const page = await app.structured.verifyCrl(rawPage, crlInput, credentialServiceAid);
276
+ await app.commitStructuredCrlPage(credentialServiceAid, page);
277
+ structuredCursor = page.next_cursor;
278
+ } while (structuredCursor !== '');
279
+ ```
280
+
281
+ 普通 CRL 结束游标为 `''`。verifyCrl 委托[verifyStructuredCrl](凭证与组织服务SDK开发与移植指南.md#66-普通-crl-分页与原子持久),核对 responder、target、request_id/nonce、issuer 过滤、证明窗口及事件序号;commitStructuredCrlPage 按 authority/CID 合并最大 event_seq,并原子保存游标。单条推送保留较新撤销证据,分页进度由完整已验页面推进。
282
+
283
+ ```mermaid
284
+ flowchart LR
285
+ A[恢复同一 AID 与持久 store] --> B[current 读取已管理凭证及续期 successor]
286
+ B --> C[加载原请求、原件、授权、回执与业务结果]
287
+ C --> D[重取全部状态 proof,按原请求复核结果]
288
+ D --> E[原幂等键续跑,保存本阶段结果]
289
+ ```
290
+
291
+ 以下示例用于原绑定与登记授权仍在有效窗口内的丢响应重试:
292
+
293
+ ```ts
294
+ const managedRoot = await issuerClient.credential.current(rootCredential);
295
+ if (managedRoot?.credential) await app.save('structured-current-root', managedRoot.credential);
296
+ const savedRegistration = await app.loadStructuredInput('structured-child-registration');
297
+ const recoveredRegistration = await relayClient.credential.register(savedRegistration);
298
+ if (!isJsonObject(recoveredRegistration)) throw new Error('登记响应无效');
299
+ relayClient.credential.verifyRegistrationReceipt(recoveredRegistration.registrationReceipt,
300
+ credential, savedRegistration, resolveCertificate, credentialServiceAid);
301
+ ```
302
+
303
+ current 返回当前身份已管理的记录;显式短期 CAP 沿保存的原件使用。跨期恢复按原回执与 SDK 提交检查点确认既成结果,见§9与[移植指南 §5.2](凭证与组织服务SDK开发与移植指南.md#52-登记授权和回执)。
304
+
305
+ ## 4. 语义凭证接入
306
+
307
+ ### 4.1 材料与公共准备
308
+
309
+ 各角色使用自己的已连接 client。语义入口平铺在 client.credential,版本为 aun-cap/semantic-1;Node TS 为下文基准。字段见[正式规范](../../../extensions/services/docs/org/0.8/语义凭证扩展规范.md)及[RPC 手册](09-凭证服务RPC手册.md#语义凭证公共约定)。
310
+
311
+ | 依赖 | 来源与职责 |
312
+ | --- | --- |
313
+ | issuerSigner/confirmerSigner | 签发者 A/确认者 K 的真实身份及授权依据 |
314
+ | authority/policy/trust | 登记管理权限、固定版本策略、证书解析和信任校验 |
315
+ | app.* | 应用端口:持久保存、认证通道、正文材料、模型、后置复核、事务账本与执行器 |
316
+
317
+ ```ts
318
+ import { randomBytes, randomUUID } from 'node:crypto';
319
+ import { semanticProtocol as sp } from '@agentunion/fastaun';
320
+ const options = { serviceAid: 'credential.agentid.cn', verificationContext: trust };
321
+ const management = (credential_cid: string) => ({
322
+ request_id: randomUUID(), nonce: randomBytes(32).toString('base64url'),
323
+ credential_cid, authority,
324
+ });
325
+ ```
326
+
327
+ 管理写操作在首次调用前持久保存完整 input;幂等重试读取原 input。facade 按当前 Unix 秒补管理绑定。SignedJsonBytes={bytes_base64} 保留签署后的严格 UTF-8 JSON 原字节,使用标准带 padding Base64;EvidenceRef 使用独立包装。
328
+
329
+ ### 4.2 签发、确认与登记(E02—E05、E18)
330
+
331
+ ```mermaid
332
+ sequenceDiagram
333
+ participant A as 签发者 A
334
+ participant K as 确认者 K
335
+ participant R as 登记权威 R
336
+ A->>A: signCredential:正文与显式上限
337
+ A->>K: 原件及确认权依据
338
+ K->>K: signMetadata:确定 iss/sub/aud/期限/次数
339
+ K->>R: register:原件、metadata、来源链、管理权限
340
+ R-->>K: CID、original_hash、逐 aud 修订与回执
341
+ K->>K: 持久保存原字节与登记结果
342
+ ```
343
+
344
+ textGrant 的正文明确授权对象、业务操作、期限和次数:
345
+
346
+ ```ts
347
+ const now = Math.trunc(Date.now() / 1000);
348
+ const textGrant = {
349
+ ver: 'aun-cap/semantic-1', cid, cap: [],
350
+ iss: issuerSigner.aid, sub: holderAid, aud: [businessAid],
351
+ nbf: now, exp: now + 3600, delegate: false,
352
+ authorization: { kind: 'text', text: grantText },
353
+ } satisfies Omit<sp.SemanticCredential, 'signature'>;
354
+ const original = await client.credential.signCredential(textGrant, issuerSigner);
355
+ ```
356
+
357
+ 累计额度绑定来源链根原件;本例为根凭证的一次使用:
358
+
359
+ ```ts
360
+ const usage = {
361
+ grant_key: sp.digest(['AUN-CAP-GRANT-v1', cid, sp.digest(sp.decodeSignedJson(original))]),
362
+ epoch: 1, audiences: [businessAid],
363
+ ledger: { scope: 'global', authority: ledgerAid },
364
+ limits: [{ id: 'reads', metric: 'count', unit: 'request', limit: '1' }],
365
+ } satisfies sp.UsageContract;
366
+ ```
367
+
368
+ ```ts
369
+ const metadata = await client.credential.signMetadata({
370
+ original_hash: sp.digest(sp.decodeSignedJson(original)), version: 'm1',
371
+ confirmed_at: now, iss: issuerSigner.aid, sub: holderAid, aud: [businessAid],
372
+ nbf: now, exp: now + 3600, use_limit: 1, usage, delegate: false, policy,
373
+ confirmation: { authority: confirmerSigner.aid,
374
+ authorization: confirmationPolicy, audiences: [businessAid] },
375
+ }, confirmerSigner);
376
+ ```
377
+
378
+ ```ts
379
+ const registrationInput = { ...management(cid), original, metadata: [metadata],
380
+ lineage_evidence: [] } satisfies sp.SemanticFacadeInput<sp.SemanticRegisterParams>;
381
+ await app.save('registration-input', registrationInput);
382
+ const registered = await client.credential.register(registrationInput, options);
383
+ await app.save('registered', registered);
384
+ ```
385
+
386
+ | 分支 | 签发与确认材料 |
387
+ | --- | --- |
388
+ | 纯语义 | cap=[],metadata 确定授权字段 |
389
+ | 混合 | cap 非空;验收取结构化范围与正文的交集 |
390
+ | 明确无限期/无限次 | 正文明确,对应原件上限省略;metadata 使用 exp=null/use_limit=null |
391
+ | 待补确认 | 返回具体补充项,有权方补签后重新登记/出示 |
392
+ | 派生凭证 | lineage_evidence 保存 root→直接 parent 的完整材料 |
393
+
394
+ ```ts
395
+ const mixedOriginal = await client.credential.signCredential({
396
+ ...textGrant, cid: mixedCid, cap: structuredCaps,
397
+ }, issuerSigner);
398
+ ```
399
+
400
+ ### 4.3 消息正文与证据(E06—E11、E15、E32)
401
+
402
+ ```mermaid
403
+ flowchart TD
404
+ A[认证通道取得原始 envelope 与收件记录] --> B[archiveMessage 保全原字节]
405
+ B --> C{证据交付方式}
406
+ C -->|inline| D[使用 archive.envelope]
407
+ C -->|aun_ref| E[按 ACL 保存对象与版本,生成引用]
408
+ D --> F[签署 message_ref,固定 signed_core_hash 与会话]
409
+ E --> F
410
+ F --> G[验发送者、原收件资格、解密与正文]
411
+ G -->|材料齐备| H[VerifiedBody 进入业务判断]
412
+ G -->|待补| I[补原材料,或有权方另签自足 text]
413
+ ```
414
+
415
+ ```ts
416
+ const archive = await client.credential.archiveMessage(rawEnvelope, received);
417
+ await app.archive.put(archiveLocator, archive.envelope_bytes);
418
+ const envelopeRef = await client.credential.createEvidenceRef(
419
+ archive.envelope_bytes, 'aun-e2ee-v2-envelope-raw/1', archiveLocator,
420
+ );
421
+ const referencedOriginal = await client.credential.signCredential({
422
+ ...messageGrant, authorization: { kind: 'message_ref',
423
+ message: { ...messageRef, envelope: envelopeRef } },
424
+ }, issuerSigner);
425
+ ```
426
+
427
+ ```ts
428
+ const inlineRef = archive.envelope;
429
+ const resolved = await client.credential.resolveEvidence(envelopeRef, archiveResolvers);
430
+ const body = await client.credential.verifyMessageBody(referencedOriginal, messageContext);
431
+ ```
432
+
433
+ | 分支 | 固定材料 |
434
+ | --- | --- |
435
+ | 自足 text+消息溯源 | authorization.evidence 保留消息证据;正文使用独立 text 签名 |
436
+ | P2P | conversation={kind:'p2p',to}、原接收 AID/设备/历史解密材料 |
437
+ | 群消息 | conversation={kind:'group',group_id,epoch,state_commitment};完整收件集合或单行 Merkle 证明 |
438
+ | 上下文/附件 | message.context 使用消息原件;attachments 使用 aun-evidence-bytes/1 |
439
+ | 长期归档 | 原字节、对象版本、ACL、历史证书、解密能力及 retain_until |
440
+
441
+ messageContext 提供可信证书、发送者历史身份与原收件密钥;received 取实际认证收件记录。签署 messageRef 的 signed_core_hash 算法见[移植指南 §4.5](凭证与组织服务SDK开发与移植指南.md#45-消息证据适配)。
442
+
443
+ ### 4.4 来源链、交付与业务请求(E12—E16、E26)
444
+
445
+ ```mermaid
446
+ flowchart LR
447
+ A[get 当前原件、metadata 与回执] --> B[逐层取得 bounded 状态快照]
448
+ B --> C[buildPackage:root 到 leaf]
449
+ C --> D[AUN 加密交付 holder]
450
+ D --> E[buildRequest 固定业务 hash]
451
+ E --> F[逐层查询 online 状态并替换快照]
452
+ F --> G[认证通道向业务方出示]
453
+ ```
454
+
455
+ 单层当前材料的准备;多跳按 root→leaf 重复:
456
+
457
+ ```ts
458
+ const current = await client.credential.get({ ...management(cid), audience: businessAid }, options);
459
+ if (current.kind === 'revision' && current.head.state === 'current') {
460
+ const status = await client.credential.status({
461
+ ...management(cid), audience: businessAid, expected_revision: current.revision,
462
+ policy: { mode: 'bounded', max_staleness_seconds: 60 },
463
+ }, options);
464
+ await app.saveEntry({ credential: sp.decodeSignedJson(current.original) as sp.SemanticCredential,
465
+ metadata: sp.decodeSignedJson(current.metadata) as sp.RegistrationMetadata,
466
+ registration_receipt: current.registration_receipt, status });
467
+ }
468
+ ```
469
+
470
+ ```ts
471
+ const grant = await client.credential.buildPackage(lineage);
472
+ await app.transport.sendEncrypted(holderAid, grant);
473
+ const request = await client.credential.buildRequest({
474
+ request_id: randomUUID(), nonce: randomBytes(32).toString('base64url'),
475
+ actor: presenterAid, sub: holderAid, target: businessAid, aud: businessAid,
476
+ ns: 'files', action: 'read', resource: '/reports', params: { report: reportId },
477
+ expires_at: Math.trunc(Date.now() / 1000) + 300, grant,
478
+ });
479
+ await app.save('business-request', request);
480
+ ```
481
+
482
+ | 来源链分支 | 验收配置 |
483
+ | --- | --- |
484
+ | 纯语义/混合多跳 | 逐跳身份、delegate、深度≤8、期限、aud、能力和全部适用正文 |
485
+ | 旧根→语义叶 | packageContext.legacyVerifier 使用普通凭证完整验证及原权威强状态 |
486
+ | 父级 message_ref | app.messageContext 为每层提供原收件材料;全部正文进入 DecisionInput |
487
+ | 代表调用 | actor 为真实发送者,sub 为叶 holder;verifyRepresentation 核验当前代表依据 |
488
+
489
+ ### 4.5 online/bounded 与状态刷新(E19—E22、E26)
490
+
491
+ ```mermaid
492
+ flowchart TD
493
+ A[固定业务 request_hash] --> B{状态策略}
494
+ B -->|online| C[独立查询 nonce,记录单调起点]
495
+ C --> D[status 绑定业务 hash,查询到确认小于 30 秒]
496
+ B -->|bounded| E[指定 1 到 300 秒 TTL,按本地观察计时]
497
+ D --> F[验服务、修订、state_seq 与绝对窗口]
498
+ E --> F
499
+ F --> G[替换同修订 status,保持业务 hash]
500
+ G --> H[业务执行前再次复核]
501
+ ```
502
+
503
+ online 示例展示一层,逐层分别保存 query 与单调起点:
504
+
505
+ ```ts
506
+ const query = { request_hash: request.request_binding.request_hash,
507
+ nonce: randomBytes(32).toString('base64url') };
508
+ const began = performance.now();
509
+ const online = await client.credential.status({ ...management(cid),
510
+ audience: request.aud, expected_revision: revision, policy: { mode: 'online' }, query,
511
+ }, options);
512
+ await client.credential.verifyStatus(online, { ...trust, expectedServiceAid: options.serviceAid,
513
+ policy: { mode: 'online' }, query, elapsedSeconds: (performance.now() - began) / 1000 });
514
+ ```
515
+
516
+ ```ts
517
+ const bounded = await client.credential.status({ ...management(cid),
518
+ audience: request.aud, expected_revision: revision,
519
+ policy: { mode: 'bounded', max_staleness_seconds: 60 },
520
+ }, options);
521
+ ```
522
+
523
+ ```ts
524
+ const refreshed = structuredClone(request);
525
+ const leaf = refreshed.grant.lineage.at(-1)!;
526
+ if ('metadata' in leaf) leaf.status = online;
527
+ const unchangedHash = await client.credential.requestHash(refreshed);
528
+ await app.transport.submit(businessAid, refreshed);
529
+ ```
530
+
531
+ 管理 nonce、业务 nonce、online 查询 nonce 分别生成。bounded 本地耗时须小于 TTL;两种策略均复核绝对窗口及最大已观察序号。刷新仅替换同修订状态;正文/metadata/回执/操作/期限变更使用新业务请求。角色变化后仍按原授权条件验收,显式撤销按当前状态策略生效。
532
+
533
+ ### 4.6 业务验收与模型三态(E16、E18、E23—E25、E34)
534
+
535
+ ```mermaid
536
+ flowchart TD
537
+ A[真实认证 actor 与 service] --> B[verifyRequest 与 verifyPackage]
538
+ B --> C[签发权、确认权、历史 policy、前置名单与约束]
539
+ C --> D[逐层验真正文,取得可信事实]
540
+ D --> E[buildDecisionInput,模型三态判断]
541
+ E -->|deny| F[保存拒绝结果]
542
+ E -->|indeterminate/超时/异常| G[保存待补项]
543
+ E -->|allow| H[后置复核与当前状态确认]
544
+ H -->|事实/策略变化| C
545
+ H -->|修订/回执变化| J[重新取材料与 buildRequest]
546
+ J --> A
547
+ H -->|通过| I[事务预留与幂等执行]
548
+ ```
549
+
550
+ ```ts
551
+ const authentication = await app.transport.authenticationFor(request);
552
+ const bindingReport = await client.credential.verifyRequest(request, authentication, {
553
+ representedActor: app.verifyRepresentation,
554
+ });
555
+ const packageReport = await client.credential.verifyPackage(request.grant, packageContext);
556
+ await app.verifyAuthorities(request);
557
+ await app.checkStructuredCapabilities(request);
558
+ await app.precheck(request, facts);
559
+ ```
560
+
561
+ ```ts
562
+ const bodies = [];
563
+ for (const entry of request.grant.lineage) {
564
+ if ('metadata' in entry) bodies.push(await client.credential.verifyMessageBody(
565
+ entry.credential, await app.messageContext(entry),
566
+ ));
567
+ }
568
+ const input = await client.credential.buildDecisionInput(request, bodies, facts, policy);
569
+ ```
570
+
571
+ ```ts
572
+ const decision = await app.evaluate(input);
573
+ await app.saveDecision(input, decision);
574
+ if (decision.verdict === 'allow') {
575
+ await app.postcheck(input, decision);
576
+ await app.refreshAndVerify(request);
577
+ await app.executeOnceWithUsage(request, decision);
578
+ }
579
+ ```
580
+
581
+ app.evaluate 将模型超时/无效输出归为 indeterminate;app.precheck 完成前置名单与本次确认准入,app.postcheck 复核确认与业务后置条件。packageContext 提供原签署者、各层登记权威、旧层验证器、状态 query 和真实单调耗时;checked/required 分别用于记录已完成检查与应用待完成职责。缓存绑定请求、正文、facts、policy、修订及状态版本。
582
+
583
+ ### 4.7 受众修订、历史读取与撤销(E17—E18、E21—E22)
584
+
585
+ ```mermaid
586
+ flowchart LR
587
+ A[get 当前 head] --> B[确认新 metadata]
588
+ B --> C[revise 批量 CAS]
589
+ C -->|提交| D[保存新 revision 与 state_seq]
590
+ C -->|冲突| A
591
+ D --> E{变更范围}
592
+ E -->|指定 aud| F[withdraw 或按最后 head 重加]
593
+ E -->|整个 CID| G[revoke,持久保存撤销结果]
594
+ ```
595
+
596
+ ```ts
597
+ const revisionInput = { ...management(cid), kind: 'metadata' as const,
598
+ change: { expected: [{ audience: businessAid, revision }], metadata: [newMetadata] },
599
+ };
600
+ await app.save('revision-input', revisionInput);
601
+ const revised = await client.credential.revise(revisionInput, options);
602
+ ```
603
+
604
+ | 变更 | change |
605
+ | --- | --- |
606
+ | 替换/批量替换 | expected=[当前 AudienceRevision],metadata=[新签 metadata] |
607
+ | 新增 aud | expected_absent=[aud],expected=[],metadata=[新签 metadata] |
608
+ | 撤下 aud | expected=[当前 AudienceRevision],withdraw=[aud],metadata=[] |
609
+ | 重加 aud | expected_withdrawn=[aud、last_revision、state_seq],expected=[],metadata=[新签 metadata] |
610
+
611
+ ```ts
612
+ const historical = await client.credential.get({ ...management(cid),
613
+ audience: businessAid, metadata_version: historicalVersion,
614
+ }, options);
615
+ const revocationInput = { ...management(cid), reason_code: 'grant_withdrawn' };
616
+ await app.save('revocation-input', revocationInput);
617
+ const revoked = await client.credential.revoke(revocationInput, options);
618
+ ```
619
+
620
+ get 使用当前、metadata_version、transition_id 三种选择之一。确认权按 confirmed_at 的固定依据核验;新修订重新确认,历史原件与回执继续保留供审计读取。
621
+
622
+ ### 4.8 额度、分配与执行结果(E27—E30)
623
+
624
+ ```mermaid
625
+ flowchart TD
626
+ A[业务 allow 与新鲜状态] --> B[按 global/per_aud 计算全部适用账户]
627
+ B --> C{账本权威}
628
+ C -->|同权威| R[同事务预留父子账户]
629
+ C -->|跨权威| S[验 allocation 及在线 active 状态]
630
+ S --> T[预留本权威账户与已分配容量]
631
+ R --> D[按原业务键幂等执行]
632
+ T --> D
633
+ D -->|committed| E[结算累计值]
634
+ D -->|取消/确认无效果| F[释放预留]
635
+ D -->|Unknown| G[保留预留,查询原执行器]
636
+ G -->|确认成功| E
637
+ G -->|确认无效果| F
638
+ ```
639
+
640
+ ledger/executor 为应用持久端口,额度使用精确十进制。跨权威先由父账本签 UsageAllocation 并验证在线状态;active 接受新预留,draining 结清在途,closed 返还剩余容量:
641
+
642
+ ```ts
643
+ const signedAllocation = await client.credential.signAllocation(unsignedAllocation, parentLedgerSigner);
644
+ const allocation = sp.decodeSignedJson(signedAllocation) as sp.UsageAllocation;
645
+ await client.credential.verifyAllocation(allocation, {
646
+ ...trust, parent: parentEntry, child: childEntry, audience: request.aud,
647
+ });
648
+ const allocationBegan = performance.now();
649
+ const allocationProof = await app.ledger.queryAllocation(allocation, allocationQuery);
650
+ await client.credential.verifyAllocationStatus(allocationProof, { ...trust, allocation,
651
+ query: allocationQuery, elapsedSeconds: (performance.now() - allocationBegan) / 1000 });
652
+ ```
653
+
654
+ sameAuthority 由已确认账本绑定计算;跨权威以已验真的 active 证明作为预留门槛:
655
+
656
+ ```ts
657
+ if (sameAuthority || allocationProof?.state === 'active') {
658
+ const reservation = await app.ledger.reserveAll(request, demands);
659
+ const execution = await app.executor.executeOnce(request);
660
+ await app.ledger.recordOutcome(reservation, execution);
661
+ }
662
+ ```
663
+
664
+ ### 4.9 UsageRef 切换与恢复(E31、E33)
665
+
666
+ ```mermaid
667
+ sequenceDiagram
668
+ participant A as 协调应用
669
+ participant R as 登记权威
670
+ participant L as 原账本/新账本
671
+ A->>R: prepareUsage:固定 change 与 from/to UsageRef
672
+ R-->>A: prepared、transition_id、fence、candidate_hash
673
+ A->>L: 冻结、核对 Unknown、结清分配
674
+ L-->>A: checkpoints、allocation_closures、acceptances
675
+ alt 提交切换
676
+ A->>R: commitUsage:同 transition/fence
677
+ R-->>A: committed,全部 aud 原子发布
678
+ else 取消切换
679
+ A->>R: abortUsage:同 transition/fence/from_usage
680
+ R-->>A: aborted 与 recovery
681
+ A->>L: 按 recovery 收集 ledger-abort 确认
682
+ end
683
+ ```
684
+
685
+ ```ts
686
+ const prepareInput = { ...management(cid), transition_id: transitionId,
687
+ from_usage: fromUsage, to_usage: toUsage, change: usageChange,
688
+ previous_abort_acks: previousAbortAcks } satisfies sp.SemanticUsageInput<'usage_prepare'>;
689
+ await app.save('usage-prepare-input', prepareInput);
690
+ const prepared = await client.credential.prepareUsage(prepareInput, options);
691
+ await app.save('usage-transition', prepared);
692
+ ```
693
+
694
+ ```ts
695
+ const commitInput = { ...management(cid), transition_id: prepared.transition_id,
696
+ fence: prepared.fence, checkpoints, allocation_closures: allocationClosures,
697
+ acceptances } satisfies sp.SemanticUsageInput<'usage_commit'>;
698
+ await app.save('usage-commit-input', commitInput);
699
+ const committed = await client.credential.commitUsage(commitInput, options);
700
+ ```
701
+
702
+ ```ts
703
+ const abortInput = { ...management(cid), transition_id: prepared.transition_id,
704
+ fence: prepared.fence, from_usage: prepared.from_usage } satisfies sp.SemanticUsageInput<'usage_abort'>;
705
+ await app.save('usage-abort-input', abortInput);
706
+ const aborted = await client.credential.abortUsage(abortInput, options);
707
+ ```
708
+
709
+ commit/abort 为两条分支。调用前保存各自输入;丢响应或重启后,用原 transition_id 查询 get,再按 prepared/committed/aborted 续跑。切换材料绑定同一 candidate_hash/UsageRef/fence,账户逐键连续;Unknown 继续保留预留与冻结,恢复资格取已签 recovery。
710
+
711
+ ### 4.10 CRL、冷恢复与双域(E21、E32—E36)
712
+
713
+ ```mermaid
714
+ flowchart LR
715
+ A[原 AID、持久 store 与 authority/scope] --> B[从保存 cursor/after 开始拉页]
716
+ B --> C[facade 验签并原子合并页与进度]
717
+ C -->|next_cursor 有值| B
718
+ C -->|next_cursor=null| D[推进 upper_event_seq]
719
+ D --> E[恢复原业务请求与 transition]
720
+ E --> F[重新取得当前状态,续查原执行结果]
721
+ ```
722
+
723
+ 首次完整分页从 cursor=null 开始;续页沿用 scope、after_event_seq 和 limit,每页生成并保存独立管理请求:
724
+
725
+ ```ts
726
+ let cursor: string | null = null;
727
+ do {
728
+ const pageInput = { ...management(''), credential_cid: '' as const, scope,
729
+ after_event_seq: afterEventSeq, cursor, limit: 100 };
730
+ await app.save('crl-page-input', pageInput);
731
+ const page = await client.credential.revocations(pageInput, options);
732
+ cursor = page.next_cursor;
733
+ if (cursor === null) await app.saveCrlProgress(scope, page.upper_event_seq);
734
+ } while (cursor !== null);
735
+ ```
736
+
737
+ scope 变化使用独立进度。恢复保留 SDK 的语义持久状态、原请求和账本预留;online 重新查询。归档保存原件、历史修订、证书与解密能力,retain_until 按留存策略持久记录。
738
+
739
+ ```ts
740
+ const remote = await client.credential.get({ ...management(remoteCid),
741
+ authority: remoteAuthority, audience: businessAid,
742
+ }, { serviceAid: 'credential.aid.com', verificationContext: remoteTrust });
743
+ ```
744
+
745
+ 跨域逐层通过 packageContext.serviceFor 选择可信登记权威,并为归档配置对应 resolver/ACL。TS/JS 使用 {serviceAid},Python 使用 target,Go 使用 NewCredentialFacade(client, serviceAID);low-level、CLI 与浏览器映射见[移植指南 §4](凭证与组织服务SDK开发与移植指南.md#4-语义凭证移植契约)。
746
+
747
+ ### 4.11 E2E 场景对照
748
+
749
+ | 场景 | 图与示例位置 |
750
+ | --- | --- |
751
+ | E01 普通兼容 | §3、§5—§7;移植指南 §3、§5—§7 |
752
+ | E02—E05、E18 签发/补确认/确认权 | §4.2、§4.6—§4.7 |
753
+ | E06—E11、E15 消息/上下文/附件 | §4.3、§4.6 |
754
+ | E12—E16 交付/多跳/旧根/代表 | §4.4、§4.6 |
755
+ | E17 多受众 CAS/历史 | §4.7 |
756
+ | E19—E22 状态/撤销/角色变化 | §4.5、§4.7、§4.10 |
757
+ | E23—E26 三态/本次确认/缓存/重传 | §4.4—§4.6 |
758
+ | E27—E30 Unknown/累计额度/父子/跨权威 | §4.8 |
759
+ | E31 UsageRef 切换 | §4.9 |
760
+ | E32—E36 归档/重启/证书/双域/公开入口 | §4.3、§4.6、§4.10;移植指南 §4.5—§4.9 |
761
+
762
+ 场景逐项来源:[scenarios.json](../../examples/semantic-credential/scenarios.json)及[真实 E2E runner](../../tests/cross-sdk/runner/run_cross_sdk_e2e.py)。本轮实际覆盖为 CN、四 SDK、本地 CN↔aid.com、真实浏览器及持久恢复;固定模型、TTL 与留存证据边界见[示例使用指南](../../examples/semantic-credential/示例使用指南.md#5-本轮验证记录与边界)。
763
+
764
+ ## 5. 组织成员流程
765
+
766
+ ### 5.1 组织创建
767
+
768
+ ```mermaid
769
+ flowchart LR
770
+ A[owner 会话和持久 AIDStore] --> B[生成并保存组织实体身份]
771
+ B --> C[准备 owner binding、CAP 和登记授权]
772
+ C --> D[Org 登记 CAP、验回执并创建组织]
773
+ D --> E[实体主签,owner token 上传名片]
774
+ ```
775
+
776
+ ```ts
777
+ const created = await ownerClient.createOrg(
778
+ { org_id: orgAid, name: '协作组织' }, { aidStore: ownerStore },
779
+ );
780
+ ```
781
+
782
+ 组织名片实体主签、owner token 上传,含当前 owner/实体指纹,附签存在则全验。组织不走通用 Ownership 绑定,名片待办与创建结果分开。
783
+
784
+ ### 5.2 申请加入与邀请
785
+
786
+ ```mermaid
787
+ sequenceDiagram
788
+ participant M as 成员 App
789
+ participant O as owner/管理员 App
790
+ participant G as Org 服务
791
+ participant C as Credential 服务
792
+ alt 成员申请
793
+ M->>G: join:成员签 binding
794
+ G-->>O: 待审批
795
+ O->>G: approveJoin:审批者签 binding,实体签 CAP/登记授权
796
+ else 组织邀请
797
+ O->>G: invite:每个目标独立 binding/CAP/登记授权
798
+ G-->>M: 原邀请材料
799
+ M->>G: inviteAccept:保留原材料,补目标成员签名
800
+ end
801
+ G->>C: 登记成员 CAP
802
+ C-->>G: 签名回执
803
+ G->>G: 验回执并最终化成员
804
+ G-->>M: active 与完整成员包
805
+ ```
806
+
807
+ 成员申请:
808
+
809
+ ```ts
810
+ const joinParams = memberClient.org.prepareRequest('org.member.join', {
811
+ org_id: orgAid, member_type: 'human', requested_role: 'member', terms,
812
+ }, orgServiceAid, memberSigner);
813
+ const application = await memberClient.org.member.join(joinParams);
814
+ ```
815
+
816
+ 审批端从原申请取得 applicationBinding/terms;ownerSigner 签 binding 的组织侧,orgSigner 签 CAP 和登记授权,ownerCredentials 提供审批资格:
817
+
818
+ ```ts
819
+ const binding = ownerClient.org.member.signBinding(applicationBinding, ownerSigner, 'org');
820
+ const approval = ownerClient.org.prepareRequest('org.member.approveJoin', {
821
+ org_id: orgAid, terms, membership_binding: binding, credentials: ownerCredentials,
822
+ }, orgServiceAid, ownerSigner, { orgSigner });
823
+ await ownerClient.org.member.approveJoin(approval);
824
+ ```
825
+
826
+ 邀请端逐目标生成材料:
827
+
828
+ ```ts
829
+ const invitationParams = ownerClient.org.prepareRequest('org.member.invite', {
830
+ org_id: orgAid, targets: [holderAid], terms, credentials: ownerCredentials,
831
+ }, orgServiceAid, ownerSigner, { orgSigner });
832
+ const invitations = await ownerClient.org.member.invite(invitationParams);
833
+ ```
834
+
835
+ invitation 取返回 invites[] 中当前成员的一项;接收端组装接受请求:
836
+
837
+ ```ts
838
+ const accepted = memberClient.org.prepareRequest('org.member.inviteAccept', {
839
+ org_id: orgAid, invite_id: invitation.invite_id,
840
+ membership_binding: invitation.membership_binding,
841
+ credential_template: invitation.credential_template,
842
+ registration_authorization: invitation.registration_authorization,
843
+ }, orgServiceAid, memberSigner);
844
+ await memberClient.org.member.inviteAccept(accepted);
845
+ ```
846
+
847
+ 首次入组绑定 membership_id 和原 request ID/nonce,不带 CID/已有 CAP。本人和代表均须目标成员签名;for≠signer.aid 另验代表证明和当前 Ownership/actor 状态。
848
+
849
+ ### 5.3 查询、状态变更与续期
850
+
851
+ ```mermaid
852
+ flowchart LR
853
+ A[同一成员关系,准备新 binding/CAP/登记授权] --> B[renewCredential:旧 CID+当前版本 CAS]
854
+ B --> C[登记新 CAP 并验回执]
855
+ C -->|成功| D[提交新成员版本,再撤旧 CAP]
856
+ C -->|失败| E[仅补偿撤新 CAP]
857
+ D --> F[立即保存完整新成员包]
858
+ ```
859
+
860
+ renewalMaterial 含旧 CID、expected_version、双签新 binding、terms、新 CAP/登记授权及当前调用授权:
861
+
862
+ ```ts
863
+ const renewal = memberClient.org.prepareRequest(
864
+ 'org.member.renewCredential', renewalMaterial, orgServiceAid, memberSigner,
865
+ );
866
+ await memberClient.org.member.renewCredential(renewal);
867
+ const current = await memberClient.credential.current(memberCredential);
868
+ ```
869
+
870
+ 续期保持原成员关系,响应后立即持久完整成员包,credential.current 无需等事件。长期凭证 READY 后及在线每60秒扫描,显式短期凭证不自动续期。
871
+
872
+ 当前资格看签名 membership_status:banned/ended 拒绝,frozen 禁普通写,offboarding 仅收尾。离职按 leave/kick→offboard→ended→撤有权吊销的 CAP→清 active projection,失败续跑。
873
+
874
+ ## 6. 组织请求与跨设备代表
875
+
876
+ ### 6.1 统一请求准备
877
+
878
+ ```mermaid
879
+ flowchart LR
880
+ A[业务参数+本次授权包] --> B[prepareRequest:原 ID/nonce、AAD、request binding]
881
+ B --> C[必要时补代表证明]
882
+ C --> D[RPC 管线生成外层 client_signature]
883
+ D --> E[Gateway service-plane]
884
+ E --> F[服务独立重算签名、摘要和当前权限]
885
+ ```
886
+
887
+ 受保护读取也须准备请求,例如查询自己的成员状态:
888
+
889
+ ```ts
890
+ const params = memberClient.org.prepareRequest('org.member.get', {
891
+ org_id: orgAid, member_aid: memberSigner.aid, credentials: memberCredentials,
892
+ }, orgServiceAid, memberSigner);
893
+ const member = await memberClient.org.member.get(params);
894
+ ```
895
+
896
+ 准备后原样发送,RPC 管线补 client_signature。受保护读取也需当前 binding/CAP;公开 lifecycle.get/list 按可见性处理。AAD 绑定 org_id,仅 lifecycle.list/health/status 可为 null。
897
+
898
+ ### 6.2 代表操作
899
+
900
+ 参数增加 for: holderAid,授权包仍属 holder。prepareRequest 绑定双方、方法、服务、摘要和时间窗;首次 admission 绑定 membership_id,其他代表绑定 CID。owner 不能替代目标成员签名。
901
+
902
+ ### 6.3 服务事件
903
+
904
+ SDK 验服务、接收 AID、证书、签名和时间窗后去重;撤销同步如下:
905
+
906
+ ```mermaid
907
+ flowchart LR
908
+ A[撤销推送/已签列表页] --> B[验签及身份/连接代次复核]
909
+ B --> C[按 authority、CID 保留最大 event_seq]
910
+ C --> D[持久保存快照]
911
+ D --> E[后续授权检查使用]
912
+ ```
913
+
914
+ 单条推送不推进分页,旧页不覆盖新证据,本地缺 CID 不证明有效。连接后一小时首次兜底拉列表,之后每小时;重连重新计时,与60秒凭证扫描独立。
915
+
916
+ ## 7. 所有权转让与实体材料
917
+
918
+ ```mermaid
919
+ sequenceDiagram
920
+ participant O as 原 owner
921
+ participant N as 目标 owner SDK
922
+ participant G as Org 服务
923
+ participant CA as CA
924
+ O->>G: transfer:当前授权请求
925
+ G-->>N: transfer proposal
926
+ N->>N: 签接受材料,持久保存新 P-256 私钥与 checkpoint
927
+ N->>G: transferAccept stage=rekey
928
+ G->>CA: 复核代际并提交新公钥
929
+ CA-->>G: 新实体证书
930
+ G-->>N: pending_finalization 与新证书
931
+ N->>N: 导入证书,重签新旧 owner binding/CAP
932
+ N->>G: stage=finalize,独立持久 request ID
933
+ G->>G: 新 owner 生效,旧 owner 降 member,撤旧 CAP
934
+ N->>N: 新实体主签,owner token 上传名片
935
+ ```
936
+
937
+ 原 owner 调用 org.lifecycle.transfer。目标验证 proposal 后签接受字段:
938
+
939
+ ```ts
940
+ const acceptance = targetClient.org.lifecycle.signTransferAcceptance(proposal, targetSigner);
941
+ ```
942
+
943
+ transferParams 合并 acceptance、原 proposal、双方完整成员材料及授权包:
944
+
945
+ ```ts
946
+ const transferred = await targetClient.completeOrgTransfer(
947
+ transferParams, { aidStore: targetStore },
948
+ );
949
+ ```
950
+
951
+ 恢复沿用原 transfer ID、输入、阶段参数和私钥;缺 key 报 persistence_unavailable,材料变化报 conflict,TS/JS 精确完成态可重放。详见 [移植 §7](凭证与组织服务SDK开发与移植指南.md#7-高层实体身份和转让编排)。
952
+
953
+ 解散用 client.dissolveOrg(params, { aidStore }),提供当前 binding/CAP;确认 dissolved 后才失效本地证书并清恢复状态,保留磁盘私钥。名片失败稿保留完整多签、固定 owner/代际和原 CAS,仅显式重试,重连不 PUT;代际变化停止旧待办。
954
+
955
+ ## 8. 四端入口速查
956
+
957
+ | 能力 | Python | TS/JS | Go |
958
+ | --- | --- | --- | --- |
959
+ | 业务入口 | client.credential/org | client.credential/org | client.Credential()/Org() |
960
+ | 请求准备 | org.prepare_request | org.prepareRequest | Org().PrepareRequest |
961
+ | 组织创建/转让 | org.lifecycle.create/transfer_accept | createOrg/completeOrgTransfer | CreateOrg/CompleteOrgTransfer |
962
+
963
+ 本节普通凭证/Org 的 Node TS 协议 helper 同步,浏览器密码 helper 为 Promise;Python RPC async/协议 helper 同步,Go 返回 value/error。文件 AIDStore.sign/verify 的 TS/JS 均须 await;语义 facade 的异步约定见§4。
964
+
965
+ ## 9. 错误与重试
966
+
967
+ 仅重试读取或原 method/request ID/摘要不变的幂等操作。签名/权限/binding/状态/幂等冲突不盲重试;未知暂缓副作用,创建补偿遇幂等冲突停自动补偿。
968
+
969
+ 跨期恢复只确认原期限内已持久且已发送的既成结果,不重登记/重签。无原回执时只保存 issuer 结果,holder 交付仍需原有效回执,边界见 [移植 §5.2](凭证与组织服务SDK开发与移植指南.md#52-登记授权和回执)。
970
+
971
+ ## 10. 验收清单
972
+
973
+ 覆盖完整 Verify、回执、双签入组、受保护读取、撤销乱序/重启、续期完整包、转让两阶段丢响应。运行见 [测试指南](../aun测试运行指南.md),版本边界见 [四端对齐清单](../../python/CHANGES_FOR_PARITY.md)。