@agentunion/fastaun 0.5.23 → 0.5.25

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 (54) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/_packed_docs/CHANGELOG.md +62 -0
  3. package/_packed_docs/INDEX.md +27 -15
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +22 -19
  5. package/_packed_docs/TS/346/263/250/345/206/214/350/207/252/345/212/250/347/273/221/345/256/232Owner/347/232/204E2E/351/252/214/350/257/201/344/273/243/347/240/201.md +196 -0
  6. package/_packed_docs/protocol/Ownership/345/215/217/350/256/256/345/256/232/344/271/2112.1.md +2 -2
  7. package/_packed_docs/sdk/0.5.24-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +401 -0
  8. package/_packed_docs/sdk/0.5.24-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +354 -0
  9. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +17 -7
  10. package/_packed_docs/sdk/INDEX.md +30 -6
  11. package/_packed_docs/sdk/Ownership-SDK/347/274/226/346/216/222/346/214/207/345/215/2272.1.md +49 -2
  12. 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 +123 -72
  13. 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 +173 -96
  14. package/dist/agent-md.d.ts +2 -1
  15. package/dist/agent-md.js +52 -22
  16. package/dist/agent-md.js.map +1 -1
  17. package/dist/aid-store.d.ts +1 -0
  18. package/dist/aid-store.js +34 -12
  19. package/dist/aid-store.js.map +1 -1
  20. package/dist/auth.d.ts +1 -0
  21. package/dist/auth.js +44 -10
  22. package/dist/auth.js.map +1 -1
  23. package/dist/client/delivery.d.ts +3 -0
  24. package/dist/client/delivery.js +197 -47
  25. package/dist/client/delivery.js.map +1 -1
  26. package/dist/client/rpc-pipeline.js +10 -0
  27. package/dist/client/rpc-pipeline.js.map +1 -1
  28. package/dist/client/v2-e2ee.js +17 -5
  29. package/dist/client/v2-e2ee.js.map +1 -1
  30. package/dist/client.d.ts +10 -10
  31. package/dist/client.js +158 -119
  32. package/dist/client.js.map +1 -1
  33. package/dist/group-fs.js +5 -0
  34. package/dist/group-fs.js.map +1 -1
  35. package/dist/index.d.ts +1 -1
  36. package/dist/keystore/aid-db.d.ts +1 -8
  37. package/dist/keystore/aid-db.js +46 -204
  38. package/dist/keystore/aid-db.js.map +1 -1
  39. package/dist/keystore/index.d.ts +0 -15
  40. package/dist/keystore/local-token-store.d.ts +1 -6
  41. package/dist/keystore/local-token-store.js +0 -15
  42. package/dist/keystore/local-token-store.js.map +1 -1
  43. package/dist/ownership-v21.d.ts +4 -2
  44. package/dist/ownership-v21.js +86 -42
  45. package/dist/ownership-v21.js.map +1 -1
  46. package/dist/ownership-workflow.d.ts +30 -59
  47. package/dist/ownership-workflow.js +260 -1667
  48. package/dist/ownership-workflow.js.map +1 -1
  49. package/dist/tools/cross-sdk-agent.d.ts +1 -2
  50. package/dist/tools/cross-sdk-agent.js +7 -14
  51. package/dist/tools/cross-sdk-agent.js.map +1 -1
  52. package/dist/version.d.ts +1 -1
  53. package/dist/version.js +1 -1
  54. package/package.json +1 -1
@@ -130,11 +130,11 @@ Ownership Facade 仅提供以下接口。应用调用编排接口发起操作,
130
130
 
131
131
  编排器和 P2P 消息处理器调用同一组内部文件方法:绑定复用 `declareSubaid`、`declareOwneraid`;解绑复用 `revokeSubaid`、`revokeOwneraid`;转移由原 owner 复用 `transferOwneraid`,目标声明和提交复用两个 declare 方法。消息处理器继续原任务,不再次调用 Facade 发起接口创建任务。`checkOwnershipConsensus` 对应用公开,其校验实现也供编排层复用。
132
132
 
133
- 绑定、释放、转移的发起接口先查询权威现状以固定起始版本,在发送消息、发布文件或删除等副作用前持久保存本端任务,返回 `operation_id` 和本端进度;超时可返回等待结果,由事件继续通知。审批接口关联已有任务,不创建新任务。`operation_id` 为 SDK 生成的 UUIDv4,不写入 agent.md、owner.md 或额外 NS 关系事实。同一 sub_aid 的本端修改串行推进;恢复复用原任务及已签署文件。
133
+ 绑定、释放、转移的发起接口先查询权威现状以固定起始版本,在发送消息、发布文件或删除等副作用前持久保存本端任务及 NS 一次性决策,返回 `operation_id` 和本端进度;超时可返回等待结果,由事件继续通知。审批接口关联已有任务,不创建新任务。`operation_id` 为 SDK 生成的 UUIDv4,不写入 agent.md、owner.md;NS 单独保存第 11 节定义的操作上下文和不可变决定,该记录不作为关系事实。同一 sub_aid 的本端修改串行推进;恢复复用原任务及已签署文件。
134
134
 
135
135
  绑定可由 sub 或 owner 发起,只有 fresh 可靠确认当前无 owner 锁才可进入绑定;`invalid`、`unavailable` 或无法确认当前基线均不能当作无锁。已有锁时只能由当前 owner 发起解绑或转移。发起 API 表达发起方意愿,接收方通过 `ownership.request` 同意或拒绝。转移仅由 NS 当前原 owner 发起;新 owner 和 sub 分别审批,原 owner 收齐两方同意后才发布转移授权。两方审批可任意先后;任一方拒绝,原 owner 通知另一方停止本次待审批任务,不发布授权,原关系保持。
136
136
 
