@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,553 @@
|
|
|
1
|
+
# Ownership 2.1 SDK 开发与移植指南
|
|
2
|
+
|
|
3
|
+
本文面向实现 Rust 等新语言 SDK 或移植其它语言 SDK 的开发者,以当前工作区的 Node TypeScript SDK 为实现参考,说明内部职责、文件验证、条件提交、P2P 编排、持久化与验收。EC CLI 等应用接入方如何发起操作及处理审批,见 [SDK 应用集成指南](Ownership2.1-SDK应用集成指南.md);编排契约见 [SDK 编排指南 2.1](Ownership-SDK编排指南2.1.md),完整文件格式和服务端授权要求以 [Ownership 协议定义 2.1](../protocol/Ownership协议定义2.1.md) 为准。
|
|
4
|
+
|
|
5
|
+
普通 `agent.md` 的基础读取、验签、上传与显式 pending 恢复不以前置 Ownership 共识、owner Storage 或关系状态为条件。普通正文更新须原样保留当前原件中全部关系材料的字段存在性、类型和值,并遵守本人签名和原 ETag/CAS;材料无效或依赖不可用不能阻断这种更新。增删改关系字段继续执行当前双文件授权核验,不能借普通名片入口清除或替换 owner 锁。
|
|
6
|
+
|
|
7
|
+
设计依据还包括 [Ownership 2.1 详细设计](Ownership2.1详细设计.md) 与 [TDD 分阶段实施计划](Ownership2.1-TDD分阶段实施计划.md)。下文分别说明协议要求和 TypeScript 的实际接线;设计要求不能直接作为某个运行环境已经验收的证据。TypeScript 是接线与组织方式的参考,不是全部差异的默认裁决版本;各项以协议和冻结契约为准,逐项采用哪个 SDK 的正确行为见 [审查报告第十二节](../audit/Ownership2.1代码审查报告.md#十二2026-10-11-本轮复审与修复)和[审查报告第十三节](../audit/Ownership2.1代码审查报告.md#十三2026-10-13-审查更正与最小修复验收)。旧集成、实现指南中的 proof、自动 escrow 和 bindAid/bindOwner 流程属于 legacy;协议 3.0 不在本文范围。
|
|
8
|
+
|
|
9
|
+
参考包在 [ts/package.json](../../ts/package.json) 中标为 `@agentunion/fastaun`、`0.5.21`,运行要求为 Node `>=22.16.0`。这些是工作区标识,不表示本文描述的 2.1 实现已发布到该版本的软件包。
|
|
10
|
+
|
|
11
|
+
兼容方向为新服务端保留旧 SDK 的既有身份认证、普通名片、通信及 legacy owner 操作;新 SDK 的 2.1 关系操作不兼容旧服务端,不要求新 SDK 源码调用形态兼容。旧注册、绑定、转移、查询和解绑 RPC 以隔离的 Auth JSONL 和 NS `ownership_proof` 承载兼容状态,不生成 2.1 双文件,不构成 2.1 授权、owner 锁、版本或共识;不得覆盖已存现代声明,见 [协议开篇与 §3.2](../protocol/Ownership协议定义2.1.md#32-判定顺序与普通名片边界)。
|
|
12
|
+
|
|
13
|
+
## 1. 实现边界与角色
|
|
14
|
+
|
|
15
|
+
| 名称 | 在实现中的含义 |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `sub_aid` | 被管理身份,也是自己 `agent.md` 的签署者、认证上传者。 |
|
|
18
|
+
| `owner_aid` | 绑定时为目标 owner;释放、转移任务中为当前/原 owner。 |
|
|
19
|
+
| `new_owner_aid` | 仅用于转移,表示原 owner 授权的目标;必须不同于 `owner_aid`。 |
|
|
20
|
+
| NS | 以同一数据库事务和 CAS 持久化 sub 的权威 `agent.md` 与同步待办,根据该名片和 owner 的权威 `owner.md` 验证当前关系。 |
|
|
21
|
+
| Storage | 保存 owner 的权威 `owner.md`,以及 NS 验收后同步的 sub 名片副本。 |
|
|
22
|
+
| SDK 任务 | 某一个身份的本端工作记录;审批、文件、通知及清理可分别恢复。 |
|
|
23
|
+
|
|
24
|
+
通用关系各方只签署、上传自己的文件:sub 向 NS 上传 `agent.md`,owner 或新 owner 向自己的 Storage 发布 `owner.md`,不得用 owner 登录态代签或代上传普通 sub 名片。Group/Org 只在作为被管理的 `sub_aid` 时排除于通用 Ownership;符合普通 owner 规则时,仍可作为 `owner_aid`。实体自身关系由专属生命周期建立、解除、转移,不进入通用任务、审批或 NS Ownership 关系状态;以 Group/Org 为 `sub` 调用任务 Facade 时以 `not_applicable` 错误结束(`retryable=false`,按语言表现为异常、Promise reject 或 Go error),共识检查则返回 `status/code=not_applicable` 的结果对象。
|
|
25
|
+
|
|
26
|
+
Ownership 是 `agent.md` 上叠加的可选关系属性。基础名片解析、普通读取和外层签名验证应与关系验证分层;仅 Ownership 字段或关系材料无效,不得据此判定基础 `agent.md` 无效。关系为 `invalid` 或 `unavailable` 时,只停止或降级依赖当前 owner 关系的授权、共识和关系操作;普通 `agent.md` 下载、基础验签及通信继续。普通读取兼容没有 Ownership 专用 Header 的旧 SDK;新 SDK 的关系操作仍执行当前协议验证。
|
|
27
|
+
|
|
28
|
+
Group/Org 名片由实体私钥生成主签,当前 owner 以本人 token 上传,无需实体登录;实体单签及带 owner 附签的双签/多签均可,每个附签都须为当前 owner,存在就必须验全部块。Group 旧实体单签及实体身份上传始终兼容,Org 不开放该实体身份旧入口。新 SDK 现代上传取消额外 V2 授权,保留当前 owner、生命周期、实体证书代际与 CAS 检查;服务端另保留旧0.5.19单块 owner 主签 V2 入口及原 HTTP 条件,见 [协议 §2.5](../protocol/Ownership协议定义2.1.md#25-grouporg-名片的实体主签与-owner-上传)。 实体 fresh GET 必须同时携带 `X-AUN-Ownership-Check: 1`、`Cache-Control: no-cache`、`X-AUN-Signature-Format: multi-v1`;NS 仅凭 Check 头绕过 LRU 并新鲜验证全部签块,仍返回 not_applicable,不进入通用 Ownership 账本。 fresh GET/HEAD 保留 current/stale、权威 owner/实体指纹头与对应表示 ETag;真正缺失为 404,权威依赖失败为 503。verified 下载逐块验证历史证书及原字节;单块显式 owner 主签旧实体使用该 owner 历史证书,不将正文实体指纹绑定到 owner 证书。历史成功不代表当前权限,例外不用于现代写入或多块 owner 主签。独立 AIDStore 上传实体名片时,Python/Go 须注入权威 entity owner resolver,返回 owner_aid 与 entity_cert_fingerprint;TS/JS 默认通过 fresh NS 与 PKI 核对当前 owner、实体类型及证书指纹,不能把 Client 的接线视为四端 AIDStore 都有的默认能力。
|
|
29
|
+
|
|
30
|
+
关系通过现有 `GET/HEAD/PUT /agent.md` 和通用 Storage 操作建立;不新增 ownership 专用 RPC。SDK 的请求、同意、拒绝和 ready 消息是普通加密 P2P 载荷,不是服务端关系授权接口。托管是应用显式选择的能力,绑定、释放和转移均不以托管为前提。
|
|
31
|
+
|
|
32
|
+
Ownership 2.1 关系事实只来自 sub 的权威 `agent.md` 与 owner 签署的权威 `owner.md`;后者保存在 owner 自己的 Storage,发布前重新核对完整原文、摘要和存在性。`owner_aid` 是身份字段,不是独立文件或 2.1 关系记录。NS 的数据库事务只保证 `agent.md` 原文、ETag CAS 与同步待办的原子性,不另存 2.1 关系表、证据事实库或历史账本。legacy Auth JSONL 不参与 2.1 判断。CA、P2P、Storage 与 SDK 本地任务分别执行;再次读取当前材料不能制造跨服务一致快照,也不提供 ABA 或完整文件回滚检测保证。
|
|
33
|
+
|
|
34
|
+
## 2. 分层与最小依赖接口
|
|
35
|
+
|
|
36
|
+
TypeScript 将语义集中在两个模块,Client 负责装配已有能力。新语言 SDK 可以采用自己的类和命名,但必须保持以下职责分离。
|
|
37
|
+
|
|
38
|
+
| 层次 | TypeScript 实现索引 | 移植时保持的职责 |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| 文件模型与验证 | [ownership-v21.ts](../../ts/src/ownership-v21.ts):`parseOwnershipFile`、`verifyOwnershipFile`、`signOwnershipFile` | 原始字节、两种文件角色、严格 schema、签名与证书状态。 |
|
|
41
|
+
| 本端文件步骤与共识 | 同文件:`OwnershipFiles` | 五个内部文件方法、原条件重试、六态检查、条件清理。 |
|
|
42
|
+
| Storage 适配 | 同文件:`OwnershipStorageAdapter` | 权威存在性、前后完整原文及摘要核对、完整文件原子发布和清理前复核。 |
|
|
43
|
+
| 编排 | [ownership-workflow.ts](../../ts/src/ownership-workflow.ts):`OwnershipWorkflow` | 固定任务、审批、inbox/outbox、串行推进和事件。 |
|
|
44
|
+
| NS HTTP 与普通名片 | [agent-md.ts](../../ts/src/agent-md.ts):`AgentMdManager` | 新鲜读取、完整原文条件 PUT、普通待上传恢复。 |
|
|
45
|
+
| 通用签验与业务 Schema | [aid-store.ts](../../ts/src/aid-store.ts)、[cert-utils.ts](../../ts/src/cert-utils.ts)、[agent-md-schema.ts](../../ts/src/agent-md-schema.ts) | Store.sign/verify、AID 兼容包装、agent.md 与 owner.md 统一复用唯一 signDocument/verifyDocument core;YAML/资源身份由调用者另验,服务端独立实现同构 core。 |
|
|
46
|
+
| 当前证书 | [auth.ts](../../ts/src/auth.ts):`AuthFlow.resolveOwnershipCertificate` | 精确证书、链、当前可签状态及严格 OCSP。 |
|
|
47
|
+
| Client 接线 | [client.ts](../../ts/src/client.ts):`_getOwnershipFiles`、`_getOwnershipWorkflow` | 本端身份、HTTP、Storage、消息、事件和连接恢复。 |
|
|
48
|
+
| 本地任务存储 | [keystore/index.ts](../../ts/src/keystore/index.ts)、[local-token-store.ts](../../ts/src/keystore/local-token-store.ts)、[aid-db.ts](../../ts/src/keystore/aid-db.ts) | 按身份隔离的每任务 CAS;失败与不存在分开。 |
|
|
49
|
+
|
|
50
|
+
`OwnershipFileDependencies` 的最小能力如下。不要让文件层依赖界面、P2P 审批或其它服务的源码。
|
|
51
|
+
|
|
52
|
+
| 依赖 | 必须提供的语义 |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| `currentAid()`、`now()` | 本端加载的签名身份;Unix 秒时钟,测试时可固定。 |
|
|
55
|
+
| `readAgentMdFresh(subAid)` | NS 当前完整原文、原 ETag、协议、关系版本、锁及观察时间。 |
|
|
56
|
+
| `submitAgentMdRaw(subAid, raw, condition)` | 本人身份上传持久保存的完整签名字节;携带唯一原条件,并回源确认。 |
|
|
57
|
+
| `readOwnerMd(ownerAid, subAid)` | 规范路径的权威存在/不存在结果、完整正文及摘要。 |
|
|
58
|
+
| `writeOwnerMd`、`deleteOwnerMd` | 本人身份、发布前起始原件核对、完整原子写入;删除前核对当前 NS 和本任务原件。 |
|
|
59
|
+
| `resolveCertificate(aid, fingerprint, purpose?)` | 精确证书及已验证的当前链、吊销、生命周期和新鲜度;未知用途可省略。 |
|
|
60
|
+
|
|
61
|
+
`OwnershipWorkflowDependencies` 只再加入本端 AID、任务存储、文件层、`send` 和 `emit`。TypeScript 的 `send` 调用 `message.send`,设置 `encrypt: true`;`emit` 进入本地 dispatcher。各服务独立实现自己的网络契约,不 import SDK 或共享服务实现代码。
|
|
62
|
+
|
|
63
|
+
五个文件方法 `declareOwneraid`、`declareSubaid`、`revokeOwneraid`、`revokeSubaid`、`transferOwneraid` 接收内部任务上下文,供编排器复用;它们不创建新 `operation_id`、不发起审批,也不是应用 Facade。`cleanupOwnerFile` 是内部后续清理步骤。
|
|
64
|
+
|
|
65
|
+
## 3. 标识、版本与数值
|
|
66
|
+
|
|
67
|
+
| 值 | 校验与用途 |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| 完整 AID | 非空、完整小写;角色、资源路径、证书 AID 和认证身份分别核对,不能靠大小写转换接受错误材料。 |
|
|
70
|
+
| `operation_id` | SDK 生成的小写 UUIDv4,关联各端同一次编排和重试;只在任务与 P2P 中使用。 |
|
|
71
|
+
| `declaration_id` | 每份声明的小写 UUIDv4;不等于 `operation_id`,也不要求两方相同。 |
|
|
72
|
+
| 名片 `version` | 字符串 `MAJOR.MINOR.PATCH`,描述名片,不是关系版本。 |
|
|
73
|
+
| `statement.version` | 整数 `2`,表示声明容器。 |
|
|
74
|
+
| NS 协议能力 | 字符串 `2.1`,通过响应头确认。 |
|
|
75
|
+
| P2P `sdk.v1` | `aun.ownership.sdk.v1` 中的版本,只表示 SDK 消息格式。 |
|
|
76
|
+
| NS 关系版本 | `0..9007199254740991`;只投影 `agent.md` 当前声明版本,无声明时为 `0`,不另存历史上界。 |
|
|
77
|
+
| 声明关系版本 | `1..9007199254740991`;新绑定为当前可见声明版本加一,无声明时从 `1` 开始;转移为当前声明的 `v+1`。 |
|
|
78
|
+
|
|
79
|
+
释放任务的目标版本沿用当前声明 `v`,release 或权威删除只解除该声明,NS 不递增版本;普通更新和重复检查也不递增。清理名片关系字段后,响应版本为 `0`,再次绑定从 `1` 开始。例如绑定 `0→1`,释放仍为 `1`,清理后 `0`,再次绑定 `1`;从版本 `1` 转移则直接到 `2`。版本不是跨清理周期的全局代际,旧任务还须匹配完整声明、原文件摘要及原 CAS 条件。
|
|
80
|
+
|
|
81
|
+
释放后再绑定同一 owner,若 sub 的 `agent.md` 仍保留旧声明,须先由 sub 完成已有字段清理,再发布新的 owner declare;SDK 在创建任务或产生副作用前以 `conflict`/`action_required` 提示,避免新 declare 覆盖唯一释放依据。绑定不同 owner 仍可使用当前可见版本 `v+1`;已清理时默认从 `1` 开始。
|
|
82
|
+
|
|
83
|
+
移植实现应在创建递增任务、构造目标版本前拒绝当前版本已经达到 `9007199254740991` 的操作;不能溢出或使用本语言更大的整数扩展协议;清理关系声明后的版本 `0` 是无声明投影。TypeScript 的 `ownershipInteger` 使用 `Number.isSafeInteger`,文件、消息和持久任务解码另做字段检查。
|
|
84
|
+
|
|
85
|
+
双方 statement 的 `version`、`owner_aid`、`sub_aid`、`relation_version` 必须一致;`declaration_id`、`declared_at` 可以不同。普通名片更新则必须保留 sub 自己原来的完整 statement,不能重新生成它来代替正文更新。
|
|
86
|
+
|
|
87
|
+
起始证据统一保存 `base_agent_md={exists,raw,sha256,etag,statement|null}` 与 `base_owner_md={exists,raw,sha256}`。非空 statement 完整相同的普通正文更新不替代关系,尚未签署的本方候选使用新鲜读取的原 ETag;已持久保存的签名字节重试仍沿用其原 CAS,不刷新条件。起始无声明时完整 agent 原文变化则停止旧审批。owner 写前和清理前重读当前完整原文、摘要及存在性,不增加远端条件字段。 base_owner_md 对应 base_agent_md.statement 所指当前/最后 owner 的文件;无 statement 时没有当前 owner 事实,本地可省略或使用空标记;bind/transfer 目标 owner 写前原件在待发布文件中另存并复读,不替代原 owner 基线。
|
|
88
|
+
|
|
89
|
+
## 4. 原始文件、严格解析与签名
|
|
90
|
+
|
|
91
|
+
### 4.1 容器和角色
|
|
92
|
+
|
|
93
|
+
文件由 YAML frontmatter、可选 Markdown 正文与连续一或多个尾签块组成。payload 为首块前原始 UTF-8 字节,最多 4096 字节;从首块至文件结尾的整个签名区最多 2048 字节,含分隔与尾白。每块签其之前完整 prefix,首块维持旧正文裸签;末块后及块间只允许空白。
|
|
94
|
+
|
|
95
|
+
解析器必须拒绝无效 UTF-8、非连续尾签块、重复字段、重复 YAML 键、自定义 tag、锚点、别名和未知 ownership 字段。计数采用 UTF-8 字节,不采用 UTF-16 字符串长度;description/avatar 的字符上限按 Unicode 字符计数。
|
|
96
|
+
|
|
97
|
+
| 文件角色 | 身份及字段约束 |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| 通用 `agent.md` | `aid`、目标 AID、认证上传者和证书 AID 均为 sub;必填 `aid/name/type/version`,name/type 为非空白字符串。`owner` 与 `ownership` 同时出现或同时省略;ownership 仅含完整 statement。human 不得声明 owner,包含 self-owner;Group/Org 按第 1 节分支处理。 |
|
|
100
|
+
| `owner.md` | 路径为 `owner_aid:/sub_aids/{sub_aid}/owner.md`;顶层恰为 `owner_aid/sub_aid/ownership`,不要求 name/type/名片 version。statement 与路径一致;ownership 含 statement/action,仅 transfer_owner 另含 transfer。 |
|
|
101
|
+
|
|
102
|
+
statement 恰含 `version/declaration_id/owner_aid/sub_aid/relation_version/declared_at`。owner 动作为 `declare`、`release`、`transfer_owner`;release 保留被释放的旧关系字段。transfer 恰含 `new_owner_aid/target_relation_version/expires_at`,目标版本等于旧版本加一,期限为正整数 Unix 秒。sub 不得在 agent.md 中放 action 来自行授权解绑。
|
|
103
|
+
|
|
104
|
+
角色取自请求资源和路径,不取自签名 TAG。TypeScript 的 `parseOwnershipFile` 分别调用 agent schema 和 owner schema;`verifyOwnershipFile` 进一步核对目标、认证 AID、证书 AID 及路径上下文。复用通用名片校验器时,不能给 owner.md 补虚构 name/type/version 来绕过角色检查。
|
|
105
|
+
|
|
106
|
+
### 4.2 数值词法不能在解析后丢失
|
|
107
|
+
|
|
108
|
+
关系版本、声明时间、授权期限等字段必须是协议整数。TypeScript 的 `parseFileFrontmatter` 检查 YAML scalar 的原始 `source`;`parseOwnershipMessage` 在 JSON 解析外用保留词法的解析结果检查重复键及版本 token。版本 token 使用 `0` 或无前导零的十进制数字,随后再检查范围及字段下限。
|
|
109
|
+
|
|
110
|
+
`declared_at`、`expires_at`、签名 `timestamp` 的范围统一为 `1..9007199254740991`,只接受十进制正整数原词法;先检查词法及范围,再转数字或日期。非法时间归 invalid,不能由日期库异常变成 unavailable;表示范围不替代证书有效期、当前时钟及授权未过期检查,不另设年份上界。
|
|
111
|
+
|
|
112
|
+
新语言不能先把输入转成普通 map 再声称完成严格校验:JSON 的重复键可能已经覆盖,`1.0`、`1e0` 可能已变成整数值。YAML 的 `+1`、`01`、十六进制、显式数值 tag、字符串 `"1"` 和布尔值均不能通过类型转换成为有效版本。Python 须排除 bool 作为 int;Go 等默认浮点 JSON 解码须保留 number token;大整数语言和数据库 BIGINT 仍检查协议上界。
|
|
113
|
+
|
|
114
|
+
### 4.3 签名输入和摘要分别保存
|
|
115
|
+
|
|
116
|
+
当前文件签名使用 **ECDSA P-256 / SHA-256**,signature 为严格 Base64 的 ASN.1 DER 签名。不能把 E2EE 或 WebCrypto 返回的固定宽度 P1363 `r||s` 原样写入文件;密码适配器负责 DER 编码、解析和验证,并拒绝多余 DER 数据及非规范整数编码。
|
|
117
|
+
|
|
118
|
+
agent 的常规输出标识为 `AUN-SIGNATURE-AGENTMD-V2`,owner 为 `AUN-SIGNATURE-OWNERSHIP-V2`,均兼容 `AUN-SIGNATURE` 和协议允许的大写字母、数字、连字符 TAG。各尾块含必填 `cert_fingerprint/timestamp/signature`、可选 `public_key_fingerprint`;附签必含 `signer_aid`,通用容器可读主块可选 signer_aid,但普通 agent.md/owner.md 主块禁止该字段,实体主块显式 signer_aid=target;两个指纹分别是证书 DER、SPKI DER 的 SHA-256。
|
|
119
|
+
|
|
120
|
+
公开 AIDStore.sign/verify 保留默认 raw detached 签验,并支持 document 多签;TS/JS 为 Promise<Result>。document 不要求 YAML,agent.md/owner.md 只能在同一 core 外叠加各自 Schema、主签身份及授权校验,不能再复制尾签算法。文本及 document 严格 UTF-8;显式 input_type="file"(TS/JS inputType: "file")读取文件,raw 文件可含任意字节,不猜路径或识别 file://。in_place/inPlace 仅 file + document 且成功后写回;浏览器 File/Blob 只读,FileSystemFileHandle 才可写。完整参数见 [API 手册](06-API手册.md#通用-sign--verify)。
|
|
121
|
+
|
|
122
|
+
append 保留已有完整链字节,后块签自身起点前全部 prefix;只有已有链末字节非 CR/LF 时补 LF,无旧块仍按首签要求非空正文以换行结束,否则拒绝。TAG 为字面后缀,空串无 TAG,内部传 AGENTMD-V2/OWNERSHIP-V2 短标签,不把 AUN-SIGNATURE 当特殊选项。verify 逐块验证并返回实际顺序的 signatures,数学失败仍保留全部结果,不能只验主签或在附签失败后降级;末端删签可形成有效短链,core 不承诺检测。总尾区仍限 2048 字节。
|
|
123
|
+
|
|
124
|
+
| 材料 | 用途 |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| payload 原始字节 | 首块前字节为主签输入;第 i 块签其之前完整 prefix,包含前序完整块与分隔。验签不重新序列化 YAML、换行或 Unicode。 |
|
|
127
|
+
| 完整签名文件 SHA-256 | 包含全部尾块,用于持久文件完整性、上传确认、Storage 完整内容核对与留证。 |
|
|
128
|
+
| NS 原始 ETag | 文档条件值,含服务返回的引号等原表示,保存后原样用作 If-Match。 |
|
|
129
|
+
|
|
130
|
+
TypeScript 的 `ownershipSha256` 计算完整文件摘要;`AgentMdManager.contentEtag` 当前生成带引号的全文 SHA-256 ETag。移植 HTTP 适配器仍须保存服务实际返回的 ETag,不能把本地重算摘要替代原条件。编辑未签 payload 后可以由本人签署新文件;已保存的待提交 raw 不再规范化或重签。
|
|
131
|
+
|
|
132
|
+
## 5. 当前证书与吊销验证
|
|
133
|
+
|
|
134
|
+
通用 Store.verify 默认离线 load 本地公钥/证书,不要求私钥,也不隐式远程 resolve。历史/远端材料通过显式可信 certificateResolver 注入;业务原有 resolver 负责证书链、签署时间或当前生命周期/吊销检查,再交唯一 core 验原字节,既有 agent.md 下载的历史远程验证流程保留。resolver 操作异常保留外层 error,不伪装为坏签名;下述当前证书检查属于关系验收层,不是通用数学验签默认保证。
|
|
135
|
+
|
|
136
|
+
文件验证不仅要求签名正确,还要求签署证书属于对应 AID、精确匹配证书指纹、链到可信根、P-256 公钥、当前有效且处于 `active_signing`、吊销状态已可靠确认。尾块 timestamp 必须在证书有效期内,不能比当前时间快超过 300 秒;它未被 payload 签名覆盖,不能独自证明历史授权时间。
|
|
137
|
+
|
|
138
|
+
TypeScript 的 `AuthFlow.resolveOwnershipCertificate` 使用既有 PKI 路径:精确 AID 与完整指纹查询,加 `consistency=authoritative`,读取 PEM 后核对以下响应头。
|
|
139
|
+
|
|
140
|
+
| 响应头 | 要求 |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| `X-AUN-Cert-Consistency` | `authoritative`。 |
|
|
143
|
+
| `X-AUN-Cert-Lifecycle-State` | 实际状态为 `active_signing`,不能从 OCSP good 推导。 |
|
|
144
|
+
| `X-AUN-Cert-Fingerprint` | 与本次请求、返回证书 DER 指纹完全匹配。 |
|
|
145
|
+
| `X-AUN-Cert-Observed-At` | UTC RFC3339 时间;过去最多 30 秒,未来偏差最多 5 秒。 |
|
|
146
|
+
|
|
147
|
+
随后核对证书链,捕获本次链选定的直接 issuer,严格验证已签名 OCSP DER、CertID 的 issuer name/key hash 和证书序列号、ResponderID、状态与时限;只接受该 issuer 亲签,内嵌证书仅认可该 issuer 本身,不接受委派 responder。链获取及 OCSP 接收后使用当时的当前时间,末尾再次核对链有效期,不能把初始时点贯穿网络等待。OCSP `ThisUpdate` 最多过去 30 秒,`ProducedAt` 最多过去 90 秒,未来偏差均最多 5 秒;`NextUpdate` 严格晚于当前时间及 ThisUpdate。90 秒窗口包含现有 CA 对 ProducedAt 的分钟取整;不放宽其它当前状态窗口。整个验证窗口也不能超过 30 秒,NS 最终提交仍独立复核其当前材料。
|
|
148
|
+
|
|
149
|
+
`OwnershipFiles.verifyFile` 按实际签名身份查询当前证书;未知身份用途可省略,owner.md 的 owner 未知类型时不能强制普通 signing。Group/Org 主签证书属于实体并匹配当前实体指纹,可选 owner 附签同样必须验证,不替代当前生命周期授权。Client 通过 `_resolveOwnershipCertificateGateway` 选择证书所属域。缓存证书或 peer 验签成功不等于本次权威状态验证成功。
|
|
150
|
+
|
|
151
|
+
**CRL 的当前实现边界:** Ownership 上述 resolver 实际走严格 OCSP,没有额外调用通用 Auth 的 CRL 检查。`auth.ts` 中 `_verifyAuthCertRevocation/_fetchGatewayCrl` 属于另一条通用路径,存在 DER 解析失败后的 JSON revoked_serials fallback;通用比较还涉及小写字符串匹配,不能据此声称所有历史序列号表示均已兼容。移植者若使用 CRL 实现吊销适配,应验证签发者、签名、适用范围、新鲜度和序列号对应关系;无法验证的材料不得默认成“未吊销”,也不能用未经验证的 JSON 列表替代 Ownership 的当前吊销契约。
|
|
152
|
+
|
|
153
|
+
已知错误证书、坏签名、无效链、吊销或非可签状态归为 `invalid`;缺少权威头、OCSP unknown、服务不可达或材料过期归为 `unavailable`。历史任务审计保存当时完整文件和本端验证材料,不要求历史证书今天仍可签名;这些记录不是 NS 当前关系事实。当前释放状态仍从 `agent.md` 与 owner 路径的新鲜材料判定,NS 不保存释放终局;服务或验证材料不可确认时返回 `unavailable`,不能用历史结果代替。
|
|
154
|
+
|
|
155
|
+
## 6. NS HTTP 与六态共识
|
|
156
|
+
|
|
157
|
+
每个 NS GET/HEAD/PUT(含 fallback、fresh 与重试)必须携带 X-AUN-Signature-Format: multi-v1;无头时多块投影为 raw[:first.End](首块 --> 后立即结束),单块保留首签原文,并将 `<!-- AUN-SIGNATURE-<TAG>` 规范化为旧 SDK 能识别的裸 `<!-- AUN-SIGNATURE`,移除首签块中不参与摘要签名的 `signer_aid` 行。投影不改变正文、签名或证书指纹,也不改变完整存储。NS 保留完整存储,Vary、ETag、Content-Length 与 304 按表示区分;旧 If-Match 先匹配旧表示,再映射完整存储快照 CAS,不能把投影摘要当完整文件条件。agent_md_updated.etag 固定完整存储 ETag。
|
|
158
|
+
|
|
159
|
+
`AgentMdManager.readOwnershipFresh` 经 `_ownershipRequest` 同时发送 `X-AUN-Ownership-Check: 1`、`Cache-Control: no-cache` 与 multi-v1,严格读取 UTF-8 正文,禁止自动重定向。协议还允许新鲜 HEAD;TypeScript 此入口实际使用 GET。浏览器移植须确认 CORS 暴露关系头和 ETag,否则不能把读不到头当成默认值。
|
|
160
|
+
|
|
161
|
+
该 Header 用于 Ownership 共识的新鲜读取,不是普通 `agent.md` 读取、下载或基础验签的前提。旧 SDK 普通读取缺少该 Header 时 NS 必须兼容;不得因缺少关系 Header 阻断普通名片,或据此推断 Ownership/名片无效。
|
|
162
|
+
|
|
163
|
+
| 响应头 | 校验 |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| `X-AUN-Ownership-Protocol` | 精确为 `2.1`。 |
|
|
166
|
+
| `X-AUN-Ownership-Version` | 严格十进制整数,范围 0 到协议上界;只投影 `agent.md` 当前声明版本,无声明时为 `0`。 |
|
|
167
|
+
| `X-AUN-Ownership-Lock` | 仅 `locked/unlocked`,由当前两份权威材料判定,不是数据库中的独立关系事实。 |
|
|
168
|
+
| `ETag` | 文件存在时必填,保留服务原始值。 |
|
|
169
|
+
|
|
170
|
+
可靠初始 404 必须来自正确 NS 且携带 2.1、版本 `0`、`unlocked` 的完整元数据。TypeScript 对没有协议头的路由 404 可以尝试既有 NS URL,再校验最终响应;不能将任意网关 404、数据库失败或缓存 404 认定为 unbound。编排发起还要求初始名片已发布;可靠初始不存在本身不足以直接开始绑定写入。
|
|
171
|
+
|
|
172
|
+
`submitOwnershipRaw` 要求本端身份、目标 AID、名片 AID 一致,持久原条件恰为 `if_match` 或 `if_none_match: '*'` 之一,验证完整已签文件后提交,最后新鲜读取确认完整原文。新 SDK 发布包含普通更新与群名片,已有文件使用原 If-Match,首次创建使用 If-None-Match;2.1 关系和现代实体格式缺条件返回 428,文档冲突为 412,关系版本冲突为 409。NS 旧客户端旧格式入口可缺新 Header/CAS,但仍执行名片数据库 CAS、两份权威材料的关系校验和当前声明版本保护;新上传严格校验,旧关系正文更新保留原关系字段。四 SDK 将 HTTP 428 统一映射为 `unsupported_protocol`;合规 SDK 必须始终携带原条件,收到 428 时不得移除条件或降级重试。TypeScript 的 raw 提交把 409/412 映射为 `conflict`、401/403 为 `forbidden`;不要用设计中的细分错误替代实际 HTTP 适配行为。
|
|
173
|
+
|
|
174
|
+
`OwnershipFiles.checkConsensus` 的顺序是:新鲜 NS 原文及元数据 → 当前规范 owner 文件及证书 → 再次新鲜 NS。TypeScript 前后比较全文、ETag、存在性、关系版本、锁及可选 owner 元数据,且总窗口不超过 30 秒,从首次 GET 发出前计时,覆盖首读及两种末读分支;材料变化或超时返回可重试 unavailable,不能返回 consensus。仅文档 ETag 相同不足以证明 owner 未释放。
|
|
175
|
+
|
|
176
|
+
| 六态 | 判定及权限含义 |
|
|
177
|
+
| --- | --- |
|
|
178
|
+
| `consensus` | NS 锁定、NS 版本与双方声明版本一致,AID 和当前签名验证通过;owner declare 或尚未提交的 transfer_owner 均可证明旧关系。 |
|
|
179
|
+
| `released` | `agent.md` 仍有版本 `v` 的声明,对应 owner 文件为有效 release 或已权威确认不存在;前后新鲜观察一致,版本仍为 `v`。 |
|
|
180
|
+
| `unbound` | 新鲜有效的权威名片无当前声明,投影版本为 `0`;释放后清理也属于此态,解析失败不能推断无关系。 |
|
|
181
|
+
| `single_sided` | 只有一方目标材料准备,尚未成为 NS 已验收稳定关系;无 owner 权限。 |
|
|
182
|
+
| `invalid` | 已知字段、身份、路径、版本、签名或证书无效;不解锁。 |
|
|
183
|
+
| `unavailable` | 无法确认当前服务或两份权威材料;保留保护和待办,不等于解绑。 |
|
|
184
|
+
|
|
185
|
+
以上六态只描述 Ownership 关系及其授权可用性,不替代基础 `agent.md` 的解析和外层签名结果。仅关系字段或关系材料无效时,只对依赖 Ownership 的操作降级;普通名片读取、下载、基础验签和通信不因此失败。
|
|
186
|
+
|
|
187
|
+
当前 `released` 只表示本次观察确认当前声明已释放,不是 NS 持久终局;字段清理后返回 `unbound/0`。历史 completed 保持历史完成,但不能单独证明当前释放或授权。无目标上下文的公开检查不能枚举全网未提交 owner.md;内部任务已知目标时,检查器才可识别目标 owner 单方声明。转移期限过期只阻止新转移,不使旧关系自动失效。
|
|
188
|
+
|
|
189
|
+
共识结果携带 `sub_aid/owner_aid/relation_version/lock`、`agent_md_etag/agent_md_sha256`、`owner_md_sha256`,错误可附 `code/reason/retryable`。没有权威观察值时,字段可表示为空;SDK 使用的 `null`、零版本、空字符串或 `unlocked` 等占位值都不代表观察到了版本 0、空摘要或无锁。调用者必须先检查 `status`,只有 `consensus` 或 `released` 才能按对应状态解释权威字段。
|
|
190
|
+
|
|
191
|
+
## 7. Storage 权威读取、完整发布与权限
|
|
192
|
+
|
|
193
|
+
四 SDK 的 Ownership Storage 适配器使用通用 `storage.head_object/get_object/delete_object`,发布使用 `storage.create_upload_session` → HTTP PUT → `storage.complete_upload`。读取参数固定 `owner_aid`、`bucket=default`、无前导斜杠的 `object_key=sub_aids/{sub_aid}/owner.md` 与 `consistency=authoritative`。
|
|
194
|
+
|
|
195
|
+
| 权威结果 | 必须核对 |
|
|
196
|
+
| --- | --- |
|
|
197
|
+
| 所有结果 | `consistency=authoritative`、请求 owner、bucket、规范 path、布尔 exists、observed_at;恢复未就绪不能当权威不存在。 |
|
|
198
|
+
| 文件存在 | 小写完整 SHA-256,以及严格 Base64 的完整 content;现有 object_id/version 不作为读取一致性或共识条件,缺失或无效的可选 version 不拒绝其它有效读取材料。发布时单独要求既有 version 为正安全整数,不能将 null、布尔值或字符串强转为发布条件。 |
|
|
199
|
+
| 文件不存在 | 权威查询明确当前不存在,不从下载失败推断;不保存删除历史。 |
|
|
200
|
+
|
|
201
|
+
适配器前后重新读取当前完整文件、摘要及存在性,核对完整下载摘要,窗口不超过 30 秒;不一致返回 unavailable。不存在采用权威查询的 exists=false,不依赖公开下载失败。网关错误、超时、权限错误、元数据与正文不同步或恢复未完成都不能作为删除证据。
|
|
202
|
+
|
|
203
|
+
服务身份须由已认证 Gateway 路由、跨域通道和 RPC 响应绑定证明。当前 wire 不新增“Storage 自报服务证书”字段;TypeScript 适配器从目标域导出 `st.{issuer}` 标签,`OwnershipFiles.readOwner` 核对标签、认证来源、命名空间及路径。这依赖 Client 现有可信路由;新语言不能只拼出相同字符串就宣称完成服务身份认证。
|
|
204
|
+
|
|
205
|
+
`writeOwnerMd/deleteOwnerMd` 验证本端即 owner。写前重新核对保存的起始存在性、完整原文和摘要;更新为一次完整原子替换,不先删后建。发布 `owner.md` 必须使用 create 返回的会话 URL 完成 HTTP PUT,complete 携带同一 `session_id`;存在时把本次权威读取的对象 `version` 作为 create/complete 的同一 `expected_version`,不存在时使用 `0`。版本缺失或无效不影响只读共识,但不能继续该发布。三阶段保持 Content-Type 一致,complete 提交完整文件的大小、SHA-256 并公开可读;临时对象验证完整且原版本条件仍匹配后才原子替换。沿用既有 Storage 接口,不增加路径修订、哈希条件 RPC 或删除历史;再读不能识别同内容 ABA 或完整文件回滚。
|
|
206
|
+
|
|
207
|
+
Storage 负责完整文件原子替换;当前 Ownership 写删不传路径修订或哈希条件,写前再读本身不构成跨请求 CAS。上传 session 的既有 `expected_version` 在实际发布时复核,冲突不能刷新版本强行继续旧任务。第三方 ACL、token、目录授权不能获得 owner.md 写删能力;父目录删除、移动、重命名、别名、挂载、软链、批量与自动清理入口都须执行同等限制。SDK 的 requireLocal 不能替代 Storage 服务端权限检查。
|
|
208
|
+
|
|
209
|
+
起始原件变化时停止旧写入,不更换保存的原件继续。清理仅依据当前 NS 已确认释放/转移及本任务完整旧原件,删除前再读 NS 和目标文件;已观察到后续文件则停止。删除当前 owner 对应的权威 owner.md 可成为 NS 确认释放的依据;删除不表示取消任务。
|
|
210
|
+
|
|
211
|
+
## 8. 七个 Facade、事件与错误契约
|
|
212
|
+
|
|
213
|
+
TypeScript 的 [client.ts](../../ts/src/client.ts) 只提供以下七个 2.1 业务 Facade。其它语言可遵循自身命名习惯,返回语义保持一致。
|
|
214
|
+
|
|
215
|
+
| Facade | 本端角色与行为 |
|
|
216
|
+
| --- | --- |
|
|
217
|
+
| `bindOwneraid(ownerAid)` | sub 发起绑定。 |
|
|
218
|
+
| `bindSubaid(subAid)` | owner 发起绑定。 |
|
|
219
|
+
| `acceptOwnershipRequest(operationId)` | 已核验、待审批的绑定接收方或转移新 owner/sub 同意原任务。 |
|
|
220
|
+
| `rejectOwnershipRequest(operationId, reason?)` | 对同一待审批任务明确拒绝。 |
|
|
221
|
+
| `releaseSubaid(subAid)` | 当前原 owner 发布 release 并新鲜确认释放。 |
|
|
222
|
+
| `transferSubaid(subAid, newOwnerAid)` | 当前原 owner 发起三方连续转移。 |
|
|
223
|
+
| `checkOwnershipConsensus(subAid?)` | 只读六态检查;省略时使用当前身份,不创建任务。 |
|
|
224
|
+
|
|
225
|
+
TypeScript 前六个方法返回 `Promise<OwnershipTaskResult>`,`checkOwnershipConsensus` 返回 `Promise<OwnershipConsensusResult>`。任务结果包含固定上下文、`status/step` 和可选 `code/reason/retryable`;status 为 `pending/completed/rejected/stopped/error`。`step` 是本端当前步骤,不是 NS 状态。两种结果类型从 [index.ts](../../ts/src/index.ts) 导出;内部 Workflow、任务存储和五个文件方法不因此成为应用入口。
|
|
226
|
+
|
|
227
|
+
发起前先查找本端身份、发起方、操作、参与方、base/target 版本完全相同的进行中任务,早于新操作资格检查;相同任务复用 ID、审批、原签名字节、条件和期限。精确目标已提交时新鲜核验完整证据完成原任务,同代际不同意图返回 conflict 且不另建 stopped;相同意图并发只保存一个任务。后代际先停止旧任务再创建新合法任务,历史 completed、rejected、stopped、不可重试 error 不作为新操作复用或自动复活。
|
|
228
|
+
|
|
229
|
+
服务、网络或验证依赖不可用归 `unavailable`,确定无效的文件、签名、证书或证据归 `invalid`。新鲜重读发现远端 NS ETag、关系版本、锁或 owner 完整原文、摘要或存在性已不满足任务保存的原条件,归 `conflict` 并停止旧写入;同一权威快照内部的元数据、正文摘要彼此不一致,以及 Storage Base64 传输封装损坏,归 `unavailable`;摘要匹配后确定非法的 UTF-8、文件字段或签名归 `invalid`。等审批/材料、`unavailable`、`unsupported_protocol` 保持 pending/true;版本替代、目标改变、授权过期、原条件失效为 stopped/false;确定证据无效为 error/false;明确拒绝 rejected/false,完整目标确认 completed/false。预检失败不建任务;本地任务存储/CAS/租约失败归 `persistence_unavailable`,保持已存记录并停止副作用。completed 后通知/清理失败只保存错误和待办,停止前先核目标事实,终态不被迟到消息重启。
|
|
230
|
+
|
|
231
|
+
| 本地事件 | 语义 |
|
|
232
|
+
| --- | --- |
|
|
233
|
+
| `ownership.request` | 已持久保存并核验的绑定/转移审批请求。 |
|
|
234
|
+
| `ownership.action_required` | release 已提交后,sub 的名片清理需要应用明确授权。 |
|
|
235
|
+
| `ownership.progress` | 本端阶段推进,不能作为关系成立证明。 |
|
|
236
|
+
| `ownership.completed` | 新鲜 NS 目标及本端材料核验匹配。 |
|
|
237
|
+
| `ownership.rejected` | 本次审批被拒绝。 |
|
|
238
|
+
| `ownership.stopped` | 本次推进已停止或被后续版本替代。 |
|
|
239
|
+
| `ownership.error` | 无法推进或核验;completed 后的通知/清理失败也可触发,保留已提交关系及待办。 |
|
|
240
|
+
|
|
241
|
+
事件直接传 payload,不要求应用读取 `event.params`。载荷包含公共任务字段和 `local_roles`;request 另含可信 `requester_aid`,已核验时附该任务实际验收的 `relation_version`,release 的 released/v 对应 v、unbound/0 对应 0,不能直接用内部目标版本标记代替,已有历史验收记录不改写。这些是 SDK 本地 dispatcher 事件,不是服务端事件类型,也不通过 P2P 转发。TypeScript 的 `emit` 在持久保存后排入 microtask;恢复可能再次通知,应用按 operation_id、事件名、step 幂等处理。
|
|
242
|
+
|
|
243
|
+
绑定/转移 completed 需要当前双方有效共识、指定 owner 和目标版本;TypeScript `confirm` 还核对本端明确同意,并按本端角色比较自己保存的 agent/owner 全文摘要。释放 completed 接受本任务声明 `v` 的新鲜 `released/v`,或由本任务原件严格关联的真实 `unbound/0` 完成证据;任务起始、目标版本保持 `v`;本次共识验收证据的 status/relation_version 保存真实 released/v 或 unbound/0,已有历史验收记录不改写。sub 离线或字段未清理不妨碍原 owner 以新鲜 released 完成,历史完成不替代当前关系检查。通知已发送、消息 ACK、ready、relation.confirmed 均不能代替这些条件。
|
|
244
|
+
|
|
245
|
+
| 业务错误码 | 处理语义 |
|
|
246
|
+
| --- | --- |
|
|
247
|
+
| `owner_locked` | 有效原锁阻止本次改写。 |
|
|
248
|
+
| `conflict` | 原版本、ETag或固定上下文变化,停止旧条件写入。 |
|
|
249
|
+
| `invalid` | 已知字段、签名或证书无效。 |
|
|
250
|
+
| `unavailable` | 当前事实无法确认,可保留任务等待。 |
|
|
251
|
+
| `unsupported_protocol` | 缺少 2.1 能力或遇到 legacy,不能降级写入。 |
|
|
252
|
+
| `persistence_unavailable` | 任务保存/读取失败或损坏,停止外部副作用。 |
|
|
253
|
+
| `forbidden` | 本端身份、参与角色、来源或消息方向不符。 |
|
|
254
|
+
| `operation_not_found` | 审批找不到对应本端任务。 |
|
|
255
|
+
|
|
256
|
+
任务结果的 `code` 是业务字符串;抛出的 TypeScript `AUNError` 用 `stringCode` 表示业务码,`code` 是数值 RPC 码,`retryable` 在错误实例上。Workflow 的 `drive` 将部分推进失败写入结果并发事件,持久化错误会向外抛出;不能假设每次调用只返回结果或只抛异常。六态 status 也不等于任务 status;例如缺协议能力可以得到 `status=unavailable`、`code=unsupported_protocol`。
|
|
257
|
+
|
|
258
|
+
当前没有公开 2.1 任务查询、取消或 force unlock Facade。测试 HTTP agent 的 status/events 路径是测试适配器,不能照搬成新的 SDK 或 AUN 服务端接口。
|
|
259
|
+
|
|
260
|
+
## 9. P2P 载荷与实际收件拦截
|
|
261
|
+
|
|
262
|
+
控制载荷 type 固定为 `aun.ownership.sdk.v1`,必含 `operation_id/operation/action/sub_aid/owner_aid/base_relation_version/target_relation_version`;operation 为 bind/release/transfer;bind、transfer 的目标版本等于起始版本加一,新任务 release 的目标版本等于起始版本,兼容旧 0.5.19 release 的原 base+1 wire 值而不改写原任务。transfer 必含 new_owner_aid,其它操作省略。reason 只允许在 reject 或 operation.stopped 中出现;未知、缺失字段拒绝。
|
|
263
|
+
|
|
264
|
+
| action | 合法发送方向 |
|
|
265
|
+
| --- | --- |
|
|
266
|
+
| `bind.request` | sub 或 owner → 另一绑定方。 |
|
|
267
|
+
| `bind.accept/bind.reject` | 原请求接收方 → 发起方。 |
|
|
268
|
+
| `transfer.request` | 当前原 owner → 新 owner、sub。 |
|
|
269
|
+
| `transfer.accept/transfer.reject` | 指定新 owner 或 sub → 原 owner。 |
|
|
270
|
+
| `transfer.ready` | 原 owner → 新 owner、sub。 |
|
|
271
|
+
| `owner.ready` | bind 的 owner 或 transfer 的新 owner → sub。 |
|
|
272
|
+
| `relation.confirmed` | bind/transfer 的 sub → 其它参与方;release 的原 owner → sub。 |
|
|
273
|
+
| `sub.cleaned` | release 的 sub → 原 owner。 |
|
|
274
|
+
| `operation.stopped` | 已有关联任务的参与方 → 其它参与方。 |
|
|
275
|
+
|
|
276
|
+
发送采用加密持久 `message.send`,不设置 volatile TTL。来源只取消息层验证的 from_aid;不相信载荷自报身份,也不接受发给自己的 P2P。`parseOwnershipMessage` 联合本端角色、原任务发起方、固定 AID/版本、审批与 NS 现状校验方向。ready 还要求本端已同意,并回源验证原 owner 授权与目标声明;relation.confirmed 必须回源确认目标结果。
|
|
277
|
+
|
|
278
|
+
TypeScript 的拦截链为 [v2/e2ee/decrypt.ts](../../ts/src/v2/e2ee/decrypt.ts) 保留解密 JSON 原文 → Client `_publishAppEvent('message.received')` → `_handleOwnershipMessage` → `OwnershipWorkflow.receive`。`decryptedOwnershipJsonText` 保留词法,控制来源通过解密后的 from_aid 传入。实时 push、离线 pull、重连补拉和排序消息都必须经过同一入口。
|
|
279
|
+
|
|
280
|
+
被识别为 `aun.ownership.*` 的 legacy type、未知 action、无效控制载荷由拦截器消费,不作为普通聊天消息投递。有效控制消息首先按已认证发送者、operation_id、action 保存 inbox;存储失败向调用链抛出,原待解密/有序/补拉消息必须留在原处。只有可靠保存成功,才能移除原消息、推进游标、标记已投递、发送 ACK。禁止把保存失败改成普通 message.received 或不可解密通知。
|
|
281
|
+
|
|
282
|
+
[client/delivery.ts](../../ts/src/client/delivery.ts) 的 `publishOrderedQueueItem`、`publishPulledMessage` 等路径会等待 Client 事件拦截;移植时要检查实际 delivery 调用链,不能只为一个 handler 写正确代码却在其返回前 ACK。收件去重不要求网络恰好一次;重复或乱序提示回源后仅补尚未完成步骤,迟到消息不能改目标或重启拒绝/停止任务。
|
|
283
|
+
|
|
284
|
+
下图展示普通有效控制消息的持久化边界。初次回源失败时,请求仍先进入 inbox,保存错误后等待恢复;`ownership.request` 只能在请求已核验并保存后发布。`sub.cleaned` 是额外前置校验分支:保存 inbox 前双读 NS,核对稳定的 `unbound/0`、空关系字段及前后相同的 ETag;回源失败或前后观察不一致时抛错,原投递队列保留消息、不推进游标、不 ACK;当前仍有关系时消费该提示而不推进清理。
|
|
285
|
+
|
|
286
|
+
```mermaid
|
|
287
|
+
flowchart TD
|
|
288
|
+
A[push / pull / 重连 / 有序队列] --> B[解密:保留原 JSON 与已认证 from_aid]
|
|
289
|
+
B --> C{aun.ownership. 控制类型吗}
|
|
290
|
+
C -->|否| D[普通 message.received]
|
|
291
|
+
C -->|是| E{载荷词法、方向与固定任务上下文有效吗}
|
|
292
|
+
E -->|否或不支持的控制类型| F[消费控制消息,不作为聊天投递]
|
|
293
|
+
E -->|是| G[尝试新鲜读取 NS;按发送者、任务、action 去重]
|
|
294
|
+
G --> H[CAS 持久保存 inbox;存在性与存储失败分开]
|
|
295
|
+
H -->|保存失败| I[向调用链抛错:保留原队列与游标,不 ACK]
|
|
296
|
+
H -->|保存成功| J[processInbox 回源核验;失败保留已存待办]
|
|
297
|
+
J --> K{已核验的待审批请求吗}
|
|
298
|
+
K -->|是| L[持久记录核验结果后发布 ownership.request]
|
|
299
|
+
K -->|否| M[仅按已存审批推进文件、确认或清理]
|
|
300
|
+
L --> O[receive 成功返回:控制消息已处理或可靠保存]
|
|
301
|
+
M --> O
|
|
302
|
+
F --> O
|
|
303
|
+
O --> P[delivery 才可移除原消息、推进游标及 ACK]
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Client `_handleOwnershipMessage` 将已解密消息封套交给 Workflow 的关键片段如下。移植时保留原 JSON 文本;普通 JSON 对象已丢失重复键、整数词法时不能补做同等检查。
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
const envelope = message as Record<string, unknown>;
|
|
310
|
+
const content = 'payload' in envelope ? envelope.payload : message;
|
|
311
|
+
return this._getOwnershipWorkflow().receive(
|
|
312
|
+
String(envelope.from_aid ?? ''), decryptedOwnershipJsonText(content) ?? content,
|
|
313
|
+
);
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## 10. 持久任务、审批与恢复
|
|
317
|
+
|
|
318
|
+
### 10.1 存储契约
|
|
319
|
+
|
|
320
|
+
TokenStore 提供 `loadOwnershipTask(aid, operationId)`、`listOwnershipTasks(aid)`、`compareAndSwapOwnershipTask(aid, operationId, expectedRevision, task)`。不存在返回 null;读取、解析、CAS 失败必须返回错误。expectedRevision 为 null 表示仅首次插入,后续更新比较原任务修订并递增。
|
|
321
|
+
|
|
322
|
+
TypeScript `AIDDatabase` 使用 `ownership_tasks(operation_id, revision, data)`,`BEGIN IMMEDIATE` 内读取、比较、写入并提交,LocalTokenStore 按身份定位数据库。本地任务修订与文件中的关系版本独立。进程内 `runSerialized(subAid)` 只负责本实例排序;数据库 CAS 防止旧任务快照覆盖。不能将全部任务放在一份易覆盖的 metadata JSON 中,也不能把损坏数据库自动重建成“没有任务”。
|
|
323
|
+
|
|
324
|
+
| 记录分组 | 必须持久保存的内容 |
|
|
325
|
+
| --- | --- |
|
|
326
|
+
| 固定上下文 | operation_id、operation、参与 AID、起始/目标版本、发起方、本端角色。 |
|
|
327
|
+
| 审批 | local_decision 的 pending/accept/reject、按 AID 保存的 approvals;发起意愿与接收方决定分开。 |
|
|
328
|
+
| 文件 | 本人完整已签 raw、全文 hash、原 NS ETag 与起始双文件证据;接收方首次验证转移授权的全文摘要 authorization_sha256 和实际 expires_at,恢复不允许换字节或延期。 |
|
|
329
|
+
| 收件 | inbox 与 received 幂等键,不能因远端失败丢掉原收件。 |
|
|
330
|
+
| 发件 | outbox 的接收 AID 与原载荷、已安排通知标记。 |
|
|
331
|
+
| 结果及清理 | status、step、verified_relation_version、清理授权引用、旧对象条件、最近错误。 |
|
|
332
|
+
|
|
333
|
+
审批决定与待发送回复在同一次 CAS 中保存,然后发送;本方文件 raw/hash/condition 也先保存再写远端。发送成功后再 CAS 清除 outbox,若发送后保存失败则可能重发,接收方必须幂等。当前 TypeScript outbox 保存 to/payload,不应宣称已经持久保存传输 message_id。
|
|
334
|
+
|
|
335
|
+
`decide` 只批准已核验、本端未决定的 bind/transfer 请求;不能批准自己发起的任务,也不能将 accept 改成 reject。原 owner 按审批 AID 收齐转移同意,角色重合以唯一 AID 计决定;尚未决定的另一方拒绝仍结束任务,迟到回复不覆盖已持久决定。
|
|
336
|
+
|
|
337
|
+
`decode` 校验任务身份、固定参与方、版本、角色、审批及集合;completed 还要求持久验收证据包含验收时的 NS ETag、agent.md 全文 SHA256、实际 lock/owner/relation_version,并按本端角色保存本人已签原始完整字节、摘要和原提交条件。bind/transfer 的核验版本等于目标,另须有 owner.md 全文 SHA256及本端同意;release 的任务起始、目标及历史 verified 版本仍为 `v`,真实完成证据保存 `released/v` 或严格关联本任务的 `unbound/0`,不得伪造 released。sub 的 unbound 证据须对应本任务清理原件、摘要、原 CAS,或本人明确 accept 的原 bind/transfer 的匹配 `release_cleanup`,并核对当前 NS 原文、摘要、ETag及已知提交 ETag;owner 须以本任务 release 完整原件、摘要与当前 owner.md 全文、hash 一致且当前证书验证有效确认,不得补造旧条件。权威不存在的 released 证据中 owner 文件摘要可为空。该记录只证明任务当时完成,当前关系仍须重新读取两份权威材料;清理后的 `unbound/0` 不保留历史版本上界。本人原件还须按文件角色、签名者、owner/sub、base/target、action、转移目标/期限及原条件匹配任务固定上下文;历史复验不要求现在仍可签或授权未过期。缺失、损坏证据的旧 completed 返回 persistence_unavailable,不能只看 step 或 completed 字符串跳过,也不能读取当前网络补造历史证据。合法历史完成记录可保留,当前 NS 已进入后续版本不使它变成新的待写任务。
|
|
338
|
+
|
|
339
|
+
### 10.2 恢复顺序与失败重试
|
|
340
|
+
|
|
341
|
+
0.5.20、0.5.19 及更早任务按原格式及原有协议边界兼容;保留原 operation、有效审批、原签名字节和原提交条件,不能因缺少后增本地字段而一律停止或新建任务。历史适配、绑定容错和无参数 reset 的完整范围见 [编排指南第 8 节](Ownership-SDK编排指南2.1.md#8-崩溃与响应丢失后的恢复)。reset 只归档当前身份发起的未完成任务,保留原记录和远端文件,迟到消息不能复活。 旧 Owner 候选尚未发布时,原 `expected_revision` 必须有权威证据精确匹配,不能用当前 version 替代;服务未提供旧 revision 证据时保留原件及任务并返回 unavailable。目标已提交但任务仍待恢复时,只有本地原始签名候选与当前双方共识精确匹配才确认完成;缺少这些证据不能从当前网络补造历史原件或提交条件。
|
|
342
|
+
|
|
343
|
+
TypeScript `resume` 读取原任务,按 sub 串行 `drive`,实际顺序为 `processInbox → flush → 按分支 confirm/推进/清理`。`flush` 在发送每条待办前读取新鲜 NS,按 action 核对原关系或目标关系的完整声明、版本、锁和 owner;陈旧通知从 outbox 移除并持久保存,无法确认时保留待办,不发送。未完成任务的 transfer.ready 另核对持久授权期限。待审批请求重新发本地事件,仍为 pending;不能因为连接恢复或等待超时自动同意。通知发送本身不证明关系完成,后续处理和完成判断仍须核对新鲜 NS。
|
|
344
|
+
|
|
345
|
+
| 中断位置 | 恢复依据和行为 |
|
|
346
|
+
| --- | --- |
|
|
347
|
+
| 审批已保存、回复未发或发送后未清 outbox | 先新鲜核对该 action 所需原关系或目标关系,再按原 operation_id、决定和载荷重发;陈旧通知持久移除,发送本身不确认关系完成。 |
|
|
348
|
+
| 文件已签但未发布 | 复用已保存原始字节与原条件;不换 declaration_id、时间或签名。 |
|
|
349
|
+
| owner 写入响应丢失 | 当前完整 raw/hash 与本任务已签文件匹配则仅确认;否则仅在保存的起始存在性、完整原文和摘要仍匹配时重传。已观察到变化返回 conflict,不从网络补造起始证据。 |
|
|
350
|
+
| sub PUT 响应丢失 | 若尚未持久化本次发布的 NS `agent.md` ETag,只有新鲜核对指定 owner、目标版本、锁及完整原文件均匹配时才能确认并保存该 ETag;若已持久化 ETag,当前 ETag 和完整文件必须匹配,ETag 变化即使原文相同也返回 conflict。未确认发布时,仅在原 If-Match/If-None-Match 条件仍成立时重传;仅版本增加不足以证明成功。 |
|
|
351
|
+
| 当前路径不存在 | 与保存的起始存在性核对;起始文件原先存在而当前不存在时停止旧写入。不能据当前文件判断同内容 ABA 或历史回滚。 |
|
|
352
|
+
| release 已发布、NS 暂不可用 | 保留 release 与确认待办,恢复后请求新鲜 NS 检查。 |
|
|
353
|
+
| 已有后续版本、ETag 或完整原件变化 | 停止旧写入/删除,保留真实结果及错误;不能更换起始原件或刷新 NS 条件强行续写。 |
|
|
354
|
+
| 转移期限到期 | 不延期重签,不自动 release 再 bind;继续须新的明确发起和审批。 |
|
|
355
|
+
| 关系已提交、通知/旧文件/副本仍待处理 | 保持已提交关系,分别补发、条件清理或由 NS 补齐副本。 |
|
|
356
|
+
|
|
357
|
+
TypeScript 的 `publishOwner` 固化起始存在性、完整原文和摘要,连同已签 raw/hash 持久保存,实际发布前再次核对原件;`publishAgent` 固化 NS 原 If-Match/If-None-Match 条件,连同已签 raw/hash 执行 `task.persist()`。重试沿用原件、原字节与 NS 原条件。恢复不能调用 bind/transfer 发起接口代替 resume,因为每次新发起通常生成新 UUID。停止消息只停止后续推进;不能撤回已发布转移授权或已提交关系。撤回未提交授权是原 owner 核对当前完整原件后原子覆盖为同版本 declare 并新鲜确认,不是删除文件,也没有独立取消 Facade。
|
|
358
|
+
|
|
359
|
+
Client `_connectOnce` 通过 `_safeAsync(_resumeOwnershipAfterConnect())` 异步安排身份检查、注册意图和 Workflow 恢复。`await connect()` 不等于所有 Ownership 待办已经恢复完成;实现和应用应以对应结果/事件及 NS 新鲜事实判断。
|
|
360
|
+
|
|
361
|
+
移植恢复入口应恢复原任务,不能用重新调用绑定/转移来代替。下图把本地故障、可重试依赖故障、确定冲突及完成后的待办分开。
|
|
362
|
+
|
|
363
|
+
```mermaid
|
|
364
|
+
flowchart TD
|
|
365
|
+
A[重启或重连:读取并 decode 原任务] --> B{任务、审批、原件与完成证据完整吗}
|
|
366
|
+
B -->|否| P[persistence_unavailable:保留记录,停止副作用]
|
|
367
|
+
B -->|是| C[按 sub 串行:processInbox → flush → confirm / 推进 / 清理]
|
|
368
|
+
C --> D{新鲜权威结果及本人原件能确认本次目标吗}
|
|
369
|
+
D -->|能| E[CAS 保存 completed 与真实完成证据]
|
|
370
|
+
E --> F[按当前事实补有效通知、清理;失败仅留待办和错误]
|
|
371
|
+
D -->|依赖暂不可用| G[pending / retryable:保留任务、原字节和条件]
|
|
372
|
+
D -->|未提交目标| H{当前事实仍满足原声明、原件和条件吗}
|
|
373
|
+
H -->|否;目标未提交| I[conflict:stopped,不覆盖后续文件]
|
|
374
|
+
H -->|是| J{审批和授权状态}
|
|
375
|
+
J -->|未决定| K[重发 ownership.request,等待应用决定]
|
|
376
|
+
J -->|明确拒绝| L[rejected:不复活]
|
|
377
|
+
J -->|已同意且未过期| M[仅补未完成步骤,复用原任务、签名字节和原条件]
|
|
378
|
+
J -->|授权过期或撤回| I
|
|
379
|
+
C -. 确定材料无效 .-> N[invalid:error / false]
|
|
380
|
+
C -. 本地读写或 CAS 失败 .-> P
|
|
381
|
+
K --> G
|
|
382
|
+
M --> D
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
例如移植 `publishAgent` 时,下列顺序约束必须保留:先持久化完整签名文件,再通过原条件提交。片段省略本节及第 4~7 节规定的回源、原件、证书和目标材料校验,不能将它作为绕过这些校验的独立上传入口。
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
task.files.agent = saved;
|
|
389
|
+
await task.persist();
|
|
390
|
+
const published = await this.deps.submitAgentMdRaw(
|
|
391
|
+
task.sub_aid, saved.raw, saved.condition,
|
|
392
|
+
);
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## 11. 三种流程与 self-owner
|
|
396
|
+
|
|
397
|
+
| 流程 | 默认编排和最终依据 |
|
|
398
|
+
| --- | --- |
|
|
399
|
+
| 绑定 | 发起方保存意图和 request;接收方保存同意;owner 用 declareSubaid 发布 `v+1`;sub 用 declareOwneraid 自签 PUT;NS 验收后各端新鲜确认。 |
|
|
400
|
+
| 释放 | 原 owner 用 revokeSubaid 条件发布当前版本 `v` 的 release;NS 动态确认 `v/unlocked`,不另存关系或递增版本;通知 sub,字段与旧文件分别清理。真实权威不存在同样可确认该声明释放。 |
|
|
401
|
+
| 转移 | 原 owner 发 request;新 owner 与 sub 同意;原 owner 用 transferOwneraid 发布旧版本授权;新 owner 发布 `v+1` declare;sub 自签提交 `v+1`;NS 条件提交目标名片,随后从两份权威材料确认及条件清理旧文件,不另存关系或证据表。 |
|
|
402
|
+
|
|
403
|
+
审批阶段不写协议文件。默认编排给出易恢复的步骤顺序,协议本身允许各方乱序独立发布;NS 不维护跨方 prepare 或等待任务。转移授权绑定旧关系、指定新 owner、目标版本及有效期,不依赖另外两方预交目标文件或摘要。TypeScript 首次授权采用本地 3600 秒,持久保存实际 expires_at;恢复不延长它。
|
|
404
|
+
|
|
405
|
+
释放后的 sub 自动清理只使用本端明确 accept、包含 sub 角色、本人已签 agent 中 owner/sub/被释放的完整 statement(含 declaration_id、版本)完全匹配的原 bind/transfer 记录;转移历史匹配目标 owner。收到 release 通知时,因发布响应丢失仍 pending 的原任务也可提供该授权;无控制消息时,仅已完成历史任务的恢复路径触发自动清理,即使没有 relation.confirmed,也须新鲜核对权威释放事实。清理原件、全文摘要和原 CAS 单独持久保存,保持历史 completed 及原完成证据。字段已清空时不签写;响应丢失复用原件/条件,全文、ETag及已知提交 ETag 均对应原清理提交时只观察确认,冲突保留待办。没有该授权且仍有旧字段时,任务保持 pending 并发 action_required;acceptOwnershipRequest/rejectOwnershipRequest 不接受 release 任务,应用可通过已有名片 API 明确签署清理文件。
|
|
406
|
+
|
|
407
|
+
### 11.1 EC CLI 创建 sub 后,由 human owner 确认绑定
|
|
408
|
+
|
|
409
|
+
以下是供 EC CLI 开发者接入的目标流程,EC CLI 当前尚未集成 Ownership。应用需在 Evolcore 一侧创建、加载 sub 身份,再由该 sub 调用 `bindOwneraid(ownerAid)`;先读取当前 agent.md 或确认其可靠不存在,再按原条件建立声明;不能覆盖已有关系或失败稿。sub 的主动发起已保存其同意,不需要没有 UI 的 sub 再交互确认;human owner 的 App 收到 `ownership.request` 后才展示确认。CLI 创建身份的具体命令属于上层应用,SDK 不定义 `ec` 命令。
|
|
410
|
+
|
|
411
|
+
```mermaid
|
|
412
|
+
sequenceDiagram
|
|
413
|
+
participant EC as EC CLI / Evolcore(待接入)
|
|
414
|
+
participant S as sub SDK(无 UI)
|
|
415
|
+
participant O as human owner App / SDK
|
|
416
|
+
participant ST as owner Storage
|
|
417
|
+
participant NS as sub NS
|
|
418
|
+
EC->>S: 创建并加载 sub 身份
|
|
419
|
+
EC->>S: bindOwneraid(ownerAid)
|
|
420
|
+
S->>NS: 新鲜读取 agent.md 或可靠 404,核对基线及版本 v
|
|
421
|
+
S->>S: CAS 保存发起同意、原件和 outbox
|
|
422
|
+
S->>O: 加密 P2P bind.request
|
|
423
|
+
O->>O: inbox 持久化,回源核验后发 ownership.request
|
|
424
|
+
alt human 拒绝
|
|
425
|
+
O->>O: rejectOwnershipRequest;CAS 保存拒绝与回复
|
|
426
|
+
O->>S: bind.reject;双方结束审批,不写关系文件
|
|
427
|
+
else human 点击确认
|
|
428
|
+
O->>O: acceptOwnershipRequest;CAS 保存同意与回复
|
|
429
|
+
O->>S: bind.accept
|
|
430
|
+
O->>ST: declareSubaid:本人签署并原子发布 v+1 owner.md
|
|
431
|
+
O->>NS: SDK 后续推进/确认时新鲜检查
|
|
432
|
+
NS-->>O: sub 尚无匹配声明,不建立新锁
|
|
433
|
+
O->>S: owner.ready
|
|
434
|
+
S->>ST: 权威读取并验证目标 owner.md
|
|
435
|
+
S->>S: declareOwneraid:本人签署,保存原字节与原 CAS
|
|
436
|
+
S->>NS: 以 sub 身份条件 PUT agent.md
|
|
437
|
+
NS->>ST: 新鲜验证 owner 材料、证书与当前关系
|
|
438
|
+
NS->>NS: CAS 保存完整 agent.md,按原机制同步副本
|
|
439
|
+
S->>NS: 提交后再次新鲜检查
|
|
440
|
+
NS-->>S: 双文件共识成立,locked
|
|
441
|
+
S->>S: 新鲜确认共识及本人原件,保存 completed
|
|
442
|
+
S->>O: relation.confirmed
|
|
443
|
+
O->>O: 自行新鲜核查共识与本人原件后 completed
|
|
444
|
+
end
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
任一步骤遇到冲突、未知材料或服务失败,按第 10 节保留原任务或停止旧写入;`owner.ready`、消息 ACK 和图中通知均不替代新鲜共识。反向 `bindSubaid` 仍需要 sub 应用或策略明确审批;上述无人值守常规流程优先由 sub 发起。
|
|
448
|
+
|
|
449
|
+
### 11.2 owner 释放与 sub 清理
|
|
450
|
+
|
|
451
|
+
```mermaid
|
|
452
|
+
flowchart TD
|
|
453
|
+
A[原 owner 调用 releaseSubaid] --> B[新鲜确认本人旧关系 v;保存任务与原件]
|
|
454
|
+
B --> C[revokeSubaid:签署并原子发布同版本 release]
|
|
455
|
+
C --> D[新鲜读取两份权威材料,确认 released / v / unlocked]
|
|
456
|
+
D -->|无法确认| W[保留 release 与确认待办,恢复后重查]
|
|
457
|
+
W --> D
|
|
458
|
+
D -->|确认本任务| E[原 owner 保存 completed;sub 离线不阻碍]
|
|
459
|
+
E --> F[持久 outbox:relation.confirmed → sub]
|
|
460
|
+
F --> G[sub 回源确认释放;查找本人已同意的匹配原任务]
|
|
461
|
+
G --> H{有完整声明、原件和原 CAS 匹配的清理授权吗}
|
|
462
|
+
H -->|没有且仍有旧字段| I[pending;ownership.action_required;由应用明确签署清理]
|
|
463
|
+
H -->|有| J[revokeOwneraid:保存清理原件,以 sub 身份条件 PUT]
|
|
464
|
+
J --> K[NS 保存清理后的 agent.md:unbound / 0,并同步副本]
|
|
465
|
+
K --> L[sub.cleaned;owner 回源核对后更新清理进度]
|
|
466
|
+
E --> M[旧 release 延迟删除:先复核当前 NS 与本任务完整原件]
|
|
467
|
+
M -->|文件或当前关系已变化| N[停止旧删除,保留结果与待办]
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
有效权威不存在也可支持 `released/v`,但超时、无权限或普通下载 404 不属于权威不存在。若 sub 字段已清空,只能按第 10 节的本任务原件及提交证据观察确认,不能仅凭 `unbound/0` 认领完成;不再签写空字段。release 不属于可用 accept/reject 审批的任务。
|
|
471
|
+
|
|
472
|
+
### 11.3 三方连续转移
|
|
473
|
+
|
|
474
|
+
```mermaid
|
|
475
|
+
flowchart TD
|
|
476
|
+
A[原 owner:transferSubaid,保存原关系 v 与转移意图] --> B[持久并发送 transfer.request 给新 owner 和 sub]
|
|
477
|
+
B --> C[新 owner App:核验请求后明确同意或拒绝]
|
|
478
|
+
B --> D[sub 应用或明确配置的策略:核验后同意或拒绝]
|
|
479
|
+
C -->|拒绝| R[transfer.reject;停止未提交任务,原关系保持]
|
|
480
|
+
D -->|拒绝| R
|
|
481
|
+
C -->|同意| E[CAS 保存决定与 transfer.accept]
|
|
482
|
+
D -->|同意| F[CAS 保存决定与 transfer.accept]
|
|
483
|
+
E --> G{原 owner 收齐唯一参与 AID 的同意吗}
|
|
484
|
+
F --> G
|
|
485
|
+
G -->|未收齐| H[等待,不发布授权或目标文件]
|
|
486
|
+
G -->|已收齐| I[复核原件;固定期限及完整签名字节,先 CAS 持久化]
|
|
487
|
+
I --> J[transferOwneraid 发布旧版本授权;编排新鲜核查后发送 transfer.ready]
|
|
488
|
+
J --> K[新 owner 核对本端同意、授权目标、版本与未过期]
|
|
489
|
+
J --> L[sub 核对本端同意及授权,等待目标声明]
|
|
490
|
+
K --> M[declareSubaid:新 owner 自签原子发布 v+1 owner.md]
|
|
491
|
+
M --> N[新 owner 触发 NS 新鲜检查;owner.ready;sub 回源读取目标 owner.md]
|
|
492
|
+
L --> N
|
|
493
|
+
N --> O[declareOwneraid:sub 自签并保存原字节与原 CAS]
|
|
494
|
+
O --> P[以 sub 身份条件 PUT;NS 复核三方材料与期限]
|
|
495
|
+
P -->|通过| Q[CAS 保存目标关系文件 v+1;锁定新关系;sub 提交后新鲜回读]
|
|
496
|
+
P -->|不可确认或冲突| W[原任务保留或停止;不换原件、延期或 release 再 bind]
|
|
497
|
+
Q --> T[sub 新鲜确认目标与本人原件后 completed]
|
|
498
|
+
T --> U[relation.confirmed;各端自行回源确认后 completed]
|
|
499
|
+
U --> V[原 owner 复核当前 NS 及本任务完整旧原件后清理]
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
sub 没有 UI 不表示默认同意所有转移;它仍须由应用或既有明确策略决定。授权期限仅限制新转移提交,过期本身不解除旧关系;已经提交的目标保持,通知或旧文件清理失败分别恢复。
|
|
503
|
+
|
|
504
|
+
### 11.4 sub 的清理授权与 self-owner
|
|
505
|
+
|
|
506
|
+
释放后的 sub 自动清理只使用本端明确 accept、包含 sub 角色且本人已签关系文件中 owner/sub/被释放的完整 statement(含 declaration_id、版本)完全匹配的原 bind/transfer 记录;转移历史匹配目标 owner。收到 release 通知时,因发布响应丢失仍 pending 的原任务也可提供该授权;无控制消息时,仅已完成历史任务的恢复路径触发自动清理,即使没有 relation.confirmed,也须新鲜核对权威释放事实。清理原件、全文摘要和原 CAS 单独持久保存,保持历史 completed 及原完成证据。字段已清空时不签写,可记录当前已清理的观察进度;Go SubCleaned 也可表示这一观察,单独不能证明本任务执行清理或首次完成 release,后者仍须第 10.1 节的原件关联证据。响应丢失复用原件/条件,全文、ETag及已知提交 ETag 均对应原清理提交时只观察确认,冲突保留待办。没有该授权且仍有旧字段时,任务保持 pending 并发 action_required;acceptOwnershipRequest/rejectOwnershipRequest 不接受 release 任务,应用需明确关系资源的清理意愿;应用可按既有名片 API 明确自签清理,仍须核验释放事实及原 CAS。
|
|
507
|
+
|
|
508
|
+
若新鲜有效关系文件的关系字段已经清空,sub 只有以本任务持久清理原件、摘要及原 CAS,或本人明确 accept 的匹配原 bind/transfer.release_cleanup,精确核对当前 NS 原文、摘要、ETag及已知提交 ETag 后,才可仅观察本任务清理完成,无需再签写或审批;空字段本身不证明本任务完成或本端同意。原 owner 的释放任务可早已 completed,历史绑定/转移 completed 也保持原记录;当前关系检查返回 `unbound`,响应版本为 `0`,任务版本仍为 `v`。NS 不保存释放终局或历史版本上界;后续绑定和旧任务恢复须重新核对完整文件与原条件。
|
|
509
|
+
|
|
510
|
+
self-owner 为 owner_aid 等于 sub_aid,同一身份按两个角色分别签自己的 owner.md 和 agent.md;不减少文件、签名或 NS 验收要求,不添加特殊状态。应用本端发起可覆盖本端角色意愿,SDK 不向自己发 P2P;转移中 sub 与新 owner 重合时合并对同一 AID 的请求和决定。
|
|
511
|
+
|
|
512
|
+
self-owner → 外部 owner 仍需当前身份的原 owner 授权及目标 agent.md,外部新 owner 的目标 owner.md;外部 owner → self-owner 仍需原外部 owner 授权及 sub 的两个目标文件。原/新 owner 相同不是有效转移;已有外部锁不能凭两个 self-owner 文件绕过。
|
|
513
|
+
|
|
514
|
+
## 12. 普通/群名片、注册与兼容边界
|
|
515
|
+
|
|
516
|
+
普通 2.1 名片更新保留当前完整 owner 和 statement,使用新鲜 NS 原 ETag 与本人当前签名上传,不递增关系版本。已有普通 legacy owner-only、proof 或 2.0 关系的普通名片入口允许仅更新正文;owner、ownership、ownership_proof、ownership_release 的字段存在性、类型和值必须完整保留,新 metadata 和外层签名执行当前上传规则,不由普通更新新建旧绑定或自动迁入 2.1。旧 SDK 的 owner 变更另走隔离的 legacy RPC/operation ID 兼容入口,只激活旧 `ownership_proof`,不覆盖已存现代声明,不生成 2.1 lock/version/consensus。NS 接受名片后再通过受限可信 nameservice 内部 `storage.put_object` 原子同步 `{sub_aid}:/agent.md` 原始签名副本,无需客户端 HTTP 会话;内部镜像只能写本域 `default/agent.md`,不能写删 `owner.md`。副本失败不回滚关系。正文普通更新会改变文件 ETag,即使关系版本不变也要重新同步;副本不能替代 NS 作为授权依据。
|
|
517
|
+
|
|
518
|
+
四 SDK 普通 `downloadAgentMd`/`download_agent_md` 及文件验签兼容历史 aid-only、无 frontmatter 的已签正文、实体自签及旧关系材料;历史尾签允许 16/64 hex 的 DER/SPKI 指纹、前缀省略、冒号和大小写,时间戳前导零及 CN 去首尾空白/忽略大小写仅适用于 agent.md 历史读取。签名原字节、实际 signer、指纹、证书链及签署时间仍须验证;现代 Group/Org 即使在兼容读取中也要求严格完整 DER 证书指纹、owner 与 entity_cert_fingerprint,主签 cert_fingerprint 必须匹配实体指纹,已出现但无效的指纹不得回退 legacy。旧 Group 读取仅限 type=group、恰一个签名块、无 entity_cert_fingerprint 且主 signer_aid 缺省或等于实体 AID;Org 不开放,上传不采用这些读取宽松规则。读取兼容的证书查询/缓存与通用 Auth、消息及当前 Ownership 验证隔离。`verification.ownership_status` 保留 legacy proof 展示语义,不是 2.1 新鲜共识或授权结果;文件验签成功不代表当前关系,仍须调用 `checkOwnershipConsensus` 及本语言对应方法,业务执行端自行新鲜授权。
|
|
519
|
+
|
|
520
|
+
普通名片候选先通过本地 schema/外层签名验证,在首次远端 preflight 前独立持久保存私有 `local_draft_content`;不覆盖远端 content/ETag。持有本地私钥的自有身份默认 resolve 优先该稿,返回 unverified、in_sync=false、source.agent_md_fetched=false;显式 download/forceRefresh 仍读取远端权威内容并保留草稿,服务端确认对应候选提交成功后才清稿。失败稿仅本地保留,普通 initial 失败稿同样需要应用显式重试;重连即使发现普通 pending 也不自动重传。`AgentMdManager._uploadPrepared` 取得可靠 NS 条件后,仍在 PUT 前持久保存 signedContent、pending_condition 和 pending_relation(原 owner、完整 statement、relation_version、lock)。显式重试既有 pending 时,`resumePendingUpload` **先检查持久原条件,再读取远端**;缺条件保留原元数据及原错误,即使远端同字节也不清待办。2.1 正文更新核对原版本、锁、owner 和完整 statement;受限 legacy 正文更新另保存可信 base 全文、摘要、原 ETag 及全部旧关系快照,核对 base/candidate/remote 的存在性、类型和值,缺上下文不得补造。当前原文与提交 ETag 均对应原提交时只观察确认,否则仅在原 CAS 和关系仍匹配时重传原 blob,不换条件或重签;关系改变、远端消失或已被 2.1 接管则冲突并保留 pending。其它缺原上下文的旧待办仅允许版本 0/unlocked 的初始关系;Ownership 2.1 任务、消息及 outbox 仍由其既有机制恢复。
|
|
521
|
+
|
|
522
|
+
Group/Org 名片失败稿及 pending 保留实体命名空间中的完整多签原文、原 CAS、固定 owner 和实体证书指纹,由应用显式重试,post-connect/重连不隐式 PUT。重试先验证完整原件及当前 owner、状态和证书代际,原条件完整且同代际原文/ETag 已确认提交时只观察完成。转移、rekey 或解散后停止旧代际待办,不更换身份、指纹或条件重签。新 SDK 现代上传不再保存、刷新或检查额外 V2 授权及过期窗口;旧 V2 兼容入口仍按协议 §2.5 校验;普通文件签名与当前证书检查保留。专属 create/transfer 自身 checkpoint 恢复机制不变。
|
|
523
|
+
|
|
524
|
+
普通主体注册指定 owner 时,[aid-store.ts](../../ts/src/aid-store.ts) 先保存 `protocol=2.1` 的 registration_intent 和固定 operation_id;可靠初始化只发布本人无 owner 名片。初次连接由 `_resumeRegistrationIntent` 复用同一 operation_id 进入绑定,注册成功不是关系已成立。Group/Org 的身份准备由专属生命周期使用,不建立通用注册 owner 意图;已有关系/不可靠读取不能作为重新初始化或清空关系的依据。
|
|
525
|
+
|
|
526
|
+
旧 `ownership_proof/ownership_release`、只有 owner 字符串而缺少完整 2.1 statement 的文件不能自动降格为 unbound,也不能用旧 records 解锁。TypeScript `OwnershipFiles.verifyFile` 明确拒绝 legacy;`bindAid/bindOwner/releaseOwnership` 抛出带 `stringCode=unsupported_protocol` 的异常,`getOwner/getOwnershipStatus` 仍读取 legacy records,不能作为 2.1 当前关系查询。升级必须明确核验原权威事实,不借迁移清空版本或 owner 锁。
|
|
527
|
+
|
|
528
|
+
业务执行端仍须认证调用者、目标 sub、权限范围和新鲜共识,绑定 token/ACL 到完整关系声明及其版本并检查当前有效性;清理后版本可重复,不能单凭版本识别关系;客户端事件或布尔值不是授权证明。敏感操作执行前保存完整文件与验证证据。托管私钥和凭据交接由应用另行处理,NS 转移不自动撤销旧私钥、证书、token 的身份能力,也不代表业务交接已经完成。
|
|
529
|
+
|
|
530
|
+
## 13. 跨语言 TDD 与有序验收
|
|
531
|
+
|
|
532
|
+
移植从共同向量开始,再接文件层、持久 Workflow 和真实 Client 通路;先用失败断言固定边界,再实现该边界。不要只用当前语言生成的数据验证自己,也不要以纯 Workflow mock 代替实际收件/连接接线。
|
|
533
|
+
|
|
534
|
+
共同文件是 [tests/vectors/ownership_v21/vectors.json](../../tests/vectors/ownership_v21/vectors.json),测试向量位于顶层 `documents` 键下;当前包含 **119 个完整文件、51 个消息、24 个六态入口**,固定 verification_time 为 `1791524400`,材料范围标为静态单元夹具。`raw_base64` 必须解码为完整原文;文件解析预期与完整验签预期分别检查。
|
|
535
|
+
|
|
536
|
+
TypeScript 消费入口为 [tests/conformance/ownership_v21.test.ts](../../ts/tests/conformance/ownership_v21.test.ts);内部行为参考 [ownership-v21.test.ts](../../ts/tests/unit/ownership-v21.test.ts)、[ownership-workflow.test.ts](../../ts/tests/unit/ownership-workflow.test.ts)、[client-agent-md-api.test.ts](../../ts/tests/unit/client-agent-md-api.test.ts)。随机 ECDSA 不要求各端生成相同签名值,要求签名格式、覆盖字节及跨端验签一致。
|
|
537
|
+
|
|
538
|
+
| 验收顺序 | 完成后才能进入下一项的证据 |
|
|
539
|
+
| --- | --- |
|
|
540
|
+
| 1. 原始文件与密码 | 双角色、严格 JSON/YAML、字节大小、TAG、整数边界、DER 与完整文件签名;坏材料分类一致。 |
|
|
541
|
+
| 2. 权威适配 | NS 原条件/可靠 404,Storage 当前完整文件与存在性再读、可信来源,精确证书及当前吊销状态;故障不解锁。 |
|
|
542
|
+
| 3. 文件方法与六态 | 自签自传、五个内部步骤、绑定/release/权威删除/连续转移/self-owner;前后 NS 一致性。 |
|
|
543
|
+
| 4. 持久 Workflow | 每任务 CAS、审批与 outbox 原子、未决不自动批准、角色去重、固定期限、损坏完成态拒绝。 |
|
|
544
|
+
| 5. 实际 Client 通路 | 解密 JSON 原文保留、push/pull/reconnect 统一拦截、持久成功前零队列移除/游标/ACK;普通与群待办隔离。 |
|
|
545
|
+
| 6. 中断窗口 | 保存后发送前/后、owner/sub 提交后失响应、release 待确认、后续代际、过期、停止前后;原字节与原条件不变。 |
|
|
546
|
+
| 7. 网络互通 | 单域集成 → 单域 E2E → cross-sdk → pub/cn 双向联邦;轮换 sub/原 owner/新 owner,观察真实 NS、Storage、CA 和凭据身份。 |
|
|
547
|
+
| 8. 服务持久与副本 | 真实数据库中的名片原文、CAS 与同步待办原子一致;服务恢复后从两份权威材料验证关系,副本最终逐字节一致;与 SDK 恢复证据分开。 |
|
|
548
|
+
|
|
549
|
+
单元测试可以并行,但每项使用隔离的数据库、AID 和目录;共用 Docker 环境仅一个测试名额,按上表的网络顺序串行执行。服务代码改变后,先重新构建、更新对应容器并核对真实运行版本,再运行受影响的网络验收;不能用旧容器结果验收新服务代码。
|
|
550
|
+
|
|
551
|
+
运行到失败立即停止,保存用例 ID、任务固定上下文、已通过阶段、NS 版本/ETag、文件摘要及日志;修复后先重跑失败项,再从未完成阶段继续。已通过且未受修改影响的项目不重复执行。现有 runner 不存在通用 resume 参数,按 [TDD 第 11 节](Ownership2.1-TDD分阶段实施计划.md#11-测试命令与续跑方法) 的检查点方法续跑;测试环境和命令见 [AUN 测试运行指南](../aun测试运行指南.md)、[分布式指南](../aun分布式测试运行指南.md)、[公网指南](../aun公网测试运行指南.md)。对外地址使用 `{svc}.{issuer}`,Windows Python 使用 `-X utf8`。
|
|
552
|
+
|
|
553
|
+
当前通过项及未完成/受限项只以 [TDD 第 13.4 节](Ownership2.1-TDD分阶段实施计划.md#134-测试与失败续跑账本)、[第 13.6 节](Ownership2.1-TDD分阶段实施计划.md#136-四-sdk-一致性检查点) 和 [第 13.7 节复审修复验收](Ownership2.1-TDD分阶段实施计划.md#137-2026-10-11-本轮复审修复验收)及[第 13.8 节复查更正与修复边界](Ownership2.1-TDD分阶段实施计划.md#138-2026-10-13-复查更正与修复边界)的具体证据为准:共同向量和本地定向通过不表示真实浏览器联网、当前完整 JS bundle 互操作或所有 SDK 跨 PID 强杀恢复均已通过。SQLite/IndexedDB 连接重开、新建 Workflow、服务独立恢复进程和真正进程重启分别记录。新移植 SDK 应提供自己的目标平台与运行版本证据,不能继承参考实现尚未覆盖的环境结论。
|