@agentunion/fastaun-browser 0.5.19 → 0.5.21
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.
- package/CHANGELOG.md +176 -78
- package/_packed_docs/CHANGELOG.md +176 -78
- package/_packed_docs/INDEX.md +288 -269
- package/_packed_docs/KITE_DOCS_GUIDE.md +101 -95
- package/_packed_docs/agent.md/SCHEMA.md +7 -7
- 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
- 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
- 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
- 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
- package/_packed_docs/agent.md//350/277/234/347/250/213agent.md/347/274/223/345/255/230/344/270/216etag/351/200/217/344/274/240/346/226/271/346/241/210.md +11 -11
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +372 -331
- package/_packed_docs/protocol/08-AUN-E2EE.md +17 -12
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +676 -676
- package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +8 -12
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/211.md +445 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.0.md +161 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +666 -0
- package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2113.0.md +233 -0
- package/_packed_docs/protocol/agent.md/SCHEMA.md +1 -1
- 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
- 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
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +1 -1
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +5 -1
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +64 -64
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +70 -63
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +43 -40
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +179 -19
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +50 -49
- package/_packed_docs/sdk/09-group-rpc-manual.md +261 -254
- package/_packed_docs/sdk/09-message-rpc-manual.md +253 -160
- package/_packed_docs/sdk/09-storage-rpc-manual.md +18 -26
- package/_packed_docs/sdk/09-/345/207/255/350/257/201/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +71 -0
- package/_packed_docs/sdk/09-/347/273/204/347/273/207/346/234/215/345/212/241RPC/346/211/213/345/206/214.md +88 -0
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +105 -92
- package/_packed_docs/sdk/INDEX.md +197 -167
- package/_packed_docs/sdk/Ownership-SDK/345/256/236/347/216/260/346/214/207/345/215/227.md +169 -0
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/227.md +349 -0
- package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +930 -0
- package/_packed_docs/sdk/Ownership-SDK/351/233/206/346/210/220/346/214/207/345/215/227.md +270 -0
- 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 +363 -0
- 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 +553 -0
- 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 -0
- package/_packed_docs/sdk/Ownership2.1/350/257/246/347/273/206/350/256/276/350/256/241.md +480 -0
- package/_packed_docs/sdk/Ownership/347/256/241/347/220/206/344/270/223/351/242/230.md +559 -0
- package/_packed_docs/sdk/ProtectedHeaders/347/224/250/346/263/225/344/270/223/351/242/230.md +299 -0
- 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 +173 -0
- 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 +211 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273SDK/345/256/236/347/216/260/347/247/273/346/244/215/346/214/207/345/215/227.md +331 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273SDK/351/233/206/346/210/220/346/214/207/345/215/227.md +207 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/344/273/243/347/240/201/345/256/241/346/237/245/346/212/245/345/221/212.md +252 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/345/256/236/346/226/275/350/256/241/345/210/222.md +156 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/346/226/271/346/241/210.md +273 -0
- package/_packed_docs//350/267/250/350/256/276/345/244/207/345/267/262/350/257/273/346/234/252/350/257/273/350/257/246/347/273/206/350/256/276/350/256/241.md +211 -0
- package/dist/agent-md-schema.d.ts +16 -4
- package/dist/agent-md-schema.d.ts.map +1 -1
- package/dist/agent-md-schema.js +65 -30
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +35 -3
- package/dist/agent-md.d.ts.map +1 -1
- package/dist/agent-md.js +384 -150
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +59 -0
- package/dist/aid-store.d.ts.map +1 -1
- package/dist/aid-store.js +202 -16
- package/dist/aid-store.js.map +1 -1
- package/dist/aid.d.ts +4 -1
- package/dist/aid.d.ts.map +1 -1
- package/dist/aid.js +24 -42
- package/dist/aid.js.map +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +89 -18
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +6410 -1848
- package/dist/cert-utils.d.ts +50 -1
- package/dist/cert-utils.d.ts.map +1 -1
- package/dist/cert-utils.js +123 -56
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/delivery.d.ts +108 -16
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +1411 -184
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +4 -1
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +203 -117
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +22 -3
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +1312 -684
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +23 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +419 -101
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +8 -6
- package/dist/crypto.js.map +1 -1
- package/dist/events.d.ts +24 -3
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +171 -29
- package/dist/events.js.map +1 -1
- package/dist/facades.d.ts +42 -1
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +368 -12
- package/dist/facades.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/index.d.ts +14 -1
- package/dist/keystore/index.d.ts.map +1 -1
- package/dist/keystore/indexeddb-identity-store.d.ts +4 -0
- package/dist/keystore/indexeddb-identity-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-identity-store.js +30 -13
- package/dist/keystore/indexeddb-identity-store.js.map +1 -1
- package/dist/keystore/indexeddb-shared.d.ts +19 -2
- package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
- package/dist/keystore/indexeddb-shared.js +193 -6
- package/dist/keystore/indexeddb-shared.js.map +1 -1
- package/dist/keystore/indexeddb-token-store.d.ts +15 -2
- package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-token-store.js +308 -27
- package/dist/keystore/indexeddb-token-store.js.map +1 -1
- package/dist/org-protocol.d.ts +45 -0
- package/dist/org-protocol.d.ts.map +1 -1
- package/dist/org-protocol.js +827 -21
- package/dist/org-protocol.js.map +1 -1
- package/dist/ownership-v21.d.ts +43 -9
- package/dist/ownership-v21.d.ts.map +1 -1
- package/dist/ownership-v21.js +183 -81
- package/dist/ownership-v21.js.map +1 -1
- package/dist/ownership-workflow.d.ts +36 -1
- package/dist/ownership-workflow.d.ts.map +1 -1
- package/dist/ownership-workflow.js +610 -89
- package/dist/ownership-workflow.js.map +1 -1
- package/dist/seq-tracker.d.ts +2 -0
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +3 -2
- package/dist/seq-tracker.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +61 -3
- package/dist/tools/cross-sdk-agent.d.ts.map +1 -1
- package/dist/tools/cross-sdk-agent.js +524 -45
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +4 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +64 -30
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Ownership 2.1 SDK 应用集成指南
|
|
2
|
+
|
|
3
|
+
本文面向 EC CLI/Evolcore 等应用的集成开发者,以当前工作区的 Node.js TypeScript SDK 为例,说明身份准备、发起关系操作、接入审批界面、跟踪结果与断线恢复。主示例为 EC CLI 创建 agent 类型的 sub AID,由 Evolcore 一侧发起绑定,human owner 在自己的 App 中点击同意。EC CLI 当前尚未接入 Ownership 2.1,以下 SDK 代码是开发者需要接入的目标流程,不表示现有 CLI 已支持绑定命令。协议依据为 [Ownership 协议定义 2.1](../protocol/Ownership协议定义2.1.md);编排契约见 [Ownership SDK 编排指南 2.1](Ownership-SDK编排指南2.1.md),实现边界见 [Ownership 2.1 详细设计](Ownership2.1详细设计.md)。
|
|
4
|
+
|
|
5
|
+
普通 `agent.md` 的基础读取、验签、上传与显式 pending 恢复不以前置 Ownership 共识、owner Storage 或关系状态为条件。普通正文更新须原样保留当前原件中全部关系材料的字段存在性、类型和值,并遵守本人签名和原 ETag/CAS;材料无效或依赖不可用不能阻断这种更新。增删改关系字段继续执行当前双文件授权核验,不能借普通名片入口清除或替换 owner 锁。
|
|
6
|
+
|
|
7
|
+
需要实现或移植 SDK 内部机制时,查阅 [Ownership 2.1 SDK 开发与移植指南](Ownership2.1-SDK开发与移植指南.md);本文聚焦应用公有接口。
|
|
8
|
+
|
|
9
|
+
本文使用当前 [包入口](../../ts/src/index.ts) 和 [AUNClient](../../ts/src/client.ts) 的公有 API。工作区包名为 `@agentunion/fastaun`、参考版本为 `0.5.21`,要求 Node.js `>=22.16.0`,见 [package.json](../../ts/package.json)。这些信息描述当前源码,不表示同版本 npm 包已经发布或包含本工作区的全部 2.1 实现;EC 集成时应核对实际依赖具有本文接口与行为,不能直接假定现有旧依赖已经支持。旧 `Ownership-SDK集成指南.md`、`Ownership-SDK实现指南.md` 属于 legacy;协议 3.0 不属于本文范围。
|
|
10
|
+
|
|
11
|
+
兼容方向为新服务端兼容新旧 SDK 的既有身份认证、普通名片和通信入口,并保留旧 SDK 的 legacy owner 操作;新 SDK 的 2.1 关系操作不兼容旧服务端。Ownership 2.1 当前关系始终重新核对两份当前文件;旧 SDK 的旧格式关系由隔离的 Auth JSONL、operation ID 和 NS ownership_proof 兼容,不生成 2.1 双文件或共识,也不得覆盖已存现代声明。不把新 SDK 源码调用形态兼容作为本契约要求。
|
|
12
|
+
|
|
13
|
+
## 1. 应用需要理解的关系边界
|
|
14
|
+
|
|
15
|
+
`group/org` 作为被管理的 `sub` 时使用自身生命周期:创建自动建立 owner,解散自动解除,专属转移强制 rekey,身份材料始终由当前 owner 持有;它们不适用本指南针对 `sub` 的绑定、释放、转移和审批流程。Group/Org 仍可按普通主体关系中的 owner 规则作为 `owner_aid`。将 Group/Org 作为 `sub` 调用任务 Facade 会 reject/抛出 `not_applicable`(`retryable=false`);对其调用 `checkOwnershipConsensus` 才会返回 `status/code=not_applicable` 的共识结果对象。名片必须含 owner,必须省略 ownership、ownership_proof、ownership_release,并由实体私钥主签、当前 owner 使用本人 token 上传,可选追加 owner 附签;完整格式见 [协议 §2.5](../protocol/Ownership协议定义2.1.md#25-grouporg-名片的实体主签与-owner-上传)。Group 入口见 [Group RPC Manual](09-group-rpc-manual.md#群组生命周期),Org 沿用专属 0.8 生命周期,不把组织成员双签解释为 Ownership 2.1。
|
|
16
|
+
|
|
17
|
+
现代 Group/Org 文件的 `entity_cert_fingerprint` 与主签 `cert_fingerprint` 必须是相同的完整 `sha256:<64位小写hex>`,主块显式 `signer_aid=实体AID`;每个附签必须是当前 owner,存在就必须全验。只有 type=group、恰好一个签名块、未出现 entity_cert_fingerprint 且主块 signer_aid 缺省或等于群 AID 的文件才可走旧 Group 读取兼容;字段已出现但无效不能按旧格式放行,Org 没有此入口。
|
|
18
|
+
|
|
19
|
+
Ownership 是 `agent.md` 上叠加的可选关系属性。Ownership 关系无效或暂时不可确认,只限制依赖该关系的授权、绑定、释放、转移等操作;它本身不会使基础格式和外层签名有效的 `agent.md` 失效。普通读取、下载、基础验签及通信仍可继续。NS 兼容旧 SDK 不带 Ownership 专用 Header 的普通读写和旧格式名片上传;旧关系字段在正文更新时必须原样保留。新 SDK 新建关系或提交新格式时仍须执行当前 Ownership 规则,不能用旧客户端兼容入口绕过校验。
|
|
20
|
+
|
|
21
|
+
| 名称 | 应用中的含义 |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| `sub_aid` | 被管理身份;签署自己的 `agent.md`,以自己的认证身份提交到 NS。 |
|
|
24
|
+
| `owner_aid` | 绑定目标或当前/原 owner;签署、发布自己 Storage 中的 `owner.md`。 |
|
|
25
|
+
| `new_owner_aid` | 转移目标;独立签署、发布自己的目标 `owner.md`。 |
|
|
26
|
+
| NS | 以数据库事务和 CAS 持久化 sub 的权威 `agent.md` 与同步待办,根据该名片和 owner 的权威 `owner.md` 验证当前关系。 |
|
|
27
|
+
| Storage | 保存 owner 的权威 `owner.md`,以及 NS 异步同步的 sub 名片副本。 |
|
|
28
|
+
|
|
29
|
+
每个参与身份都需要自己的密钥、证书和客户端。owner 权限不等于持有 sub 私钥,也不授予代签或代上传能力。owner 文件位于 `owner_aid:/sub_aids/{sub_aid}/owner.md`;sub 的权威名片位于 NS,`sub_aid:/agent.md` 是其 Storage 副本。
|
|
30
|
+
|
|
31
|
+
Ownership 2.1 关系事实只来自 sub 的权威 `agent.md` 与 owner 签署、保存在自己 Storage 中的权威 `owner.md`。`owner_aid` 是 `owner.md` 中的 owner 身份字段,不是独立文件或数据库关系记录。NS 的数据库事务只保证 `agent.md` 原文、CAS 更新与同步待办的原子性,不另存关系账本或验收证据表,不依赖 `ownership.journal`、独立关系日志或 reserve-confirm 恢复流程。SDK 本地任务数据库仅用于恢复本端编排任务,不是关系事实的替代来源。
|
|
32
|
+
|
|
33
|
+
应用调用 Facade 表达意愿,SDK 通过普通加密 P2P 消息协调各端自己的文件操作,NS 验收结果决定关系。本指南的 2.1 编排不新增 ownership 专用 RPC,也不需要应用自行构造控制消息或调用内部文件方法。文件角色、上传身份及 owner 锁约束见 [协议第 1、2 节](../protocol/Ownership协议定义2.1.md#1-权威文档与-owner-锁)。
|
|
34
|
+
|
|
35
|
+
## 2. 接入前提与能力检查
|
|
36
|
+
|
|
37
|
+
| 前提 | 接入要求与不足时的处理 |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| 独立身份 | 各参与端加载本身份可用的私钥和证书。`AIDStore.load()` 成功也可能只得到公钥证书,仍须检查 `isPrivateKeyValid()`。 |
|
|
40
|
+
| 初始名片 | NS 上已有 sub 自己签署、上传的初始 `agent.md`。可用 `AIDStore.downloadAgentMd(subAid)` 确认可读;真正的关系变更仍由 Facade 新鲜检查。不存在时会遇到 `unavailable`,不能以本地空白名片代替。 |
|
|
41
|
+
| NS 2.1 | 部署支持基于两份权威文件的 2.1 新鲜关系检查,以及名片和同步待办的原子 CAS。只读共识检查遇到不支持时返回 `unavailable`,其 `code` 可为 `unsupported_protocol`。 |
|
|
42
|
+
| Storage | 部署支持权威对象查询和完整文件原子发布;写入前核对起始完整原文、摘要和存在性,清理前核对当前 NS 和本任务完整原件。 |
|
|
43
|
+
| P2P 编排 | 参与端运行支持当前编排的 SDK。对端离线或不能处理请求时保持等待,不把超时、ACK 或投递成功当作批准。 |
|
|
44
|
+
| 持久任务存储 | 固定、可写、可恢复的数据目录;创建和更新任务必须能够原子保存。存储不可用或损坏时停止有副作用的编排。 |
|
|
45
|
+
| 可信根与当前证书状态 | 安全配置根证书,验证证书链、用途和当前撤销状态。TLS 校验与文件签名验证都需要成立。 |
|
|
46
|
+
|
|
47
|
+
`checkOwnershipConsensus()` 是当前关系的只读预检,不是全部服务能力的探测接口。尤其是无 owner 时,它不会验证尚未读取的 owner Storage 发布能力;部署能力仍需由服务配置和验收结果确认。
|
|
48
|
+
|
|
49
|
+
`AIDStore` 的配置参数是 `aunPath`、`encryptionSeed`、`slotId?`、`verifySsl?`、`rootCaPath?`、`debug?`,见 [AIDStore](../../ts/src/aid-store.ts)。生产应用应显式设置 `verifySsl: true`,通过可信部署渠道配置 `rootCaPath`;该路径用于 SDK 的 AUN 证书信任验证,不自动替代 Node.js HTTPS/TLS 自身的信任配置。私有 TLS 站点仍需正确配置 Node.js 的 TLS 信任,不能仅凭该路径就视为可信。不能用对端提供的任意根替换本地信任配置。服务发现及外部地址使用部署域名,例如 `ns.agentid.pub`、`st.agentid.pub`。
|
|
50
|
+
|
|
51
|
+
默认数据根为用户目录的 `.aun`。当前本地存储在首选目录不可用时还可能回退到工作目录的 `.aun`;应用应事先确保配置的固定绝对目录可写,避免重启或工作目录变化后使用另一份数据。任务保存于 `{aunPath}/AIDs/{aid}/aun.db`,与该身份的密钥、证书、本地 secret store 和稳定设备信息一起保留。`slotId` 也应固定;它不是任务数据库的隔离目录。实际路径逻辑见 [LocalTokenStore](../../ts/src/keystore/local-token-store.ts) 和 [配置实现](../../ts/src/config.ts)。
|
|
52
|
+
|
|
53
|
+
`persistence_unavailable` 表示本地任务存储能力缺失、数据库恢复不可用、任务记录损坏或原子保存失败;远端 NS ETag、owner 原件或原 NS CAS 条件变化属于 `conflict`,不是本地持久化故障。它不是连接成功后就能忽略的提示;Facade 可抛出该错误,恢复也会停止。只读共识检查不依赖本地任务存储,不能用其成功证明任务可持久化。
|
|
54
|
+
|
|
55
|
+
## 3. EC CLI 集成示例:sub 发起,human owner 同意
|
|
56
|
+
|
|
57
|
+
本节按执行顺序展示两端接线;sub 代码运行于 EC/Evolcore 的 AUN 运行层,owner 代码运行于 owner 自己的 Node.js App 后端。owner 的人机界面调用该后端审批;浏览器 SDK 的身份存储按其自身平台接口接入,不直接使用 Node.js 文件存储。
|
|
58
|
+
|
|
59
|
+
### 3.1 EC CLI 创建 sub 身份
|
|
60
|
+
|
|
61
|
+
EC 现有创建入口如下,`<EC持久目录>` 替换为本机固定绝对目录;本例创建普通 agent,不在注册时指定 owner:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
ec aid new helper.agentid.pub --aun-path "<EC持久目录>" --format json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
命令注册身份并尝试上传普通 agent 名片,应用按业务需要检查 agentmdUploaded,失败时可用现有 `ec aid agentmd put helper.agentid.pub --aun-path "<EC持久目录>"` 显式重试。普通名片发布成功不是关系绑定前提;EC 开发者仍需接入第 3.4 节运行层。现有扫码绑定和本地 owners[] 不等于 Ownership 共识。
|
|
68
|
+
|
|
69
|
+
### 3.2 两端分别装载自己的身份
|
|
70
|
+
|
|
71
|
+
以下公用装载函数分别放在两端代码中。`subConfig` 必须沿用 EC 创建身份时的同一 `aunPath` 与身份解密配置,并使用运行层固定的 slot,不能换用 SDK 默认 `.aun` 或另一 seed;当前 EC 的 seed 策略固定为 `evol`。`ownerConfig` 来自 owner App 自己的独立存储,`owner.agentid.pub` 已注册为 human。两者都应配置可信根。配置字段不是 `AUNClient` 构造参数。
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { AIDStore, AUNClient } from '@agentunion/fastaun';
|
|
75
|
+
type IdentityConfig = { aunPath: string; encryptionSeed: string; rootCaPath: string; slotId: string };
|
|
76
|
+
function loadOwnClient(aid: string, config: IdentityConfig): AUNClient {
|
|
77
|
+
const store = new AIDStore({ ...config, verifySsl: true });
|
|
78
|
+
const loaded = store.load(aid);
|
|
79
|
+
if (!loaded.ok) throw new Error(loaded.error.message);
|
|
80
|
+
if (!loaded.data.aid.isPrivateKeyValid()) throw new Error('本身份私钥不可用');
|
|
81
|
+
return new AUNClient(loaded.data.aid);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
构造函数接收 `AID` 对象或无参,不接收 AID 字符串、配置对象或其它身份的凭据。需要延后装载时,可在无身份或已关闭状态调用 `loadIdentity(aid)`。本例直接传入已装载的 AID,使客户端沿用其持久目录、设备、slot、TLS 和可信根配置。连接选项传给 `connect()`。
|
|
86
|
+
|
|
87
|
+
两端共用以下事件订阅方式。`updateOwnershipView(event: string, payload: Parameters<EventHandler>[0]): void | Promise<void>` 由应用实现,保存任务进度并更新 CLI 状态或 App 界面;事件直接携带载荷,没有 `event.data` 包装。
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import type { EventHandler } from '@agentunion/fastaun';
|
|
91
|
+
const events = ['ownership.action_required', 'ownership.progress', 'ownership.completed',
|
|
92
|
+
'ownership.rejected', 'ownership.stopped', 'ownership.error'];
|
|
93
|
+
function watchOwnership(client: AUNClient): void {
|
|
94
|
+
for (const event of events) client.on(event, payload => updateOwnershipView(event, payload));
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3.3 owner App 先订阅审批,再连接
|
|
99
|
+
|
|
100
|
+
owner App 展示 SDK 已验证的 `ownership.request`,包含操作、sub、owner、版本和发起方。`EventHandler` 是通用载荷,下面先收窄 `operation_id`;其余展示字段按第 5 节解析。`showOwnerApproval(payload: Parameters<EventHandler>[0], decide: (accept: boolean) => Promise<void>): void` 由 App 实现:展示同意/拒绝按钮,用户点击时才调用 `decide`,并处理其异步错误;同一 ID 幂等更新界面。它不是 SDK 内置 UI。
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const ownerClient = loadOwnClient('owner.agentid.pub', ownerConfig);
|
|
104
|
+
ownerClient.on('ownership.request', payload => {
|
|
105
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) return;
|
|
106
|
+
const operationId = 'operation_id' in payload ? payload.operation_id : undefined;
|
|
107
|
+
if (typeof operationId !== 'string') return;
|
|
108
|
+
showOwnerApproval(payload, accept => decideOwner(operationId, accept));
|
|
109
|
+
});
|
|
110
|
+
watchOwnership(ownerClient);
|
|
111
|
+
await ownerClient.connect({ auto_reconnect: true });
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
按钮回调处理原任务。`saveBusinessTask(task: OwnershipTaskResult): Promise<void>` 是应用自实现的业务持久化函数,保存任务 ID、参与方、版本、状态与阶段;异常按第 9 节处理。
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
async function decideOwner(operationId: string, accept: boolean): Promise<void> {
|
|
118
|
+
const result = accept
|
|
119
|
+
? await ownerClient.acceptOwnershipRequest(operationId)
|
|
120
|
+
: await ownerClient.rejectOwnershipRequest(operationId, '用户拒绝');
|
|
121
|
+
await saveBusinessTask(result);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
请求回调只展示界面,不在收到事件时自动同意,也不等待用户操作而阻塞事件处理。owner 不再调用 `bindSubaid` 创建反向申请。human 可作为 owner;被禁止的是 human 自己作为 sub 声明 owner。
|
|
126
|
+
|
|
127
|
+
### 3.4 EC/Evolcore 的 sub 发起绑定
|
|
128
|
+
|
|
129
|
+
以下展示 sub 运行层尚无客户端时的初始化;已有客户端时直接复用,不再次装载和连接。先订阅结果事件,再连接,最后由 CLI 用户指令触发一次申请。sub 发起即表达自己的同意,不需要 sub UI,也不再调用审批方法。
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const subClient = loadOwnClient('helper.agentid.pub', subConfig);
|
|
133
|
+
watchOwnership(subClient);
|
|
134
|
+
await subClient.connect({ auto_reconnect: true });
|
|
135
|
+
const task = await subClient.bindOwneraid('owner.agentid.pub');
|
|
136
|
+
await saveBusinessTask(task);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`pending` 是正常等待审批或远端材料的结果;Promise 返回、消息 ACK、owner 点击同意均不等于完成。EC 应让持久运行层继续保持 sub SDK 在线,处理 owner 的批准和后续文件交换;CLI 可返回原 `operation_id`,不能因发起接口返回就终止唯一的 sub 运行实例。重连由 SDK 恢复同一任务,不重新调用绑定。若复用 EC 已有客户端,应在其连接前订阅并复用该实例,不为此流程另开同一消费身份的竞争连接。
|
|
140
|
+
|
|
141
|
+
各端通过 `ownership.completed` 记录本端任务目标已新鲜核验。owner App 查看当前关系必须显式传 sub AID;省略参数会检查 human owner 自己:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const current = await ownerClient.checkOwnershipConsensus('helper.agentid.pub');
|
|
145
|
+
showConsensus(current);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`showConsensus(result: OwnershipConsensusResult): void` 为 App 自实现函数;仅在 `status === 'consensus'` 且 owner 与 sub 匹配时展示当前绑定成立,六态和授权边界见第 7 节。两端均先订阅再连接;`connect()` 返回不代表后台注册意图或任务恢复已结束。页面卸载可调用 `on()` 返回的 `Subscription.unsubscribe()`。真实接线见 [AUNClient](../../ts/src/client.ts)、[事件类型](../../ts/src/events.ts) 和 [工作流实现](../../ts/src/ownership-workflow.ts)。
|
|
149
|
+
|
|
150
|
+
### 3.5 首次注册时携带 owner 的替代分支
|
|
151
|
+
|
|
152
|
+
开发者也可在首次注册时保存 owner 意图。下面替代第 3.1 节的无 owner 创建及第 3.4 节的显式申请,不与它们重复执行;`store` 是按 subConfig 创建的 AIDStore:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
const registered = await store.register('helper.agentid.pub', {
|
|
156
|
+
type: 'agent', owner: 'owner.agentid.pub',
|
|
157
|
+
});
|
|
158
|
+
if (!registered.ok) throw new Error(registered.error.message);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`register()` 返回 `Result<{ registered: true }>`,并尝试以本身份条件创建初始名片。`type: 'agent'` 的 `owner` 可省略;省略时只初始化普通 `agent.md`,不保存 Ownership 关系意图。有 owner 时保存固定 `operation_id` 的 owner 注册意图;初始名片不直接写入 owner 关系,首次连接后 SDK 用原意图继续绑定,owner 仍须审批。应用需确认初始名片已可用,不能把 `registered: true` 当作关系建立完成,也不能再调用绑定发起接口来“继续注册”。`type: 'human'` 禁止提供 owner,`group/org` 要求当前 owner 并沿用专属生命周期。注册与恢复见 [AIDStore.register](../../ts/src/aid-store.ts) 和 [设计第 7.1 节](Ownership2.1详细设计.md#71-七个-facade-与内部复用)。
|
|
162
|
+
|
|
163
|
+
### 3.6 通用签验与多签名片
|
|
164
|
+
|
|
165
|
+
应用通过 `AIDStore.sign/verify` 使用通用签验,TS/JS 两者均须 await,返回 `Promise<Result>`。默认 `format: 'raw'` 生成/验证 detached Base64 签名;`format: 'document'` 返回签后全文与签名列表,verify 返回 valid、status、payload 和逐块 signatures。先检查外层 ok,再判断验签 valid;数学失败保留全部逐块结果,resolver 操作异常是外层 error。详细参数及四语言命名见 [API 手册](06-API手册.md#通用-sign--verify)。
|
|
166
|
+
|
|
167
|
+
输入默认是文本,不猜测路径或识别 file://;读文件须显式 inputType: 'file'(Python input_type),原地签写还须 document + inPlace: true(Python in_place),成功后才写回。raw 文件按任意原字节签验,字符串和 document 严格 UTF-8;浏览器 File/Blob 只读,FileSystemFileHandle 才能原地写。verify 默认离线加载本地公钥/证书,无需私钥;历史或远端证书由应用显式提供可信 certificateResolver,不能把通用数学验签当作证书链、当前生命周期或 owner 授权检查,既有 downloadAgentMd 仍保留原远程验证流程。
|
|
168
|
+
|
|
169
|
+
需要附签时对完整已签原文使用 document + append: true;后块签正文与全部前序完整块的原始 prefix,只有已有签名链的末字节非 CR/LF 时才补 LF,无旧块按首签要求非空正文以换行结束。TAG 仅字面标签、附签有则全验;返回列表只表示实际存在的签名,不能检测末端删签。agent.md、owner.md 与公共门面复用同一内部 core,业务仍单独校验 Schema、主签身份和资源授权;普通 agent.md/owner.md 主块不输出且不接受 signer_aid。sign 本身不发布文件,名片发布仍使用 uploadAgentMd,owner.md 仍由关系 Facade 管理,见 [协议 §2.4/§2.5](../protocol/Ownership协议定义2.1.md#24-文件签名)。
|
|
170
|
+
|
|
171
|
+
新 SDK 的每个 NS GET/HEAD/PUT(含 fallback、fresh、重试)携带 X-AUN-Signature-Format: multi-v1 获取完整多签。无头旧客户端的多签读取只返回正文与首块,单签保持原 raw;HTTP 的 ETag、304 与缓存按表示区分,服务完整存储不变,应用应保留该表示原 ETag 作为条件。实体 fresh GET 还同时携带 X-AUN-Ownership-Check: 1 与 Cache-Control: no-cache,绕过 LRU 全块新鲜验证,仍为 not_applicable,不进入通用关系账本。
|
|
172
|
+
|
|
173
|
+
## 4. 七个 Facade 的参数、角色与结果
|
|
174
|
+
|
|
175
|
+
六个任务/审批方法返回 `Promise<OwnershipTaskResult>`;共识方法返回独立的 `Promise<OwnershipConsensusResult>`。方法名的 `Owneraid`、`Subaid` 大小写需按下面原样使用。
|
|
176
|
+
|
|
177
|
+
| 方法及参数 | 本端调用角色 | 结果与行为 |
|
|
178
|
+
| --- | --- | --- |
|
|
179
|
+
| `bindOwneraid(ownerAid: string)` | sub | 请求绑定指定 owner;发起即表达 sub 意愿,owner 收到审批请求。 |
|
|
180
|
+
| `bindSubaid(subAid: string)` | owner | 请求管理指定 sub;sub 收到审批请求。 |
|
|
181
|
+
| `releaseSubaid(subAid: string)` | 当前/原 owner | 发布释放并等待 NS 确认;不要求 sub 审批或在线。 |
|
|
182
|
+
| `transferSubaid(subAid: string, newOwnerAid: string)` | 当前/原 owner | 请求 sub 和新 owner 审批后转移;新 owner 必须不同于原 owner。 |
|
|
183
|
+
| `acceptOwnershipRequest(operationId: string)` | 已验证请求的本端接收方 | 批准已有绑定或转移任务;关联原任务,不创建新任务。 |
|
|
184
|
+
| `rejectOwnershipRequest(operationId: string, reason?: string)` | 已验证请求的本端接收方 | 拒绝已有绑定或转移任务;`reason` 是可选字符串。 |
|
|
185
|
+
| `checkOwnershipConsensus(subAid?: string)` | 检查方 | 只读检查当前关系;省略参数时检查本端 AID,owner 查询自己管理的身份时应明确传入 sub。 |
|
|
186
|
+
|
|
187
|
+
任务结果包含 `operation_id`、`operation`(`bind`/`release`/`transfer`)、`sub_aid`、`owner_aid`、起始 `base_relation_version`、目标 `target_relation_version`、`status` 和 `step`;转移另有 `new_owner_aid`。`status` 为 `pending`、`completed`、`rejected`、`stopped` 或 `error`;`step` 是当前本端阶段字符串,不是共识枚举。`code`、`reason`、`retryable` 是可选错误信息。
|
|
188
|
+
|
|
189
|
+
`pending` 可保留等待恢复的工作;`rejected`、`stopped`、`error` 会停止常规任务推进,不能假定重连后都能继续。`completed` 后仍可能为字段清理或旧文件清理发布 `ownership.error`;应用应根据任务状态和当前共识展示清理失败,不能把既成关系改回未完成。
|
|
190
|
+
|
|
191
|
+
独立绑定示例适用于已准备好的存量 sub,且没有正在续跑的 owner 注册意图。`saveBusinessTask(task: OwnershipTaskResult): Promise<void>` 由应用实现,持久保存业务记录与 SDK 任务 ID 的对应关系:
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
import type { OwnershipTaskResult } from '@agentunion/fastaun';
|
|
195
|
+
const task: OwnershipTaskResult = await subClient.bindOwneraid('owner.agentid.pub');
|
|
196
|
+
await saveBusinessTask(task);
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
不要只保存“已点击绑定”:保存 `operation_id`、参与 AID、起始/目标版本、最后的 `status`、`step` 和错误信息,便于页面重载后继续展示同一业务任务。任务结果可带等待或错误信息,Promise 正常返回也不一定是 `completed`。类型定义见 [OwnershipTaskResult](../../ts/src/ownership-workflow.ts),包入口已公开该类型。
|
|
200
|
+
|
|
201
|
+
四个发起 Facade 会先匹配本端相同的进行中意图;匹配本端身份、发起方、操作、全部参与方及起始/目标关系版本时复用原 `operation_id`,没有匹配任务时才生成新的 UUID。应用收到 ready 消息、超时或断线后应让 SDK 恢复原任务,不能通过更改参数或伪造 `operation_id` 冒充原任务重试。
|
|
202
|
+
|
|
203
|
+
首次权威预检抛错时可能尚未创建任务,应用不一定拿到 `operation_id`;其它阶段抛错也不保证任务或副作用不存在。应用应结合已保存的业务记录、已收到的事件和当前权威关系确认阶段,不能以“没有返回 ID”为由盲目重复发起。
|
|
204
|
+
|
|
205
|
+
## 5. 审批与本地事件接入 UI
|
|
206
|
+
|
|
207
|
+
本地事件直接携带任务结果字段,并增加以下信息。它们属于本端 SDK 通知,不是服务端 `event/...`,也不作为 P2P 消息再次发送。
|
|
208
|
+
|
|
209
|
+
| 载荷字段 | UI/策略用途 |
|
|
210
|
+
| --- | --- |
|
|
211
|
+
| `operation_id`、操作和参与 AID | 关联业务任务,展示被管理身份、原 owner、转移目标。 |
|
|
212
|
+
| `requester_aid` | 仅 `ownership.request` 附带,经消息层确认的发起方;不能从任意聊天文本自报字段推导审批身份。 |
|
|
213
|
+
| `local_roles` | 本端承担的 `owner`、`sub`、`new_owner` 角色数组;同一 AID 可同时承担多个角色。当前实现为各 Ownership 本地事件附带它。 |
|
|
214
|
+
| `base_relation_version`、`target_relation_version` | 本次固定审批上下文,不允许 UI 在批准时替换目标。 |
|
|
215
|
+
| `relation_version` | SDK 已核验本任务时附带的实际验收版本:release 按 released/v 返回 v、按 unbound/0 返回 0;base/target 仍固定 v。已有历史事件依据原验收记录,未核验时可缺省,不能替代当前新鲜共识。 |
|
|
216
|
+
| `status`、`step`、`code?`、`reason?`、`retryable?` | 当前任务及错误展示;错误字段按实际存在处理。 |
|
|
217
|
+
|
|
218
|
+
| 事件 | 应用处理 |
|
|
219
|
+
| --- | --- |
|
|
220
|
+
| `ownership.request` | 显示同意/拒绝或交给明确的自动策略;策略未决定时保持待审批。 |
|
|
221
|
+
| `ownership.action_required` | 提示释放后 sub 的名片清理缺少应用明确授权;处理见第 6.2 节。 |
|
|
222
|
+
| `ownership.progress` | 更新本端进度,不宣布关系成立。 |
|
|
223
|
+
| `ownership.completed` | 记录本任务目标已核验;关系清理和凭据交接另行跟踪;普通名片副本独立同步。 |
|
|
224
|
+
| `ownership.rejected` | 本次审批拒绝,不回滚已验收的历史关系。 |
|
|
225
|
+
| `ownership.stopped` | 本次流程不再推进;不是关系解锁通知。 |
|
|
226
|
+
| `ownership.error` | 展示错误和可重试提示,核对载荷中的任务状态;已完成关系的后续清理错误单独展示。 |
|
|
227
|
+
|
|
228
|
+
`EventHandler` 是通用载荷类型,不能把回调参数直接当作一个已声明的专用请求类型。第 3.3 节的 `showOwnerApproval` 应解析本端请求字段并保存 `operation_id`,再产生自己的界面决定。下面展示其按钮回调中的错误处理;`appApproval` 由该 UI 提供,类型为 `{ operation_id: string; accept: boolean; reason?: string }`;`showOwnershipError(code: string, retryable: boolean): void` 也是应用自实现函数。
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
import { AUNError } from '@agentunion/fastaun';
|
|
232
|
+
try {
|
|
233
|
+
const result = appApproval.accept
|
|
234
|
+
? await ownerClient.acceptOwnershipRequest(appApproval.operation_id)
|
|
235
|
+
: await ownerClient.rejectOwnershipRequest(appApproval.operation_id, appApproval.reason);
|
|
236
|
+
await saveBusinessTask(result);
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (error instanceof AUNError) showOwnershipError(error.stringCode, error.retryable);
|
|
239
|
+
else throw error;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
同一批准或拒绝可按原 ID 幂等处理,已经持久保存的决定不能改成相反决定。发起方无需再批准自己;审批方法只用于本端已有、已验证的绑定或转移请求。无界面应用也必须明确作出同意或拒绝,SDK 不因无人响应而默认批准。
|
|
244
|
+
|
|
245
|
+
恢复可能再次发出待审批请求。UI 按 `operation_id`、事件名和 `step` 幂等更新,已保存的决定不重新询问或改变。不要把所有历史事件都会重放当作前提:应用自己的业务记录和最后进度仍需持久保存。载荷与接线依据见 [编排指南第 2.6 节](Ownership-SDK编排指南2.1.md#26-本地事件与完成依据) 和 [当前 emit 实现](../../ts/src/ownership-workflow.ts)。
|
|
246
|
+
|
|
247
|
+
## 6. 关系操作流程
|
|
248
|
+
|
|
249
|
+
### 6.1 绑定:双方都可发起
|
|
250
|
+
|
|
251
|
+
| 发起方 | 入口 | 接收方审批后的共同顺序 |
|
|
252
|
+
| --- | --- | --- |
|
|
253
|
+
| sub | `subClient.bindOwneraid(ownerAid)` | owner 发布自己的 `owner.md` → sub 自签提交自己的 `agent.md` → NS 验收目标 owner 与版本 → 各端新鲜核验完成。 |
|
|
254
|
+
| owner | `ownerClient.bindSubaid(subAid)` | sub 批准后,按同一文件顺序推进。 |
|
|
255
|
+
|
|
256
|
+
绑定只从当前两份权威材料确认无锁时开始,目标版本为 `agent.md` 当前可见声明版本加一;名片无声明时基数为 `0`,目标为 `1`。已有稳定 owner 锁时,sub 不能通过普通名片更新清除或更换 owner。应用也不能因双方私下同意就跳过 NS 验收。
|
|
257
|
+
|
|
258
|
+
释放后再绑定同一 owner,若 sub 的 `agent.md` 仍保留旧声明,须先由 sub 完成已有字段清理,再发布新的 owner declare;SDK 在创建任务或产生副作用前以 `conflict`/`action_required` 提示,避免新 declare 覆盖唯一释放依据。绑定不同 owner 仍可使用当前可见版本 `v+1`;已清理时默认从 `1` 开始。
|
|
259
|
+
|
|
260
|
+
### 6.2 释放:原 owner 发起,sub 可以离线
|
|
261
|
+
|
|
262
|
+
原 owner 调用 `releaseSubaid(subAid)`,SDK 发布当前声明版本 `v` 的 release 文件;释放任务的起始、目标及历史 verified 版本均为 `v`,NS 不另存释放状态或递增版本。sub 不必在线;NS 根据 `agent.md` 的当前声明与有效 release 文件,或该 owner 路径的权威不存在结果,动态确认 `released`。服务或验证依赖不可用不能当作删除。sub 的旧名片字段可暂时保留,原 owner 可凭新鲜 `released/v`,或本任务 release 原件与当前 owner.md 全文、hash、当前有效证书精确匹配后确认的真实 `unbound/0` 完成;响应丢失时重新读取当前完整文件确认。实际完成证据保留真实状态和版本;权威删除不是取消任务。
|
|
263
|
+
|
|
264
|
+
sub 收到 release 通知时,可使用本人明确 accept、含 sub 角色,且本人已签 agent 的 owner、sub 与被释放完整 statement(含 declaration_id、版本)完全匹配的原绑定/转移记录自动自签清理,即使原任务因发布响应丢失仍 pending;转移历史匹配其目标 owner。无控制消息时,仅已完成历史任务的恢复路径触发自动清理,即使没有收到 relation.confirmed,也须新鲜核验权威释放事实。清理原件及原 CAS 单独保存,历史 completed 及完成证据保持。响应丢失后复用清理原件与条件,原文、ETag及已知提交 ETag 已对应原提交时只观察完成,字段已清空时不再签名或 PUT。缺少该授权且旧字段仍在时,发布 `ownership.action_required`,本端清理任务保持等待。
|
|
265
|
+
|
|
266
|
+
释放清理不能调用 `acceptOwnershipRequest`/`rejectOwnershipRequest`,这两个接口会拒绝 release 任务。应用明确决定清理后,由 sub 用自己的身份通过现有 `AIDStore.uploadAgentMd(subAid, content)` 自签上传清除旧 `owner`、`ownership` 的名片,遵守当前 NS 条件与代际,不能指定其它上传身份或覆盖后续关系。新鲜有效名片的关系字段已清空时,SDK 仅在本任务持久清理原件、摘要、原 CAS,或本人明确 accept 的匹配原 bind/transfer.release_cleanup,与当前 NS 原文、摘要、ETag及已知提交 ETag 精确对应后观察完成;空字段本身不证明该任务完成,也不补造 sub 的清理同意或历史条件。
|
|
267
|
+
|
|
268
|
+
已完成的历史绑定/转移或释放任务保持历史完成,但当前关系必须从两份权威材料重新判断:旧声明仍在且释放依据有效时为 `released`,关系字段清理后为 `unbound`、版本 `0`。NS 不保留释放终局或历史版本上界,材料不可确认时不得沿用历史释放结果作当前授权。详细释放与清理规则见 [编排指南第 2.4 节](Ownership-SDK编排指南2.1.md#24-应用层-facade编排审批与共识检查) 和 [协议第 4.2 节](../protocol/Ownership协议定义2.1.md#42-解绑)。
|
|
269
|
+
|
|
270
|
+
### 6.3 三方转移
|
|
271
|
+
|
|
272
|
+
原 owner 调用 `transferSubaid(subAid, newOwnerAid)`。sub 与新 owner 分别接到同一任务的审批请求,两者可任意先后决定;全部同意后,原 owner 发布指定新 owner 的转移授权,新 owner 发布目标 `owner.md`,sub 自签提交目标 `agent.md`,NS 从旧版本 `v` 直接切换到 `v+1`。
|
|
273
|
+
|
|
274
|
+
任一尚待决定的接收方拒绝,审批阶段结束并保留原关系。批准消息本身不能完成转移;迟到拒绝不能改变同一审批方已保存的同意或已提交的关系。转移授权具有固定期限,恢复不能刷新期限或换目标,过期或版本冲突后停止旧流程。应用不得把转移失败自动改为先释放再绑定;该做法会改变授权条件和关系连续性。转移验收见 [协议第 4.3 节](../protocol/Ownership协议定义2.1.md#43-transfer_owner)。
|
|
275
|
+
|
|
276
|
+
### 6.4 自拥有与角色重合
|
|
277
|
+
|
|
278
|
+
| 情形 | 本端决定与文件要求 |
|
|
279
|
+
| --- | --- |
|
|
280
|
+
| 建立 self-owner | sub 调用 `bindOwneraid(自己的 AID)`,或 owner 角色调用 `bindSubaid(自己的 AID)`;一次发起覆盖本端两个角色,仍分别签署、提交双文件。 |
|
|
281
|
+
| 外部 owner → self-owner | 原外部 owner 发起转移,目标为 sub;sub 同时承担 `sub` 和 `new_owner`,一个审批决定覆盖两角色,先发布自己的 owner 文件再提交关系文件。 |
|
|
282
|
+
| self-owner → 外部 owner | 同一 AID 兼任原 owner 与 sub,发起意愿覆盖这两个本端角色,外部新 owner 仍须审批。 |
|
|
283
|
+
|
|
284
|
+
SDK 合并同一接收 AID 的请求,不给自己发送 P2P。self-owner 仍要验证双文件并建立锁;`human` 不能声明 owner,包括自拥有;SDK 在任务、消息和文件副作用前拒绝此绑定。原 owner 与新 owner 相同不是有效转移。业务若要求外部管理方,还须检查 `owner_aid != sub_aid`,不能仅凭 self-owner 的 `consensus` 满足该要求。参见 [协议第 4.5 节](../protocol/Ownership协议定义2.1.md#45-self-owner-的建立解绑与转移)。
|
|
285
|
+
|
|
286
|
+
## 7. 任务完成与当前共识六态
|
|
287
|
+
|
|
288
|
+
任务状态回答“这一个本端业务任务推进到哪里”,共识状态回答“当前两份权威材料证明什么关系”。普通主体适用下表六态;Group/Org 作为 `sub` 调用共识检查时返回特殊 `status/code=not_applicable`、`retryable=false`,不属于六态。P2P 投递成功、ACK、对端 `relation.confirmed` 提示或本地阶段标记都不是任务完成证据。绑定/转移的完成要求新鲜 NS 目标 owner、目标版本与本任务文件材料匹配;原 owner 必须有本任务已保存的转移授权,接收方固定首次验证授权的全文摘要及实际期限,不接受恢复时换字节或延期;释放完成要求新鲜 `released/v`,或按本任务原件严格关联的真实 `unbound/0`,任务起始、目标版本保持 `v`,共识验收证据及公共事件 relation_version 使用该任务实际验收的 released/v 或 unbound/0;已有历史验收记录不改写,也不替代之后的当前关系查询。
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
import type { OwnershipConsensusResult } from '@agentunion/fastaun';
|
|
292
|
+
const consensus: OwnershipConsensusResult = await ownerClient.checkOwnershipConsensus('helper.agentid.pub');
|
|
293
|
+
showConsensus(consensus);
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
`showConsensus(result: OwnershipConsensusResult): void` 为应用自实现展示函数。结果包含 `status`、`sub_aid`、`owner_aid`(可为 null)、`relation_version`、`lock`、`agent_md_etag`、`agent_md_sha256`、`owner_md_sha256`,以及可选 `code`、`reason`、`retryable`。当 `status` 不是 `consensus` 或 `released` 时,未取得的权威观察字段可能为 null、空值或 SDK 使用的占位值(例如 `0`、`unlocked`);它们不表示实际观察到对应版本、锁或文件证据。应用必须先判断 `status`,任何结果字段本身都不能单独作为授权证据。定义见 [OwnershipConsensusResult](../../ts/src/ownership-v21.ts)。
|
|
297
|
+
|
|
298
|
+
| 共识状态 | 应用含义 |
|
|
299
|
+
| --- | --- |
|
|
300
|
+
| `consensus` | 当前未释放关系的身份、版本和双方完整文件签名匹配;执行端仍需认证调用者并核对业务权限范围。 |
|
|
301
|
+
| `released` | `agent.md` 仍有当前声明,但对应 `owner.md` 为有效 release 或已权威确认不存在;版本仍为该声明的 `v`,旧 owner 不再据此获权。 |
|
|
302
|
+
| `unbound` | 新鲜有效的权威名片没有当前关系声明,版本为 `0`;释放后字段清理也属于此态。解析失败、服务不可用或不完整观察不能推断无关系,此态也不证明某个 SDK 任务已结束或对端从未准备文件。 |
|
|
303
|
+
| `single_sided` | 仅一方准备或声明,稳定关系尚未成立。 |
|
|
304
|
+
| `invalid` | 字段、路径、角色、版本或签名无效,不能授予 owner 权限。 |
|
|
305
|
+
| `unavailable` | 当前 NS、Storage 或证书事实不能确认;保留最后已确认状态用于展示,不将未知当作解绑或授权。 |
|
|
306
|
+
|
|
307
|
+
公开共识方法只有 sub 参数,不能枚举全网独立 owner 声明;NS 尚无 owner 且检查器没有目标上下文时,owner 单方已准备仍可能显示 `unbound`。该边界不能被 UI 用来推断某个绑定任务已取消。
|
|
308
|
+
|
|
309
|
+
四 SDK 普通名片下载的 `verification.ownership_status` 仍是 legacy proof 展示字段,不是 2.1 授权结果。文件签名有效或旧展示状态为 complete 不能证明 2.1 共识;该展示字段对 2.1 名片显示不完整或其他旧状态也不能代替当前关系检查。应用使用 `checkOwnershipConsensus(subAid)` 获取 2.1 新鲜结果。
|
|
310
|
+
|
|
311
|
+
关系完成、subject 关系字段清理、旧 owner 文件清理和凭据交接分别展示。普通名片副本独立同步,不参与关系验收,也不替代两个当前关系文件。
|
|
312
|
+
|
|
313
|
+
敏感业务在执行时由执行端核对当前 owner、sub、关系版本、权限范围和新鲜共识,并保存授权证据;UI 布尔值、历史完成事件和旧 token 不替代该校验。若业务使用 token/ACL,应把它们绑定到完整关系声明及其版本,并新鲜检查释放、转移后的有效性;清理后重新绑定可能再次使用版本 `1`,版本号不能单独识别关系。完整授权边界见 [协议第 6 节](../protocol/Ownership协议定义2.1.md#6-共识审计与安全边界)。
|
|
314
|
+
|
|
315
|
+
## 8. 断线与重启恢复
|
|
316
|
+
|
|
317
|
+
0.5.20、0.5.19 及更早任务按原格式及原有协议边界兼容;保留原 operation、有效审批、原签名字节和原提交条件,不能因缺少后增本地字段而一律停止或新建任务。历史适配、绑定容错和无参数 reset 的完整范围见 [编排指南第 8 节](Ownership-SDK编排指南2.1.md#8-崩溃与响应丢失后的恢复)。reset 只归档当前身份发起的未完成任务,保留原记录和远端文件,迟到消息不能复活。 旧 Owner 候选尚未发布时,原 `expected_revision` 必须有权威证据精确匹配,不能用当前 version 替代;服务未提供旧 revision 证据时保留原件及任务并返回 unavailable。目标已提交但任务仍待恢复时,只有本地原始签名候选与当前双方共识精确匹配才确认完成;缺少这些证据不能从当前网络补造历史原件或提交条件。
|
|
318
|
+
|
|
319
|
+
1. 启动时恢复原 `aunPath`、密钥解密配置、稳定设备和 slot,装载同一身份,先注册事件处理器再连接。
|
|
320
|
+
2. SDK 从自己的持久任务继续审批、已签文件和待发送通知;请求重发和响应丢失的恢复复用原字节与原提交条件。恢复先核对权威关系和本任务证据,旧任务不能覆盖后续代际。
|
|
321
|
+
3. 应用从自己的数据库恢复业务记录与 `operation_id`,幂等更新 UI。待审批请求可再次通知;已经保存的决定不重新作相反选择。
|
|
322
|
+
4. 已合法完成的历史任务可以保留 `completed`,即使当前关系已被后续释放或转移;当前状态另调 `checkOwnershipConsensus(subAid)` 获取。
|
|
323
|
+
|
|
324
|
+
当前七 Facade 没有公开“按 operation_id 查询任务”、取消任务或强制解锁接口。`getOwnershipStatus()`/`getOwner()` 读取旧 metadata,不是 2.1 任务查询或新鲜共识;cross-sdk 测试 agent 的私有存储查询也不是应用 API。因此业务层必须保存自己的任务关联和最后进度,不能依赖私有 `_tokenStore` 重建 UI。真实恢复触发点见 [AUNClient](../../ts/src/client.ts),任务恢复实现见 [OwnershipWorkflow](../../ts/src/ownership-workflow.ts)。
|
|
325
|
+
|
|
326
|
+
重复发起相同进行中操作会复用原 `operation_id`、审批、签名字节、提交条件和授权期限;匹配要求本端身份、发起方、操作、全部参与方及起始/目标关系版本一致。同代际不同进行中意图返回 conflict,不产生第二任务。拒绝、停止、不可重试 error 不复活;后续代际的新合法操作使用新任务,历史 completed 不仅凭参数相同复用。不要删除任务数据库、清除审批记录、删除 `owner.md` 或刷新条件来制造“恢复成功”;删除 owner 的权威文件本身可能导致释放,含义不是取消任务。
|
|
327
|
+
|
|
328
|
+
Group/Org 名片失败稿及 pending 保留实体命名空间中的完整多签原文、原 CAS、固定 owner 和实体证书指纹,由应用显式重试,post-connect/重连不隐式 PUT。重试先验证完整原件及当前 owner、状态和证书代际,原条件完整且同代际原文/ETag 已确认提交时只观察完成。转移、rekey 或解散后停止旧代际待办,不更换身份、指纹或条件重签。新 SDK 现代上传不再保存、刷新或检查额外 V2 授权及过期窗口;旧 V2 兼容入口仍按协议 §2.5 校验;普通文件签名与当前证书检查保留。专属 create/transfer 自身 checkpoint 恢复机制不变。
|
|
329
|
+
|
|
330
|
+
## 9. 错误处理与安全降级
|
|
331
|
+
|
|
332
|
+
错误有三种入口:Facade 抛出异常;任务结果/本地事件附带错误;共识返回 `invalid` 或 `unavailable`。抛出的 `AUNError.code` 是数字 RPC 错误码,Ownership 字符串码读取 `error.stringCode`,是否可重试读取错误实例的 `error.retryable`;正常返回的任务或共识结果则读取其 `code`、`reason`、`retryable`。
|
|
333
|
+
|
|
334
|
+
| 字符串码或状态 | 应用处理 |
|
|
335
|
+
| --- | --- |
|
|
336
|
+
| `persistence_unavailable` | 停止有副作用的编排,恢复原持久存储能力;不以新任务替代损坏的审批历史。 |
|
|
337
|
+
| `unsupported_protocol` | 暂停 2.1 变更并核对 SDK/服务能力;不回落到 legacy 代理流程。 |
|
|
338
|
+
| `owner_locked` | 当前关系已有锁;按当前 owner 的释放或转移流程处理。 |
|
|
339
|
+
| `conflict` | NS ETag、owner 原件、原 NS CAS 条件、版本、目标或审批已变化;停止旧目标并重新核对权威事实,不自动换 ETag 或起始 owner 原件。 |
|
|
340
|
+
| `forbidden` | 调用角色、身份或审批阶段不允许;不更换凭据冒用另一方。 |
|
|
341
|
+
| `operation_not_found` | 本端没有该 ID 的请求;确认身份、持久目录及 UI 关联,不由审批 API 创建任务。 |
|
|
342
|
+
| `invalid` | 输入、签名、证书或材料确定无效;已有任务为不可重试 error,不将验签失败当成服务不可用或同意。 |
|
|
343
|
+
| `unavailable` | 服务、网络或依赖不可用,包括权威元数据、正文摘要不一致及 Storage Base64 传输封装损坏;已有任务保持 pending 并可重试,首次权威预检失败不创建任务。摘要匹配后确定非法的 UTF-8、文件字段或签名归 invalid。初始名片缺失或当前证书事实无法确认均须按原因处理。 |
|
|
344
|
+
|
|
345
|
+
输入格式校验也可能抛出普通 `ValidationError`,其 `stringCode` 不一定已填;不要靠字符串码穷举替代正常异常处理。`retryable` 只提示可以恢复验证,不授权换目标、刷新期限或再发起一个新的操作。服务状态未知时,普通认证和通信可按各自能力继续,依赖 owner 权限的敏感操作须暂停。
|
|
346
|
+
|
|
347
|
+
等审批、等材料及缺少 2.1 能力同样保持 pending;版本替代、目标改变、授权过期或原条件失效为 stopped;明确拒绝为 rejected,完整目标确认才为 completed。决定停止前先核验目标是否已提交;completed 后通知或清理失败只记录错误和待办。本地任务数据库写入/CAS、租约或持久化损坏返回 `persistence_unavailable`,保持原存储状态并停止副作用;远端 NS ETag、owner 原件或原 NS CAS 条件变化归为 `conflict`。三个协议时间字段采用 `1..9007199254740991` 的十进制正整数;范围内仍执行证书、当前时钟和授权未过期校验,重试不延期。
|
|
348
|
+
|
|
349
|
+
## 10. 可选托管与旧接口迁移
|
|
350
|
+
|
|
351
|
+
托管是应用显式启用的独立能力,不是绑定、释放或转移的前提。即使应用保存身份密文,两份关系文件仍由相应身份自己签署、上传。原 owner 曾能解密 sub 私钥时,关系转移不会自动撤销它掌握的凭据、续签或恢复能力;应用需独立确认凭据隔离,并将该交接进度与 NS 关系结果分开。
|
|
352
|
+
|
|
353
|
+
| 旧入口/判断 | 当前接入方式 |
|
|
354
|
+
| --- | --- |
|
|
355
|
+
| `bindOwner(...)`/`bind_owner(...)` | sub 使用 `bindOwneraid(ownerAid)`,owner 处理本端审批。 |
|
|
356
|
+
| `bindAid(...)`/`bind_aid(...)` | owner 使用 `bindSubaid(subAid)`,sub 明确审批。 |
|
|
357
|
+
| `releaseOwnership(...)`/`release_ownership(...)` | 当前 owner 使用 `releaseSubaid(subAid)`。 |
|
|
358
|
+
| 旧 `ownership_proof`、`proof.complete`、metadata owner | 改用当前双文件和新鲜 `checkOwnershipConsensus`;旧材料不是 2.1 共识证据。 |
|
|
359
|
+
| 旧代签、代上传、默认托管或自动 rekey 流程 | 按独立身份、明确审批及应用自己的可选凭据交接接入。 |
|
|
360
|
+
|
|
361
|
+
当前这些 legacy 发起方法会抛出 `unsupported_protocol`,不是新接口的兼容别名。更换调用名称也不等于存量旧关系已经迁入 2.1;旧关系缺少可验证的当前关系事实或材料时保持原保护,迁入条件与双方重新签署需按明确方案处理,不能清空旧关系强行初始化。兼容边界见 [设计第 9 节](Ownership2.1详细设计.md#9-降级旧版及审计)。
|
|
362
|
+
|
|
363
|
+
当前实现的实际验证与限制简要查阅 [TDD 账本第 13.4 节](Ownership2.1-TDD分阶段实施计划.md#134-测试与失败续跑账本)、[第 13.6 节四 SDK 一致性检查点](Ownership2.1-TDD分阶段实施计划.md#136-四-sdk-一致性检查点) 和 [第 13.7 节复审修复验收](Ownership2.1-TDD分阶段实施计划.md#137-2026-10-11-本轮复审修复验收)。本指南的短示例按当前 TypeScript 源码核对;本地类型成立不能替代服务部署、跨端通信或真实恢复验收。
|