137
- 三方意向共识只保存在各端 SDK 任务中,不写入协议文件或额外 NS 关系事实。sub 的同意还须落实为其自行签署、提交目标 agent.md;同意消息本身不能完成转移。
137
+ 参与方决定由 sub 归属 NS 持久化裁决,各端 SDK 保留本地执行检查点,不同步整份任务;决定不写入关系协议文件,也不作为额外 NS 关系事实。sub 的同意还须落实为其自行签署、提交目标 agent.md;同意消息或决策记录本身不能完成转移。
138
138
 
139
139
  审批决定限定 `operation_id`、操作、参与 AID 及起始/目标关系版本,在发送回复或发布文件前持久保存;不能用一个任务的同意批准另一目标。审批 API 仅用于待审批任务,批准后的停止按第 2.6 节处理。
140
140
 
@@ -937,3 +937,50 @@ version: 1.0.0
937
937
  恢复、降级与审计沿用第 8、9 节;分别核对 NS 和自身 Storage 的两份文件,不能退为单文件验收。
938
938
 
939
939
  self-owner 共识仅证明本方自主管理声明;外部 owner 的身份及业务信任检查按第 9.1 节,审计同样保存两个完整文件。
940
+
941
+ ## 11. AID 级多设备一次性决策
942
+
943
+ ### 11.1 权威与不可变约束
944
+
945
+ 同一操作统一访问 `sub_aid` 归属的 NS。owner、新 owner 及其不同设备不分别在各自域建立副本裁决。NS 通过已有 Bearer 验证取得真实 AID;跨域使用该 AID 归属域的认证验证,不信任 JSON 自报的设备身份。
946
+
947
+ NS 保存两类小记录:
948
+
949
+ | 记录 | 唯一键 | 保存内容 |
950
+ | --- | --- | --- |
951
+ | operation 上下文 | `operation_id` | 操作、sub、原/目标 owner、发起方、起始/目标版本。 |
952
+ | AID 决定 | `operation_id, deciding_aid` | 稳定 `decision_id`、`accept/reject`、拒绝原因、NS 提交时间。 |
953
+
954
+ 发起方以认证身份登记自己的 `accept` 并创建 operation,之后才能发布文件或发送请求。其它参与方只能对已登记且完整上下文匹配的 operation 决策。角色重合时,同一 AID 只占一个决策槽。不同 AID 的决定相互独立;例如 transfer 的 sub 和新 owner 各有一次决定机会。
955
+
956
+ 决定首次提交成功后永不修改。相同 `decision_id`、相同决定和原因的重试返回原记录;其它提交返回 `operation_already_processed` 及原决定。同一 ID 更换载荷也不能改决定。operation 上下文不同返回 `conflict`,不能将旧 ID 用于另一目标或版本。
957
+
958
+ ### 11.2 HTTP 接口与事务
959
+
960
+ 接口为 sub 权威 NS 的 `/api/nameservice/ownership/decisions`,GET、POST 均要求认证且响应 `Cache-Control: no-store`,携带 Bearer 的请求不跟随重定向。
961
+
962
+ POST 请求包含 `context`、`deciding_aid`、`decision_id`、`decision` 和可选 `reason`。`context` 固定为 `operation_id`、`operation`、`sub_aid`、`owner_aid`、`initiator_aid`、`base_relation_version`、`target_relation_version`;transfer 另含 `new_owner_aid`。各方本地基线可能因 Stage 而不同,因此不以本地任务的基线摘要生成跨设备上下文。原件、完整 statement、签名字节及 CAS 校验仍按原文件协议执行。
963
+
964
+ 首次写入返回 HTTP 201,完全相同的重试返回 HTTP 200,内容为 `decision` 原记录及 `idempotent`。原记录固定为 `{context, deciding_aid, decision_id, decision, reason, decided_at}`,`context` 保持嵌套,`reason` 缺省为空字符串,`decided_at` 为 NS 的整数毫秒时间。已有其它决定返回 HTTP 409,错误为 `operation_already_processed`,同时返回原记录。GET 使用 `operation_id`、`deciding_aid` 查询参数认证当前参与 AID,返回固定 `context` 及该 operation 的决定列表;非参与方不得查询。仅 404 且 JSON 错误为 `operation_not_found` 表示不存在,认证失败、路由错误或依赖不可用均不得视为未决定。
965
+
966
+ 数据库事务锁定 operation 行并核对固定上下文,再检查该 AID 的决定。已有决定优先按幂等规则返回,不因关系文件随后变化而重新决定。首次决定在同一事务中锁定、核对校验时读取的 sub 文档和 pending 快照,再插入唯一决定;快照竞争返回冲突。只有提交成功才能返回成功响应,数据库故障或提交结果未知均不能本地放行。唯一约束和事务负责跨进程、跨 NS 实例互斥,进程内锁不承担此保证。
967
+
968
+ ### 11.3 SDK 提交与故障恢复
969
+
970
+ 审批前先持久保存稳定的 `decision_intent`,包含请求 ID、原决定和原因;然后执行原有身份、请求上下文及 fresh 文件校验,向 NS 提交。收到成功记录后先保存 receipt,才改变本端审批状态、排队回复、签字或发布文件。
971
+
972
+ 若提交响应丢失,恢复先查询 NS。原 intent 已提交时恢复原决定;尚未提交时重新校验并以同一 ID 重试,不能另选相反决定。本机已有持久化、校验匹配的不可变 receipt 时直接复用,不随每次推进重复查询;待审批副本和新收到的对端决定仍查询权威记录。NS 不可用时保留任务和 intent,不发送审批、不发布文件,也不以本地缓存推断未处理。
973
+
974
+ P2P 审批消息和同 AID 其它设备的 self-sync 副本仅触发权威查询。远端审批必须与 NS 中对应 AID 的决定一致,不能以迟到消息覆盖已确定的相反决定。ready 消息、转移授权和双方文件验收仍沿原协议,不由 receipt 替代。
975
+
976
+ ### 11.4 待办回收与完成边界
977
+
978
+ 其它设备查到本 AID 已由另一 intent 决定时,结束本设备的待审批副本并移出 pending;后续点击返回 `operation_already_processed`。保留可阻止迟到消息复活的本地终态和 NS 最小决定,不补造本设备的签字、原件或发布成功证据。包含实际文件提交、outbox 或必要清理证据的执行任务不能作为普通审批副本删除。
979
+
980
+ 拒绝表示该 AID 的本次决定已结束;同意只表示批准,绑定仍可能执行中。只有当前 `agent.md + owner.md` 有效共识及原任务提交证据满足既有完成规则,才确认执行完成。决定后的执行失败保留原决定,不重新开放审批;新意图必须使用新 operation。
981
+
982
+ 回收由现有收件、self-sync 提示、重连恢复和显式审批操作触发,不新增周期轮询。离线设备的界面可以暂存旧待办,但上线后的查询及每次提交均由 NS 裁决,不能成功提交第二次决定。NS 决定不随本地 pending 回收、重置或历史任务清理删除。
983
+
984
+ ### 11.5 TDD 验收边界
985
+
986
+ 必须覆盖并发 accept/reject 只胜出一次、重复拒绝、同 ID 同载荷重试、同 ID 改载荷、跨 AID 上下文冲突、跨域认证错配、数据库失败和提交响应丢失;四 SDK 还须覆盖稳定 intent 落盘、另一设备决定后的 pending 收敛、迟到 self-sync、未登记请求拒绝及恢复不重决策。原租约、revision CAS、签名字节和条件写入回归继续保留。
@@ -1,6 +1,6 @@
1
1
  # Ownership 2.1 SDK 应用集成指南
