@agentunion/fastaun 0.5.35 → 0.5.37

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 (49) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/_packed_docs/CHANGELOG.md +40 -0
  3. package/_packed_docs/INDEX.md +10 -3
  4. package/_packed_docs/sdk/0.5.36-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +130 -0
  5. package/_packed_docs/sdk/0.5.36-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +176 -0
  6. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +6 -6
  7. package/_packed_docs/sdk/INDEX.md +15 -10
  8. package/dist/agent-md.d.ts +2 -1
  9. package/dist/agent-md.js +34 -6
  10. package/dist/agent-md.js.map +1 -1
  11. package/dist/aid-store.js +5 -1
  12. package/dist/aid-store.js.map +1 -1
  13. package/dist/auth.js +5 -2
  14. package/dist/auth.js.map +1 -1
  15. package/dist/client/control-messages.js +4 -2
  16. package/dist/client/control-messages.js.map +1 -1
  17. package/dist/client/delivery.d.ts +2 -0
  18. package/dist/client/delivery.js +111 -40
  19. package/dist/client/delivery.js.map +1 -1
  20. package/dist/client/lifecycle.js +1 -1
  21. package/dist/client/lifecycle.js.map +1 -1
  22. package/dist/client/rpc-pipeline.d.ts +3 -0
  23. package/dist/client/rpc-pipeline.js +45 -3
  24. package/dist/client/rpc-pipeline.js.map +1 -1
  25. package/dist/client/v2-e2ee.js +16 -8
  26. package/dist/client/v2-e2ee.js.map +1 -1
  27. package/dist/client.js +90 -51
  28. package/dist/client.js.map +1 -1
  29. package/dist/ownership-v21.d.ts +2 -1
  30. package/dist/ownership-v21.js +19 -9
  31. package/dist/ownership-v21.js.map +1 -1
  32. package/dist/pubsub/binding.d.ts +2 -6
  33. package/dist/pubsub/binding.js +58 -61
  34. package/dist/pubsub/binding.js.map +1 -1
  35. package/dist/pubsub/channel.js +3 -3
  36. package/dist/pubsub/channel.js.map +1 -1
  37. package/dist/pubsub/client.js +3 -4
  38. package/dist/pubsub/client.js.map +1 -1
  39. package/dist/pubsub/service.js +1 -1
  40. package/dist/pubsub/service.js.map +1 -1
  41. package/dist/secret-store/file-store.js +8 -1
  42. package/dist/secret-store/file-store.js.map +1 -1
  43. package/dist/tools/cross-sdk-agent.d.ts +1 -1
  44. package/dist/udp-standby.d.ts +0 -1
  45. package/dist/udp-standby.js +10 -13
  46. package/dist/udp-standby.js.map +1 -1
  47. package/dist/version.d.ts +1 -1
  48. package/dist/version.js +1 -1
  49. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  # AUN SDK 文档索引
2
2
 