2
2
 
3
- 面向应用开发者,按“准备身份 → 发起 → 审批 → 核验 → 恢复”接入。示例使用 Node.js TypeScript SDK `@agentunion/fastaun` 当前工作区 `0.5.22`(未发布,升级基线 `0.5.21`),Node.js ≥22.16.0;实际依赖须具有本文接口。
3
+ 面向应用开发者,按“准备身份 → 提交文件 → 通知/同意 → NS 验收”接入。示例使用 Node.js TypeScript SDK `@agentunion/fastaun` 当前工作区 `0.5.24`,Node.js ≥22.16.0;实际依赖须包含本文接口。
4
4
 
5
5
  协议见 [Ownership 2.1](../protocol/Ownership协议定义2.1.md),SDK 内部实现见 [开发与移植指南](Ownership2.1-SDK开发与移植指南.md)。
6
6
 
@@ -10,17 +10,19 @@
10
10
  | --- | --- |
11
11
  | sub | 被管理身份;自己签署并以本人身份向 NS 提交 `agent.md`。 |
12
12
  | owner/新 owner | 自己签署并向本人 Storage 发布 `sub_aids/{sub_aid}/owner.md`。 |
13
- | NS | 根据这两份当前权威文件核验关系;Storage 中的 sub 名片副本不参与验收。 |
13
+ | NS | 根据这两份当前权威文件验收并锁定关系;Storage 中的 sub 名片副本不参与验收。 |
14
14
 
15
15
  owner 权限不包含 sub 私钥或代签、代上传能力。普通名片更新保留全部关系字段及原 CAS;关系无效或暂不可确认只影响依赖 owner 的授权,不阻断普通名片和通信。
16
16
 
17
- 本流程用于普通主体;human 可作为 owner,不能作为声明 owner 的 sub。Group/Org 自身使用专属创建、解散和强制 rekey 转让流程:任务方法抛出 `not_applicable`,共识方法返回同名状态。它们仍可按普通 owner 规则管理其他 sub。
17
+ 本流程用于普通主体;human 可作为 owner,不能作为声明 owner 的 sub。Group/Org 自身使用专属创建、解散和强制 rekey 转让流程:关系操作抛出 `not_applicable`,共识方法返回同名状态。它们仍可按普通 owner 规则管理其他 sub。
18
+
19
+ SDK 不维护 Ownership 任务状态机、WAL 或后台恢复,不提交独立 decisions 回执。NS 以归属事实判断冲突;锁定后,新的 accept/reject 不能改变关系,须走释放或转移。
18
20
 
19
21
  ## 2. 接入前提与能力检查
20
22
 
21
23
  - 各端具有自己的私钥、有效证书和客户端;`load()` 成功后仍检查私钥。
22
- - sub 的初始 `agent.md` 已在 NS 可读;部署具备 NS 2.1、权威 Storage、P2P 和持久任务能力。共识查询成功不代表所有发布能力可用。
23
- - 固定可写的 `aunPath`、解密 seed、设备和 slot;任务保存在 `{aunPath}/AIDs/{aid}/aun.db`,重启沿用原数据。
24
+ - sub 的初始 `agent.md` 已在 NS 可读;部署具备本轮 NS 2.1 验收、Stage、权威 Storage 能力。交互流程另需 P2P;本地编排不发 P2P。
25
+ - 保管好各身份的 `aunPath`、解密 seed 和私钥;普通长连接使用各自的设备和 slot。本地编排由 SDK 另建专属 slot 的短连接。
24
26
  - 启用 TLS 校验并配置可信根;`rootCaPath` 用于 AUN 证书验证,Node.js HTTPS 信任仍须单独正确配置。外部地址使用 `ns.{issuer}`、`st.{issuer}`。
25
27
 
26
28
  ## 3. EC CLI 集成示例:sub 发起,human owner 同意
@@ -48,19 +50,18 @@ if (!loaded.data.aid.isPrivateKeyValid()) throw new Error('本身份私钥不可
48
50
  const client = new AUNClient(loaded.data.aid);
49
51
  ```
50
52
 
51
- 两端先订阅再连接。下文 `saveMessage`、`updateView`、`saveTask` 为应用自己的消息持久处理、界面更新和业务任务保存函数。
53
+ 两端先订阅再连接。下文 `saveMessage`、`updateView` 为应用自己的消息持久处理和界面更新函数,不要求应用保存 Ownership 任务。
52
54
 
53
55
  ```ts
54
56
  function watch(client: AUNClient): void {
55
57
  client.on('message.received', payload => saveMessage(payload));
56
- for (const event of ['ownership.action_required', 'ownership.progress',
57
- 'ownership.completed', 'ownership.rejected', 'ownership.stopped', 'ownership.error']) {
58
+ for (const event of ['ownership.completed', 'ownership.rejected']) {
58
59
  client.on(event, payload => updateView(event, payload));
59
60
  }
60
61
  }
61
62
  ```
62
63
 
63
- `0.5.22` 至少需要 `message.received/message.recalled/message.batch` 中一种普通消息订阅才启动后台 P2P 拉取;已有订阅直接复用。消息处理须完成持久交付后返回,不能用空回调 ACK。仅订阅 `ownership.*` 不够;控制消息由 SDK 内部消费,仍遵守队列背压。
64
+ 当前 TS 实现至少需要 `message.received/message.recalled/message.batch` 中一种普通消息订阅才启动后台 P2P 拉取;已有订阅直接复用。消息处理须完成持久交付后返回,不能用空回调 ACK。仅订阅 `ownership.*` 不够;控制消息由 SDK 内部消费,仍遵守队列背压。
64
65
 
65
66
  ### 3.3 owner App 先订阅审批,再连接
66
67
 
@@ -70,10 +71,10 @@ function watch(client: AUNClient): void {
70
71
  ownerClient.on('ownership.request', payload => {
71
72
  const request = readApproval(payload);
72
73
  showApproval(request, async accept => {
73
- const task = accept
74
+ const result = accept
74
75
  ? await ownerClient.acceptOwnershipRequest(request.operation_id)
75
76
  : await ownerClient.rejectOwnershipRequest(request.operation_id, '用户拒绝');
76
- await saveTask(task);
77
+ updateView('ownership.result', result);
77
78
  });
78
79
  });
79
80
  ```
@@ -83,15 +84,15 @@ watch(ownerClient);
83
84
  await ownerClient.connect({ auto_reconnect: true });
84
85
  ```
85
86
 
86
- 收件回调不等待用户决定;按 `operation_id` 幂等展示,不因重连重复审批或改变已保存的决定。
87
+ 收件回调不等待用户决定;按 `operation_id` 去重展示。SDK 使用经过认证的原始请求执行 accept/reject,应用不要自行拼造请求;失败按 §8 查询 NS 后重新发起。
87
88
 
88
89
  ### 3.4 EC/Evolcore 的 sub 发起绑定
89
90
 
90
91
  ```ts
91
92
  watch(subClient);
92
93
  await subClient.connect({ auto_reconnect: true });
93
- const task = await subClient.bindOwneraid('owner.agentid.pub');
94
- await saveTask(task);
94
+ const result = await subClient.bindOwneraid('owner.agentid.pub');
95
+ updateView('ownership.result', result);
95
96
  ```
96
97
 
97
98
  ```mermaid
@@ -101,16 +102,16 @@ sequenceDiagram
101
102
  participant O as human owner App
102
103
  participant T as owner Storage
103
104
  S->>N: fresh 确认无锁及 Stage 能力
104
- S->>S: 保存同意、签名原件和原 CAS
105
+ S->>S: 本次签署 agent.md,保留文件 CAS
105
106
  S->>N: Stage 条件提交 agent.md
106
107
  N-->>S: pending / v+1 / unlocked
107
108
  S->>O: 加密 bind.request
108
- O->>O: 核验并保存请求,用户点击同意
109
+ O->>O: 核验原始请求,用户点击同意
109
110
  O->>T: 本人发布匹配的 owner.md
110
111
  O->>N: fresh 检查双文件
111
112
  N-->>O: consensus / locked
112
- O-->>S: 提示结果;sub 可离线后恢复
113
- S->>N: fresh 核验目标及本人原件后完成
113
+ O-->>S: 发送结果通知;sub 无需在线或再次 PUT
114
+ S->>N: 应用查询当前共识并更新界面
114
115
  ```
115
116
 
116
117
  sub 发起即表达本端同意,不再调用审批方法。Stage 只保存待确认名片,此时公共共识为 `single_sided`;owner 同意并发布后,NS 可直接验收已有候选,sub 无需再次 PUT。
@@ -124,7 +125,7 @@ const registered = await store.register('helper.agentid.pub', {
124
125
  if (!registered.ok) throw new Error(registered.error.message);
125
126
  ```
126
127
 
127
- 这是显式 `bindOwneraid` 的替代入口。注册先初始化无关系名片并保存固定 ID 的意图,连接后 SDK 续跑绑定,owner 仍须审批;不要再发起另一绑定。省略 owner 只注册普通 agent;`registered: true` 不表示关系成立。
128
+ 这是显式 `bindOwneraid` 的替代入口。注册先初始化无关系名片,再于本次调用内用专属短连接提交绑定并通知 owner,最后关闭连接;owner 仍须审批。省略 owner 只注册普通 agent;`registered: true` 不表示关系成立。失败后先检查已注册身份与 NS 状态,需要时显式调用 `bindOwneraid`,不等待连接后自动续跑。
128
129
 
129
130
  ### 3.6 通用签验与多签名片
130
131
 
@@ -137,7 +138,7 @@ if (!verified.ok || !verified.data.valid) throw new Error('验签失败');
137
138
 
138
139
  默认 `raw` 为 detached 签名;文件输入须显式 `inputType: 'file'`,附签用 `append: true`。验签检查全部已有签块,数学验签不等于当前证书或 owner 授权。签名不发布文件;完整参数见 [API 手册](06-API手册.md#通用-sign--verify)。
139
140
 
140
- ## 4. 七个 Facade 的参数、角色与结果
141
+ ## 4. Facade 的参数、角色与结果
141
142
 
142
143
  | 方法 | 本端角色/结果 |
143
144
  | --- | --- |
@@ -145,25 +146,25 @@ if (!verified.ok || !verified.data.valid) throw new Error('验签失败');
145
146
  | `bindSubaid(subAid)` | owner 发起绑定,sub 审批。 |
146
147
  | `releaseSubaid(subAid)` | 当前 owner 释放,不要求 sub 在线。 |
147
148
  | `transferSubaid(subAid, newOwnerAid)` | 当前 owner 发起,sub 和新 owner 审批。 |
149
+ | `bindLocalSubaid(subClient)` | 本地 owner 与 sub 双身份自动绑定,见 §6.5。 |
150
+ | `transferLocalSubaid(subClient, newOwnerClient)` | 本地旧 owner、sub、新 owner 三身份自动转移,见 §6.6。 |
148
151
  | `acceptOwnershipRequest(operationId)` | 同意本端已验证的 bind/transfer 请求。 |
149
152
  | `rejectOwnershipRequest(operationId, reason?)` | 拒绝同一请求。 |
150
153
  | `checkOwnershipConsensus(subAid?)` | 只读当前共识;省略参数检查本端 AID。 |
151
154
 
152
- 前六项返回 `Promise<OwnershipTaskResult>`,包含 `operation_id`、参与方、base/target 版本及 `status/step`;status 为 `pending/completed/rejected/stopped/error`。共识查询返回独立的 `OwnershipConsensusResult`。
155
+ 除共识查询外,方法返回 `Promise<OwnershipTaskResult>`;这是保留的类型名,表示本次调用结果,包含 `operation_id`、参与方、base/target 版本及 `status/step`。共识查询返回独立的 `OwnershipConsensusResult`。
153
156
 
154
- 保存业务记录与 `operation_id` 的对应关系。Promise 返回、ACK、审批通过都不是完成;`completed` 表示本端已核验本次目标,后续清理错误不撤销该结果。没有公开按 ID 查询任务、取消或强制解锁接口。
157
+ 当前 TS 普通交互方法返回 `completed/step=local_actions`,只表示当次文件与通知动作执行完成;例如 sub 发出请求后仍可能是 `single_sided`。本地编排会额外确认目标共识。应用统一以 §7 的 NS 共识判断当前归属,不以返回值、ACK 或通知代替验收。SDK 没有待办任务查询、取消或强制解锁接口。
155
158
 
156
159
  ## 5. 审批与本地事件接入 UI
157
160
 
158
161
  | 本地事件 | 处理 |
159
162
  | --- | --- |
160
163
  | `ownership.request` | 展示已验证请求,等待用户或明确策略决定。 |
161
- | `ownership.action_required` | sub 清理旧关系字段需要明确授权。 |
162
- | `ownership.progress` | 更新阶段。 |
163
- | `ownership.completed` | 保存本任务完成记录;当前关系另查共识。 |
164
- | `ownership.rejected/stopped/error` | 展示拒绝、停止或错误;完成后的清理错误单独显示。 |
164
+ | `ownership.completed` | 本次执行观察到共识,可刷新界面;当前关系另查共识。 |
165
+ | `ownership.rejected` | 展示对端拒绝通知;不代表 NS 回滚或解除关系。 |
165
166
 
166
- 载荷直接传入回调,没有 `event.data` 包装;包含任务字段及 `local_roles`,request 另含可信 `requester_aid`。按任务 ID、事件、step 幂等更新;`relation_version` 是本任务实际验收版本,不能替代当前查询。事件字段见 [编排指南 §2.6](Ownership-SDK编排指南2.1.md#26-本地事件与完成依据)。
167
+ 以上为当前 TS 工作流实际发出的事件,不依赖旧 `progress/action_required/stopped/error` 事件。载荷直接传入回调,没有 `event.data` 包装;request 含操作、参与方、base/target 版本和可信 `requester_aid`,不要依赖旧 `local_roles`。`operation_id` 只关联通知与界面,不是 NS 的归属锁或决定记录。调用错误仍须处理返回的 `status/code/reason` 和异常。
167
168
 
168
169
  ## 6. 关系操作流程
169
170
 
@@ -172,8 +173,8 @@ if (!verified.ok || !verified.data.valid) throw new Error('验签失败');
172
173
  sub-first 见 §3.4;owner-first 如下:
173
174
 
174
175
  ```ts
175
- const task = await ownerClient.bindSubaid('helper.agentid.pub');
176
- await saveTask(task);
176
+ const result = await ownerClient.bindSubaid('helper.agentid.pub');
177
+ updateView('ownership.result', result);
177
178
  ```
178
179
 
179
180
  ```mermaid
@@ -185,22 +186,24 @@ sequenceDiagram
185
186
  O->>N: fresh 确认无锁
186
187
  O->>T: 按原条件发布 owner.md
187
188
  O->>S: bind.request
188
- S->>S: 验证并固定提案全文/SHA,用户明确同意
189
+ S->>S: 验证当前提案,用户明确同意
189
190
  S->>N: 直接条件提交 agent.md,不使用 Stage
190
191
  N->>T: 核对当前声明
191
192
  N-->>S: consensus / locked
192
- S-->>O: 提示结果;owner 自行 fresh 核验完成
193
+ S-->>O: 提示结果;owner 查询当前共识
193
194
  ```
194
195
 
195
- 绑定目标版本为当前可见声明 `v+1`,无声明时从 `1` 开始。只有可靠无锁状态可发起;`invalid/unavailable` 不能当作无锁。owner-first 正常成功无需 `bind.accept/owner.ready` 往返。
196
+ 初次绑定版本从 `1` 开始;替换未锁定的候选时沿用候选版本,不因重新通知而递增。只有可靠无锁状态可发起;`invalid/unavailable` 不能当作无锁。NS 验收不以 `bind.accept` 通知到达或发起端再次在线为前提。
197
+
198
+ 拒绝仅发送通知,不删除或回滚已上传文件。未锁定前,sub 可用 CAS 替换 owner 声明,以最后成功上传的 `agent.md` 为准:先声明 B 后声明 C,B 同意不能形成共识;C 同意才可验收,C 拒绝则保留单边声明。NS 锁定后,同目标 accept 可返回已完成,reject 或不同目标不能改变归属;不再维护跨设备“唯一决定”记录。
196
199
 
197
- 拒绝仅清理仍属于本任务、未锁定且原文/摘要/CAS 匹配的候选或邀请;不能删除已验收文件。释放后重绑同一 owner 前,先清除 sub 的旧声明,避免覆盖释放依据。
200
+ 释放后重绑同一 owner 前,先清除 sub 的旧声明,避免覆盖释放依据。
198
201
 
199
202
  ### 6.2 释放:原 owner 发起,sub 可以离线
200
203
 
201
204
  ```ts
202
- const task = await ownerClient.releaseSubaid('helper.agentid.pub');
203
- await saveTask(task);
205
+ const result = await ownerClient.releaseSubaid('helper.agentid.pub');
206
+ updateView('ownership.result', result);
204
207
  ```
205
208
 
206
209
  ```mermaid
@@ -208,23 +211,21 @@ flowchart LR
208
211
  A[原 owner 发起] --> B[发布同版本 v 的 release]
209
212
  B --> C[NS fresh 确认 released / v]
210
213
  C --> D[owner 完成;sub 可离线]
211
- D --> E[sub 回源确认释放]
212
- E --> F{有匹配的本人历史同意吗}
213
- F -->|有| G[本人条件清理 agent.md]
214
- F -->|没有| H[action_required:应用明确决定清理]
215
- H --> G
216
- G --> I[unbound / 0]
214
+ D --> E[sub 收到合法释放通知]
215
+ E --> F[当次回源验证并条件清理 agent.md]
216
+ F --> G[unbound / 0]
217
+ D --> H[通知未处理则仍为 released,不等待后台任务]
217
218
  ```
218
219
 
219
- 释放不递增版本。权威确认 owner 文件不存在也可证明释放,网络错误或普通 404 不可。自动清理须匹配本人已同意的原 bind/transfer 完整声明;否则应用明确决定后,用本人 `store.uploadAgentMd(subAid, content)` 清除旧关系字段。release 不接受 accept/reject 审批。
220
+ 释放不递增版本。权威确认 owner 文件不存在也可证明释放,网络错误或普通 404 不可。sub 收到合法 release 通知时,当次回源核验并用本人身份条件清理声明,不依赖历史审批任务。若通知未处理,先按 `released` 展示;当前没有公开的强制清理 Facade,不能用普通 `uploadAgentMd` 删除关系字段。release 不接受 accept/reject 审批。
220
221
 
221
- 字段已空不能单独认领某任务完成;SDK 仍核对本任务原件和提交证据。关系释放、sub 字段清理、旧 owner 文件清理分别展示。
222
+ NS 已确认 `released/unlocked` 即关系释放;sub 字段未清不恢复旧 owner 权限,清理后为 `unbound/0`。关系释放和文件清理分开展示。
222
223
 
223
224
  ### 6.3 三方转移
224
225
 
225
226
  ```ts
226
- const task = await ownerClient.transferSubaid('helper.agentid.pub', 'next.agentid.pub');
227
- await saveTask(task);
227
+ const result = await ownerClient.transferSubaid('helper.agentid.pub', 'next.agentid.pub');
228
+ updateView('ownership.result', result);
228
229
  ```
229
230
 
230
231
  ```mermaid
@@ -233,25 +234,74 @@ sequenceDiagram
233
234
  participant S as sub
234
235
  participant N as 新 owner
235
236
  participant NS as sub NS
237
+ O->>O: 发布指定目标、v+1 和固定期限的转移授权
236
238
  O->>S: transfer.request
237
239
  O->>N: transfer.request
238
- S-->>O: 明确同意
239
- N-->>O: 明确同意
240
- O->>O: 发布指定目标、v+1 和固定期限的转移授权
241
- N->>N: 验证授权,发布 v+1 owner.md
242
- S->>NS: 本人条件提交目标 agent.md
243
- NS-->>S: 核验三方材料,直接从 v 切到 v+1
244
- S-->>O: 提示结果,各端自行 fresh 核验
245
- S-->>N: 提示结果,各端自行 fresh 核验
240
+ par sub 同意(无先后要求)
241
+ S->>NS: 验证授权,Stage 提交目标 agent.md
242
+ NS-->>S: 材料未齐时保留旧 active / locked / v
243
+ and 新 owner 同意
244
+ N->>N: 验证授权,发布 v+1 owner.md
245
+ end
246
+ S->>NS: 验收当前材料;任一参与方可触发检查
247
+ NS-->>S: 三方材料一致,原子切到新 owner / v+1
248
+ S-->>O: 提示结果,各端查询当前共识
246
249
  ```
247
250
 
248
- 审批未齐不发布授权;任一待审批方拒绝则停止未提交流程。授权过期不自动解除旧关系,恢复不延期、不换目标,也不改成“先释放再绑定”。
251
+ 旧 owner 先发布授权再通知。sub 与新 owner 各自上传本人文件,不要求同时在线,也没有同意时序要求。拒绝只反馈,不撤销已发布材料;授权过期或撤回不解除旧活动关系。材料未齐时 NS 保留旧 owner 锁,达成一致后原子切换,不经过“先释放再绑定”。
249
252
 
250
253
  ### 6.4 自拥有与角色重合
251
254
 
252
- 同一 AID 的多个角色合并为一次决定,不给自己发 P2P;双文件签署和 NS 核验仍执行。`sub.bindOwneraid(subAid)` 建立 self-owner;外部 owner 转给 sub 时,sub 同时审批 `sub/new_owner` 两个角色。human 禁止 self-owner,原 owner 与新 owner 相同不是有效转移。
255
+ 同一 AID 承担多个角色时,一次调用执行本人的全部文件动作,不给自己发 P2P;双文件签署和 NS 核验仍执行。`sub.bindOwneraid(subAid)` 建立 self-owner;外部 owner 转给 sub 时,sub 同时审批 `sub/new_owner` 两个角色。human 禁止 self-owner,原 owner 与新 owner 相同不是有效转移。
256
+
257
+ ### 6.5 本地双身份自动绑定
258
+
259
+ Evolcore/EC CLI 同时掌握 daemon 与新 sub 的身份材料时,由 daemon 调用 `bindLocalSubaid(subClient)` 自动完成绑定,无需 P2P 或人工确认。传入两个 client 用于提供身份,不要求应用另行 connect;SDK 创建 `ownership-UUID` 专属 slot 的短连接,完成认证、发布与验收后在 `finally` 关闭,避免占用普通长连接 slot。
260
+
261
+ ```ts
262
+ const bound = await daemonClient.bindLocalSubaid(subClient);
263
+ if (bound.status !== 'completed') throw new Error(bound.reason);
264
+ showBound({
265
+ sub_aid: bound.sub_aid, owner_aid: bound.owner_aid,
266
+ relation_version: bound.target_relation_version,
267
+ });
268
+ ```
269
+
270
+ ```mermaid
271
+ flowchart LR
272
+ A[daemon + sub 两个本地 client] --> B[SDK 创建两身份专属短连接]
273
+ B --> C[daemon 签署并发布 owner.md]
274
+ C --> D[sub 签署并条件提交 agent.md]
275
+ D --> E[NS 验收一致归属并锁定]
276
+ E --> F[返回结果,关闭短连接]
277
+ ```
278
+
279
+ ### 6.6 本地三身份自动转移
253
280
 
254
- ## 7. 任务完成与当前共识六态
281
+ 当前 owner、本地 sub 和目标 owner 的身份材料都可用时,由当前 owner 调用 `transferLocalSubaid(subClient, newOwnerClient)`。SDK 为三个身份创建专属短连接,先发布原 owner 授权和新 owner 声明,再由 sub 提交名片并确认 NS 共识;不发 P2P,不经过先释放再绑定。
282
+
283
+ ```ts
284
+ const moved = await daemonClient.transferLocalSubaid(subClient, nextAgentClient);
285
+ if (moved.status !== 'completed') throw new Error(moved.reason);
286
+ showBound({
287
+ sub_aid: moved.sub_aid, owner_aid: moved.new_owner_aid,
288
+ relation_version: moved.target_relation_version,
289
+ });
290
+ ```
291
+
292
+ ```mermaid
293
+ flowchart LR
294
+ A[旧 owner + sub + 新 owner 三个本地 client] --> B[SDK 创建三身份专属短连接]
295
+ B --> C[旧 owner 发布指定目标的转移授权]
296
+ C --> D[新 owner 签署并发布 owner.md]
297
+ D --> E[sub 签署并条件提交新 agent.md]
298
+ E --> F[NS 验收并原子切换归属]
299
+ F --> G[核验目标,条件清理旧授权并关闭短连接]
300
+ ```
301
+
302
+ 两个本地方法仅支持不同的 `type: agent` 身份,每个 client 均须有有效私钥、证书及 NS 名片。human 作为 owner 仍走 §3/§6.3 的现有确认流程;本地方法不替人同意,也不自动沿 daemon 的 owner 关系推导授权。失败后按 §8 查询 NS 再重新发起,不等待后台恢复。
303
+
304
+ ## 7. 当前共识六态与完成判断
255
305
 
256
306
  ```ts
257
307
  const current = await ownerClient.checkOwnershipConsensus('helper.agentid.pub');
@@ -271,42 +321,43 @@ if (current.status === 'consensus' && current.owner_aid === 'owner.agentid.pub')
271
321
 
272
322
  Group/Org 的 `not_applicable` 不属于六态。先判断 status,不能把占位版本 0/unlocked 当成无锁证据。无目标上下文的查询也不能枚举独立 owner 邀请。
273
323
 
274
- 普通下载的 `verification.ownership_status` 是 legacy 展示字段;当前授权使用 fresh 共识。敏感操作由执行端核对调用者、sub、owner、权限范围及完整声明;清理后可再次出现版本 1,版本号不是全局关系标识。
324
+ 普通下载的 `verification.ownership_status` 是 legacy 展示字段。普通 peer 名片展示可按 ETag 复用 Ownership 快照,不必轮询重检;`owner.md` 可独立变化,实际管理操作仍由 SDK/服务端回源核验当前归属、权限和文件 CAS。清理后可再次出现版本 1,版本号不是全局关系标识。
275
325
 
276
- ## 8. 断线与重启恢复
326
+ ## 8. 故障后查询与重新发起
277
327
 
278
328
  ```mermaid
279
329
  flowchart LR
280
- A[恢复原身份、目录、设备和 slot] --> B[订阅后连接]
281
- B --> C[SDK 读取原任务、审批、签名字节和 CAS]
282
- C --> D{fresh 核对结果}
283
- D -->|完整目标与本任务证据匹配| E[确认原任务完成]
284
- D -->|尚未提交且原条件有效| F[只补未完成步骤]
285
- D -->|依赖暂不可用| G[保留 pending]
286
- D -->|原件或关系已变化| H[停止旧写入]
330
+ A[恢复本人身份,订阅后连接] --> B[查询 NS 当前共识]
331
+ B --> C{当前事实}
332
+ C -->|目标归属已锁定| D[按已完成更新界面]
333
+ C -->|仍无锁或只有单边声明| E[用户显式重新发起绑定]
334
+ C -->|仍锁定原 owner| F[需要时重新发起转移或释放]
335
+ C -->|已锁定其它 owner| G[停止旧请求,按当前归属处理]
336
+ C -->|unavailable / invalid| H[先排除依赖或材料问题]
287
337
  ```
288
338
 
289
- `connect()` 返回不表示恢复已完成。应用恢复自己的业务任务记录并幂等更新 UI;SDK 复用原 operation,不重新绑定或转移。合法历史 completed 保留,当前关系另查。
339
+ SDK 不保存未完成操作,不在 `connect()` 后扫描任务或补发通知。若上传成功但通知失败,已提交文件仍然有效;先查 NS,目标已锁定则视为完成,否则显式重新发起。新调用有新的 `operation_id`,NS 按当前归属事实和 CAS 验收,不靠旧消息 ID 锁定关系。
290
340
 
291
- `resetOwnershipTask()` 仅归档当前身份发起的未完成任务,不删除远端候选、不解绑或解锁;普通断线不用 reset。历史任务和三类 CAS 冲突见 [移植指南 §10](Ownership2.1-SDK开发与移植指南.md#10-持久任务审批与恢复)。
341
+ 审批时需要经过认证的原始请求。实现可从正常消息记录重取原请求;若已不可恢复,让发起方重新发起,不重建审批任务。不要调用旧 `resetOwnershipTask()` 来期望回滚或续跑;它不再是新流程的一步。
292
342
 
293
343
  ## 9. 错误处理与安全降级
294
344
 
295
345
  | 错误 | 处理 |
296
346
  | --- | --- |
297
- | `persistence_unavailable` | 恢复原存储,停止副作用,不删除数据库伪造新任务。 |
298
347
  | `unsupported_protocol` | 核对 SDK/服务能力,不回退 legacy 写入。 |
299
348
  | `owner_locked` | 由当前 owner 释放或转移。 |
300
349
  | `conflict` | fresh 核对已提交目标;真实变化则停止,不换 CAS 强写。 |
301
- | `forbidden/operation_not_found/invalid` | 检查角色、身份、任务关联或材料,不盲重试。 |
302
- | `unavailable` | 保留原任务和字节,依赖恢复后继续核验。 |
350
+ | `forbidden/operation_not_found/invalid` | 检查角色、身份、原始请求或材料;请求丢失时重新发起,不盲重试。 |
351
+ | `unavailable` | 恢复依赖后查询 NS;未完成时显式重新发起。 |
303
352
 
304
- 错误可能来自异常、任务/事件或共识结果。结果读取 `code/reason/retryable`;抛出的 `AUNError` 读取 `stringCode/retryable`,其 `code` 是数字 RPC 码。`retryable` 不授权换目标、重签或延期。
353
+ 错误可能来自异常、当次结果或共识结果。结果读取 `code/reason/retryable`;抛出的 `AUNError` 读取 `stringCode/retryable`,其 `code` 是数字 RPC 码。不要绕过 CAS 强写,或因网络错误认定远端未提交;重新发起仍须按当前 NS 事实验收。
305
354
 
306
355
  ## 10. 可选托管与旧接口迁移
307
356
 
308
357
  托管和凭据交接由应用独立决定;关系转移不会自动撤销旧 owner 已掌握的私钥、证书或 token。
309
358
 
310
- 旧 `bindOwner/bindAid/releaseOwnership` 在新 SDK 中返回 `unsupported_protocol`;分别改用 `bindOwneraid/bindSubaid/releaseSubaid`。旧 proof、metadata owner 和旧查询不能证明 2.1 共识。新服务端保留旧 SDK 隔离兼容,新 SDK 的 2.1 操作不兼容旧服务端;不能清空旧关系强行迁入。
359
+ 旧 `bindOwner/bindAid/releaseOwnership` 在新 SDK 中返回 `unsupported_protocol`;分别改用 `bindOwneraid/bindSubaid/releaseSubaid`。旧 proof、metadata owner 和旧查询不能证明 2.1 共识,不能清空旧关系强行迁入。
360
+
361
+ 完整的新语义应配套发布 NS 与四 SDK。已有 2.1 NS 的普通绑定、本地绑定及目标 owner 文件先提交的本地转移,正常路径仍可能可用;sub 先同意的转移、Stage 与 owner 文件交错及相同归属重新签发,需要本轮 NS 修复。新 SDK 不调用 decisions,旧服务保留该接口不影响它;过渡版 SDK 若强依赖已移除接口,则需升级。Rust SDK 未随本轮改造,不能套用本文“无任务、无 WAL”的实现结论。
311
362
 
312
363
  Group/Org 名片由实体主签、当前 owner token 上传;失败稿保留完整多签原文、固定 owner/证书代际及原 CAS,应用显式重试,重连不自动 PUT。格式见 [协议 §2.5](../protocol/Ownership协议定义2.1.md#25-grouporg-名片的实体主签与-owner-上传)。