3
- > 当前四 SDK 源码版本为 **0.5.35**;最新接入与实现见 [0.5.35 应用集成指南](0.5.35-SDK应用集成指南.md)、[开发与移植指南](0.5.35-SDK开发与移植指南.md),源码增量见 [parity 0.5.35](../../python/CHANGES_FOR_PARITY.md#v0535) 和四 SDK CHANGELOG,基础手册、RPC 手册与 0.5.34 历史专题继续提供接入说明。`0.5.xx-*` 为版本增量专题,CHANGELOG 保留历史记录;完整事件协议另见发布订阅专题。三层索引:Layer 1 文档地图,Layer 2 主题交叉索引,Layer 3 单篇摘要。
3
+ > 当前四 SDK 源码版本为 **0.5.36**;本版接入与实现见 [0.5.36 应用集成指南](0.5.36-SDK应用集成指南.md)、[开发与移植指南](0.5.36-SDK开发与移植指南.md),源码增量见 [parity 0.5.36](../../python/CHANGES_FOR_PARITY.md#v0536) 和四 SDK CHANGELOG;[0.5.35 应用集成指南](0.5.35-SDK应用集成指南.md)、[开发与移植指南](0.5.35-SDK开发与移植指南.md)与 [parity 0.5.35](../../python/CHANGES_FOR_PARITY.md#v0535) 保留历史记录,基础手册、RPC 手册与 0.5.34 历史专题继续提供接入说明。`0.5.xx-*` 为版本增量专题,CHANGELOG 保留历史记录;完整事件协议另见发布订阅专题。三层索引:Layer 1 文档地图,Layer 2 主题交叉索引,Layer 3 单篇摘要。
4
4
 
5
5
  ---
6
6
 
@@ -16,6 +16,7 @@
16
16
  | [0.5.22 SDK 开发与移植指南](0.5.22-SDK开发与移植指南.md) | 后台退避 · 群状态 · 两种绑定与 Stage/CAS · 消息内部消费 · 撤销同步 · 组织恢复及配套服务修复 · 默认读缓存 · Rust 清单 |
17
17
  | [0.5.24 SDK 应用集成指南](0.5.24-SDK应用集成指南.md) | 当前身份与消息接入 · 无任务 Ownership · local 双/三身份编排 · resolve 与文件缓存 · 凭证组织 · 升级 |
18
18
  | [0.5.24 SDK 开发与移植指南](0.5.24-SDK开发与移植指南.md) | peer/batch 提交 · NS 事实与远端 CAS · local 短连接 · 观察与 PKI 缓存 · 持久化边界 · 语言差异和验收 |
19
+ | [0.5.36 应用集成指南](0.5.36-SDK应用集成指南.md)、[开发与移植指南](0.5.36-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0536);四 SDK CHANGELOG | 事件大小/令牌桶、共识持久缓存与 force、摘要观察失效、历史验签/新签、UDP 租约、Node/Go 差异及单实例边界 |
19
20
  | [0.5.35 应用集成指南](0.5.35-SDK应用集成指南.md)、[开发与移植指南](0.5.35-SDK开发与移植指南.md);[0.5.35 变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0535);[0.5.34 历史应用集成指南](0.5.34-SDK应用集成指南.md)、[开发与移植指南](0.5.34-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0534);[Python](../../python/CHANGELOG.md)、[Go](../../go/CHANGELOG.md)、[TS](../../ts/CHANGELOG.md)、[JS](../../js/CHANGELOG.md) CHANGELOG | 对照已发布 0.5.34:通配订阅/发布者过滤、本地收发、后台 ACK、Echo v3.2、三端 UDP/原生 Mail、语言专属修复、单实例及验证边界 |
20
21
  | [0.5.32 应用集成指南](0.5.32-SDK应用集成指南.md)、[开发与移植指南](0.5.32-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0532);[Python](../../python/CHANGELOG.md)、[Go](../../go/CHANGELOG.md)、[TS](../../ts/CHANGELOG.md)、[JS](../../js/CHANGELOG.md) CHANGELOG | 对照已发布 0.5.31:EventService · 设备租约 · 有界背压 · 消息调度 · 限流缓存 · Ownership · 已有验证范围 |
21
22
  | [0.5.30 SDK 应用集成指南](0.5.30-SDK应用集成指南.md)、[开发与移植指南](0.5.30-SDK开发与移植指南.md)、[变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0530--控制流按需恢复与-sdk-行为对齐未发布) | 按需控制流恢复 · observer.forward 本地字段剥离 · human owner 本地 Ownership · Storage 版本预检 · 内部 RPC 边界 |
@@ -84,11 +85,13 @@
84
85
  - 当前身份与消息接入、无任务 Ownership、两个 local 场景、名片及文件缓存、凭证组织与升级 → [应用集成指南](0.5.24-SDK应用集成指南.md)
85
86
  - 三主体分层、提交/ACK、NS 事实和远端 CAS、local 身份隔离、缓存新鲜度、语言差异与验收 → [开发与移植指南](0.5.24-SDK开发与移植指南.md)
86
87
 
87
- ### 0.5.35 增量与 0.5.34 接入专题
88
+ ### 0.5.36 增量与历史接入专题
89
+
90
+ - 0.5.36 应用升级、大事件、共识重启复用、证书与 UDP → [应用集成指南](0.5.36-SDK应用集成指南.md);令牌桶、缓存与失效、NS 配套、验签/新签、UDP 状态机及四端落点 → [开发与移植指南](0.5.36-SDK开发与移植指南.md);源码与已有验证 → [parity 0.5.36](../../python/CHANGES_FOR_PARITY.md#v0536) 和四 SDK CHANGELOG
88
91
 
89
92
  - 0.5.35 应用升级、订阅过滤、ACK/恢复、Echo、UDP/Mail 接线与验收 → [应用集成指南](0.5.35-SDK应用集成指南.md);0.5.34 多角色、持久化、durable outbox、实时目录及 Group FS/Service Proxy → [历史应用指南](0.5.34-SDK应用集成指南.md)
90
93
  - 0.5.35 四端共同契约、可信发布者、本地路径、ACK 任务、UDP 心跳和三端 Mail 差异 → [开发与移植指南](0.5.35-SDK开发与移植指南.md);0.5.34 存储、队列恢复、条件 ACL、Group FS/Storage/Proxy → [历史移植指南](0.5.34-SDK开发与移植指南.md)
91
- - 当前源码差异、三端 UDP/Mail、单实例发布与验证边界 → [parity 0.5.35](../../python/CHANGES_FOR_PARITY.md#v0535);[0.5.34 parity](../../python/CHANGES_FOR_PARITY.md#v0534) 保留历史记录
94
+ - 0.5.35 源码差异、三端 UDP/Mail、单实例发布与验证边界 → [parity 0.5.35](../../python/CHANGES_FOR_PARITY.md#v0535);[0.5.34 parity](../../python/CHANGES_FOR_PARITY.md#v0534) 保留历史记录
92
95
 
93
96
  - 0.5.32 历史应用调用与升级影响 → [应用集成指南](0.5.32-SDK应用集成指南.md);四端契约、内部流程及验收 → [开发与移植指南](0.5.32-SDK开发与移植指南.md);源码差异与已有验证 → [parity](../../python/CHANGES_FOR_PARITY.md#v0532)。EventService 的当前增量见上面的 0.5.34 专题。
94
97
  - 0.5.30 应用行为、主动 Pull 边界、本地 Ownership、Storage 版本及内部 RPC → [应用指南](0.5.30-SDK应用集成指南.md);控制恢复、转发净化、YAML 与版本预检的四端契约 → [开发与移植指南](0.5.30-SDK开发与移植指南.md);验证范围见 [parity](../../python/CHANGES_FOR_PARITY.md#v0530--控制流按需恢复与-sdk-行为对齐未发布)。
@@ -194,9 +197,11 @@ TypeScript 身份与消息接线、Ownership 审批恢复、resolve、默认缓
194
197
 
195
198
  定义消息 peer/batch/Gate、Ownership NS 事实和远端 CAS、Stage、local 专属 slot 与身份代际、展示及文件缓存、PKI 和 Credential 查询新鲜度、组织 checkpoint。列出四端兼容差异、Rust 核查与分层验收,不将已有专项证据等同完整发布验证。
196
199
 
197
- ### 0.5.35 变更与 0.5.34 历史指南
200
+ ### 0.5.36 应用集成、开发移植与历史指南
201
+
202
+ [0.5.36 应用指南](0.5.36-SDK应用集成指南.md):范围 L7-19、事件大小/速率 L20-42、共识复用与失效 L43-76、证书 L77-87、UDP L88-107、Node/Go L108-117、验收 L118-130;[开发与移植指南](0.5.36-SDK开发与移植指南.md):契约 L7-19、事件 L20-50、持久共识 L51-85、观察失效 L86-102、NS L103-112、历史验签/新签 L113-128、UDP L129-153、语言专属 L154-161、回归 L162-176。[0.5.36 变更与跨端对齐](../../python/CHANGES_FOR_PARITY.md#v0536) L15-78:基线/矩阵 L17-30、事件大小与速率 L32-38、共识缓存、观察及证书验签 L40-54、UDP/Node/Go 差异 L56-61、配套服务与边界 L63-67、核验 L69-78。
198
203
 
199
- [0.5.35 应用指南](0.5.35-SDK应用集成指南.md):范围 L7-20、EventService L21-61、ACK/恢复 L62-77、Echo L78-94、UDP L95-124、Mail L125-163、语言专属 L164-177、验收 L178-189;[开发与移植指南](0.5.35-SDK开发与移植指南.md):职责 L7-17、事件契约 L18-63、ACK/同步 L64-83、Echo L84-99、UDP L100-136、Mail L137-172、语言落点 L173-184、回归 L185-204。 [当前 0.5.35 parity](../../python/CHANGES_FOR_PARITY.md#v0535) L15-90 覆盖通配/过滤、本地事件路径、后台 ACK、Echo、三端 UDP/原生 Mail、Python/Go 专属变化及单实例发布边界。两份 0.5.34 历史专题分别覆盖应用接入和四端实现:EventService 多角色共存、目录与订阅合并恢复、发布 durable outbox、按事件汇总的实时目录,以及 Storage 条件 ACL、Group FS、Service Proxy 和弹性补拉。配套 parity 章节记录四端落点、服务依赖和未执行的部署/跨域验收边界。
204
+ [0.5.35 应用指南](0.5.35-SDK应用集成指南.md):范围 L7-20、EventService L21-61、ACK/恢复 L62-77、Echo L78-94、UDP L95-124、Mail L125-163、语言专属 L164-177、验收 L178-189;[开发与移植指南](0.5.35-SDK开发与移植指南.md):职责 L7-17、事件契约 L18-63、ACK/同步 L64-83、Echo L84-99、UDP L100-136、Mail L137-172、语言落点 L173-184、回归 L185-204。 [历史 0.5.35 parity](../../python/CHANGES_FOR_PARITY.md#v0535) L84-159 覆盖通配/过滤、本地事件路径、后台 ACK、Echo、三端 UDP/原生 Mail、Python/Go 专属变化及单实例发布边界。两份 0.5.34 历史专题分别覆盖应用接入和四端实现:EventService 多角色共存、目录与订阅合并恢复、发布 durable outbox、按事件汇总的实时目录,以及 Storage 条件 ACL、Group FS、Service Proxy 和弹性补拉。配套 parity 章节记录四端落点、服务依赖和未执行的部署/跨域验收边界。
200
205
 
201
206
  ### 0.5.32 更新日志与跨端对齐
202
207
 
@@ -204,25 +209,25 @@ TypeScript 身份与消息接线、Ownership 审批恢复、resolve、默认缓
204
209
 
205
210
  [开发与移植指南](0.5.32-SDK开发与移植指南.md):基线/架构/四端入口 L5-53、单实例注册与状态 L54-107、鉴权和目录原子提交 L108-156、消息/公平背压/RPC预算 L157-227、恢复/限流/任务 L228-242、VFS并发失效 L243-288、四端落点/独有变化 L289-303、验收入口及已有证据 L304-319。
206
211
 
207
- 历史 [parity](../../python/CHANGES_FOR_PARITY.md#v0532) L242-339:发布基线 L246-251、门面 L252-267、授权与默认凭证存储 L268-283、消息及设备租约 L284-293、容量与公平调度 L294-310、通用消息恢复/限流 L311-319、Storage/Ownership L320-329、已有验证和发布边界 L330-339。四 SDK CHANGELOG 按各语言整理同一基线后的实际增量;0.5.31 已发布,较早章节保留历史语义。
212
+ 历史 [parity](../../python/CHANGES_FOR_PARITY.md#v0532) L311-408:发布基线 L315-320、门面 L321-336、授权与默认凭证存储 L337-352、消息及设备租约 L353-362、容量与公平调度 L363-379、通用消息恢复/限流 L380-388、Storage/Ownership L389-398、已有验证和发布边界 L399-408。四 SDK CHANGELOG 按各语言整理同一基线后的实际增量;0.5.31 已发布,较早章节保留历史语义。
208
213
 
209
214
  ### 0.5.30 更新日志与跨端对齐
210
215
 
211
216
  0.5.30 [应用指南](0.5.30-SDK应用集成指南.md):行为摘要 §1 L5-14、消息恢复 §2 L16-29、本地 Ownership §3 L31-43、Storage §4 L45-47、转发与风控 §5 L49-53、升级 §6 L55-61;[开发与移植指南](0.5.30-SDK开发与移植指南.md):跨端契约 §1 L5-14、控制恢复 §2 L16-29、observer.forward §3 L31-43、Ownership/YAML §4 L45-49、Storage §5 L51-55、内部 RPC 与差异 §6 L57-68。
212
217
 
213
- 历史 [0.5.30 变更与对齐清单](../../python/CHANGES_FOR_PARITY.md#v0530--控制流按需恢复与-sdk-行为对齐未发布) L411-452:按需恢复、转发净化、本地 Ownership、Storage 预检与当时的验证范围;当前增量见 [0.5.35 parity](../../python/CHANGES_FOR_PARITY.md#v0535)。
218
+ 历史 [0.5.30 变更与对齐清单](../../python/CHANGES_FOR_PARITY.md#v0530--控制流按需恢复与-sdk-行为对齐未发布) L480-521:按需恢复、转发净化、本地 Ownership、Storage 预检与当时的验证范围;当前增量见 [0.5.36 parity](../../python/CHANGES_FOR_PARITY.md#v0536)。
214
219
 
215
220
  ### 0.5.29 更新日志与跨端对齐
216
221
 
217
222
  0.5.29 [应用指南](0.5.29-SDK应用集成指南.md):接入与消息 §1—§2 L5-54、共识 §3 L55-80、resolve §4 L81-104、上传管理 §5 L105-145、缓存/业务 §6—§7 L146-167、升级 §8 L168-180;[开发与移植指南](0.5.29-SDK开发与移植指南.md):契约 §1—§2 L5-63、缓存/resolve §3—§4 L64-94、上传恢复 §5 L95-123、四端/继承 §6—§7 L124-151、核查 §8 L152-164。
218
223
 
219
- 历史 [0.5.29 变更与对齐清单](../../python/CHANGES_FOR_PARITY.md#v0529--共识查询缓存与普通上传未发布) L456-525:公共共识、ETag/resolve、普通上传、NS 配套与当时的验证范围;四端 CHANGELOG 提供接口摘要。
224
+ 历史 [0.5.29 变更与对齐清单](../../python/CHANGES_FOR_PARITY.md#v0529--共识查询缓存与普通上传未发布) L525-594:公共共识、ETag/resolve、普通上传、NS 配套与当时的验证范围;四端 CHANGELOG 提供接口摘要。
220
225
 
221
226
  ### 0.5.28 更新日志与跨端对齐
222
227
 
223
- 历史 0.5.28 [应用指南](0.5.28-SDK应用集成指南.md):身份/消息接入 §2—§3 L18-95、凭证/组织 §4—§5 L96-137、Storage/Ownership §6—§7 L138-186、Owner 通知 §8 L187-201、风控/升级 §9—§10 L202-228;[开发与移植指南](0.5.28-SDK开发与移植指南.md):上传/下载 schema §1 L7-36、非一致共识 fresh §2 L37-62、分类控制消息 §3 L63-108、Owner outbox §4 L109-121、风控 §5 L122-134、移植矩阵 §6 L135-146。 [历史对齐清单](../../python/CHANGES_FOR_PARITY.md#v0528--校验控制消息与风控未发布) L529-610 记录四端落点、已有测试入口及服务依赖/验收边界;公共共识流程以 0.5.29 为准。
228
+ 历史 0.5.28 [应用指南](0.5.28-SDK应用集成指南.md):身份/消息接入 §2—§3 L18-95、凭证/组织 §4—§5 L96-137、Storage/Ownership §6—§7 L138-186、Owner 通知 §8 L187-201、风控/升级 §9—§10 L202-228;[开发与移植指南](0.5.28-SDK开发与移植指南.md):上传/下载 schema §1 L7-36、非一致共识 fresh §2 L37-62、分类控制消息 §3 L63-108、Owner outbox §4 L109-121、风控 §5 L122-134、移植矩阵 §6 L135-146。 [历史对齐清单](../../python/CHANGES_FOR_PARITY.md#v0528--校验控制消息与风控未发布) L598-679 记录四端落点、已有测试入口及服务依赖/验收边界;公共共识流程以 0.5.29 为准。
224
229
 
225
- 0.5.27 [应用指南](0.5.27-SDK应用集成指南.md):身份/连接/消息迁移 §2—§3 L30-133,结构化 §4 L134-192/语义 §5 L193-349,组织与缓存 §6—§7 L350-388,升级 §8 L389-408;[开发与移植指南](0.5.27-SDK开发与移植指南.md):字节/签名 §2 L38-84,结构化 §3 L85-123/语义 §4 L124-297,组织 §5 L298-334,迁移交付 §6 L335-383,平台与回归 §7—§8 L384-410。 [变更与对齐清单](../../python/CHANGES_FOR_PARITY.md#v0527--相对于-v0525-基线的变更未发布) L614-728 对照 0.5.25 源码,说明语义凭证、消息证据、状态/Usage 恢复、Gateway 迁移、时间容错、组织及 CLI;四端 CHANGELOG 提供接口级摘要,parity 列出实现落点、语言差异和已有验证范围。0.5.26 仅为 TypeScript 根证书打包修正,旧版本章节保留历史记录。
230
+ 0.5.27 [应用指南](0.5.27-SDK应用集成指南.md):身份/连接/消息迁移 §2—§3 L30-133,结构化 §4 L134-192/语义 §5 L193-349,组织与缓存 §6—§7 L350-388,升级 §8 L389-408;[开发与移植指南](0.5.27-SDK开发与移植指南.md):字节/签名 §2 L38-84,结构化 §3 L85-123/语义 §4 L124-297,组织 §5 L298-334,迁移交付 §6 L335-383,平台与回归 §7—§8 L384-410。 [变更与对齐清单](../../python/CHANGES_FOR_PARITY.md#v0527--相对于-v0525-基线的变更未发布) L683-797 对照 0.5.25 源码,说明语义凭证、消息证据、状态/Usage 恢复、Gateway 迁移、时间容错、组织及 CLI;四端 CHANGELOG 提供接口级摘要,parity 列出实现落点、语言差异和已有验证范围。0.5.26 仅为 TypeScript 根证书打包修正,旧版本章节保留历史记录。
226
231
 
227
232
  ### CHANGELOG-0.5.6
228
233
 
@@ -136,7 +136,7 @@ export declare class AgentMdManager {
136
136
  etag: string;
137
137
  version: number;
138
138
  content_hash: string;
139
- }): boolean;
139
+ }, consensusContent?: string): boolean;
140
140
  localOwnershipConsensus(aid: string, record: Record<string, unknown> | null): OwnershipConsensusResult | null;
141
141
  private _clearConfirmedDraft;
142
142
  upload(content?: string | null, originalCondition?: OwnershipSavedFile['condition']): Promise<Record<string, unknown>>;
@@ -181,6 +181,7 @@ export declare class AgentMdManager {
181
181
  download(aid?: string | null, timeoutMs?: number): Promise<AgentMdDownloadResult>;
182
182
  check(aid: string, ttlDays?: number): Promise<AgentMdCheckResult>;
183
183
  observeMeta(aid: string, etag?: string, lastModified?: string, source?: string): void;
184
+ observeOwnershipMeta(aid: string, digest: string): void;
184
185
  observeRpcMeta(meta: Record<string, unknown>, ownerAid?: string | null): void;
185
186
  observeEnvelope(envelope: unknown): void;
186
187
  eventSnapshot(aid?: string | null): {
package/dist/agent-md.js CHANGED
@@ -376,6 +376,8 @@ export class AgentMdManager {
376
376
  }
377
377
  if (observation && (this.root !== observation.root || String(next.remote_etag ?? '') !== observation.etag || Number(next.observation_version ?? 0) !== observation.version))
378
378
  throw ownershipFailure('unavailable', 'agent.md observation changed during download', true);
379
+ if (typeof inputFields.remote_etag === 'string' && next.remote_etag !== inputFields.remote_etag && next.ownership_snapshot?.agent_md_etag !== inputFields.remote_etag)
380
+ delete next.ownership_snapshot;
379
381
  if (hasContent) {
380
382
  const content = String(inputFields.content ?? '');
381
383
  savedTo = this.writeContent(target, content);
@@ -423,7 +425,7 @@ export class AgentMdManager {
423
425
  saveRecord(aid, fields, observation) {
424
426
  return this._saveRecord(aid, fields, Object.prototype.hasOwnProperty.call(fields, 'local_draft_content'), observation);
425
427
  }
426
- cacheOwnershipSnapshot(aid, snapshot, observation) {
428
+ cacheOwnershipSnapshot(aid, snapshot, observation, consensusContent) {
427
429
  const target = this.safeAid(aid);
428
430
  return this._withRecordLock(target, () => {
429
431
  if (this.root !== observation.root)
@@ -434,6 +436,11 @@ export class AgentMdManager {
434
436
  if (String(record.remote_etag ?? '') !== observation.etag || Number(record.observation_version ?? 0) !== observation.version || hash !== observation.content_hash)
435
437
  return false;
436
438
  record.ownership_snapshot = JSON.parse(JSON.stringify(snapshot));
439
+ const ownerDigest = snapshot.owner_md_sha256;
440
+ if (ownerDigest)
441
+ record.remote_owner_md_sha256 = ownerDigest;
442
+ if (consensusContent !== undefined)
443
+ record.ownership_agent_md = consensusContent;
437
444
  record.updated_at = Date.now();
438
445
  this._writeRecordUnlocked(target, record);
439
446
  this._cache.set(target, { ...record, ...(content === null ? {} : { content, local_etag: `"${hash}"` }) });
@@ -442,16 +449,18 @@ export class AgentMdManager {
442
449
  }
443
450
  localOwnershipConsensus(aid, record) {
444
451
  const snapshot = record?.ownership_snapshot;
452
+ const content = record?.content ?? record?.ownership_agent_md;
445
453
  if (!snapshot || snapshot.status !== 'consensus' || snapshot.sub_aid !== aid || snapshot.lock !== 'locked'
446
- || !snapshot.agent_md_etag || snapshot.agent_md_etag !== record?.remote_etag || record.remote_status === 'missing'
447
- || typeof record.content !== 'string' || AgentMdManager.contentEtag(record.content).slice(1, -1) !== snapshot.agent_md_sha256)
454
+ || !snapshot.agent_md_etag || record?.remote_etag && snapshot.agent_md_etag !== record.remote_etag || record?.remote_status === 'missing'
455
+ || record?.remote_owner_md_sha256 && record.remote_owner_md_sha256 !== snapshot.owner_md_sha256
456
+ || typeof content !== 'string' || AgentMdManager.contentEtag(content).slice(1, -1) !== snapshot.agent_md_sha256)
448
457
  return null;
449
458
  try {
450
- const statement = parseOwnershipFile(record.content, 'agent', { expectedSubAid: aid }).statement;
459
+ const statement = parseOwnershipFile(content, 'agent', { expectedSubAid: aid }).statement;
451
460
  if (!statement || statement.owner_aid !== snapshot.owner_aid || statement.relation_version !== snapshot.relation_version)
452
461
  return null;
453
462
  return { status: 'consensus', sub_aid: aid, owner_aid: statement.owner_aid, relation_version: statement.relation_version,
454
- lock: 'locked', agent_md_etag: snapshot.agent_md_etag, agent_md_sha256: snapshot.agent_md_sha256 };
463
+ lock: 'locked', agent_md_etag: snapshot.agent_md_etag, agent_md_sha256: snapshot.agent_md_sha256, ...(snapshot.owner_md_sha256 ? { owner_md_sha256: snapshot.owner_md_sha256 } : {}) };
455
464
  }
456
465
  catch {
457
466
  return null;
@@ -549,7 +558,8 @@ export class AgentMdManager {
549
558
  if (!/^(?:0|[1-9][0-9]*)$/.test(version) || !Number.isSafeInteger(Number(version)) || !['locked', 'unlocked'].includes(lock) || response.status === 200 && !etag || response.status === 404 && (version !== '0' || lock !== 'unlocked'))
550
559
  throw ownershipFailure('unavailable', 'NS fresh metadata is incomplete', true);
551
560
  const ownershipStatus = headerValue(response.headers, 'X-AUN-Ownership-Status');
552
- return { sub_aid: target, exists: response.status === 200, content: response.status === 200 ? response.text : '', etag, protocol, relation_version: Number(version), lock: lock, stage_supported: headerValue(response.headers, 'X-AUN-Ownership-Stage') === '1', ...(ownershipStatus ? { ownership_status: ownershipStatus } : {}), ...(ownershipStatus === 'pending' ? { pending: true } : {}), observed_at: Math.floor(Date.now() / 1000) };
561
+ const ownerDigest = headerValue(response.headers, 'X-AUN-Owner-MD-SHA256');
562
+ return { sub_aid: target, exists: response.status === 200, content: response.status === 200 ? response.text : '', etag, protocol, relation_version: Number(version), lock: lock, stage_supported: headerValue(response.headers, 'X-AUN-Ownership-Stage') === '1', ...(ownerDigest ? { owner_md_sha256: ownerDigest } : {}), ...(ownershipStatus ? { ownership_status: ownershipStatus } : {}), ...(ownershipStatus === 'pending' ? { pending: true } : {}), observed_at: Math.floor(Date.now() / 1000) };
553
563
  }
554
564
  async submitOwnershipRaw(aid, raw, condition, assertActive, stage) {
555
565
  const target = this.safeAid(aid), current = this._currentAid();
@@ -1184,6 +1194,21 @@ export class AgentMdManager {
1184
1194
  this._scheduleDownloadIfMissing(target, record, source);
1185
1195
  this._log.debug(`agent.md meta observed: aid=${target} etag=${remoteEtag || '-'} last_modified=${remoteLastModified || '-'} source=${source || '-'}`);
1186
1196
  }
1197
+ observeOwnershipMeta(aid, digest) {
1198
+ if (!aid || !digest)
1199
+ return;
1200
+ const record = this.loadRecord(aid);
1201
+ if (record?.remote_owner_md_sha256 === digest)
1202
+ return;
1203
+ this.updateRecord(aid, (current) => {
1204
+ if (current.remote_owner_md_sha256 === digest)
1205
+ return;
1206
+ current.remote_owner_md_sha256 = digest;
1207
+ current.observation_version = Number(current.observation_version ?? 0) + 1;
1208
+ if (current.ownership_snapshot?.owner_md_sha256 !== digest)
1209
+ current.ownership_snapshot = {};
1210
+ });
1211
+ }
1187
1212
  observeRpcMeta(meta, ownerAid) {
1188
1213
  if (!meta || typeof meta !== 'object')
1189
1214
  return;
@@ -1198,6 +1223,7 @@ export class AgentMdManager {
1198
1223
  if (!isJsonObject(item))
1199
1224
  continue;
1200
1225
  const obj = item;
1226
+ this.observeOwnershipMeta(String(obj.aid ?? ''), String(obj.owner_md_sha256 ?? ''));
1201
1227
  this.observeMeta(String(obj.aid ?? ''), String(obj.etag ?? ''), String(obj.last_modified ?? obj.lastModified ?? ''), `rpc.${key}`);
1202
1228
  }
1203
1229
  }
@@ -1217,6 +1243,7 @@ export class AgentMdManager {
1217
1243
  senderAid = String(aad.from ?? env.from ?? '').trim();
1218
1244
  }
1219
1245
  this.observeMeta(senderAid, String(sender.etag ?? ''), String(sender.last_modified ?? sender.lastModified ?? ''), 'envelope.sender');
1246
+ this.observeOwnershipMeta(senderAid, String(sender.owner_md_sha256 ?? ''));
1220
1247
  }
1221
1248
  if (isJsonObject(agentMd.group)) {
1222
1249
  const group = agentMd.group;
@@ -1468,6 +1495,7 @@ export class AgentMdManager {
1468
1495
  verified_agent_md: { etag: responseEtag, content_hash: localEtag, verification, signature, cert_pem: peer.certPem },
1469
1496
  last_error: '',
1470
1497
  }, observation);
1498
+ this.observeOwnershipMeta(target, headerValue(response.headers, 'X-AUN-Owner-MD-SHA256'));
1471
1499
  const owner = this._ownerAid();
1472
1500
  let inSync = null;
1473
1501
  if (target.toLowerCase() === owner.toLowerCase()) {