Skip to content

fix: align BNS device resolution and RTCP failure diagnostics - #212

Merged
waterflier merged 2 commits into
buckyos:mainfrom
weiqiushi:fix/issue-48-did-device-resolution
Oct 22, 2026
Merged

waterflier merged 2 commits into
buckyos:mainfrom
weiqiushi:fix/issue-48-did-device-resolution

Conversation

@weiqiushi

@weiqiushi weiqiushi commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

BNS resolver 的协议迁移尚未收尾:本 PR 的 base 已支持显式 type=device 投影,但仍为旧客户端保留缺省/type=zone 的设备槽投影;RTCP 的 zone 回退错误还会覆盖首个 device 查询失败。本 PR 移除错类型兼容行为、保留两段诊断,并补齐评审指出的三个 HTTP 适配缺口。

  • 仅显式 type=device 使用父 Zone 的设备槽映射,保留独立子名字优先、签名、成员关系和投影一致性校验。
  • Registry 的 DOCUMENT_INCONSISTENT 与确定性身份/类型错误统一返回 invalid + reason,不返回正文;真实依赖故障和投影变化保留 5xx。已经 revoked/tombstoned 的终态优先于旧正文错误,继续返回 410。
  • 直查 Owner/Zone/Device 正文必须通过 hash、结构解析、请求 DID 和类型检查,校验失败不会被忽略后继续作为 active 回答。hash 反例在 mock API 边界注入损坏投影;正常 SQLite 写入会拒绝这种 hash。
  • 未指定类型时读取当前 active 类型集合:唯一类型直接选择;多类型含 zone 时选 zone 并返回警告;多类型无默认时返回 400 ambiguousDocType。排除已撤销、过期与历史版本,不触发父设备槽映射。该能力覆盖 contract/indexer 两个 HTTP 入口,不新增 kRPC wire method。
  • current metadata 区分文档 iat、编码文档 hash 与登记版本;不支持的 versionId/versionTime 明确返回 501。历史查询修正属于协议清理,并非 RTCP current 查询类型冲突的直接原因。

验证(均使用 CARGO_TARGET_DIR=/tmp/sn48-cargo-target,未运行 cargo fmt):

  • cargo test --offline -p bns-server -- --test-threads=1:51 passed,3 ignored。
  • cargo test --offline -p bns-indexer --test centralized_registry -- --test-threads=1:21 passed。
  • cargo test --offline -p bns-client --test rpc_and_controller -- --test-threads=1:27 passed。
  • cargo test --offline -p cyfs-gateway-lib --lib handshake_document -- --test-threads=1:4 passed。
  • 新增反例在修复前复现,修复后通过;git diff --check 通过。

关联 buckyos/sn-business#48。Relay device.json 的生成、旧身份补齐和分发清单已在 SN-Business 单独修复。这些修改不能单独证明现场首个 device 查询已恢复:真实 keep-tunnel / 公网 HTTPS 验收按用户要求由 issue 发起者在资产推送与相应程序部署后完成。

AuthorityCurrent 与严格类型/身份校验保持不变。IndependentControlPlane 及 TrustedSnapshot/后台确认仍需单独跟踪,本 PR 不作为整个 Relay 回流问题已经闭环的验收依据。

@waterflier

Copy link
Copy Markdown
Member

基于本 PR 的 2bd188a,对照 buckyos-base 的 resolve-did.py、HTTP resolver 协议及迁移记录做了 review。

修复方向正确:本次直接问题主要是 BNS 协议迁移未收尾,以及 RTCP 的后一段错误覆盖前一段错误。NameClient 拒绝错类型文档的行为应该保留。 当前协议明确要求设备槽位联合校验只用于显式 type=device,不能对 type=zone 返回 DeviceDocument;确定性校验失败应返回 invalid,历史查询不支持时应返回 501,不能静默回答 current。参见 类型规则、错误分类 和 历史查询。

时间线需要区分:本 PR 的 base 已支持显式 type=device 投影;迁移记录 说明旧的缺省/type=zone 投影曾为兼容旧客户端而保留。本 PR 删除的是这部分旧行为。因此,如果现场首先是 #device 查询失败,本次改动可以消除后续类型错位、保留首个失败原因,但不能单独证明设备身份已恢复可用。缺失的 Relay device.json、错误的 Zone/Owner 或未发布的设备资料仍需分别修复。RTCP 两阶段查询都是 current,历史参数修复也不应被归为这条类型冲突的直接原因。

目前还有三处需要补齐。以下均为本 PR 修复范围内尚未覆盖的既有问题,不是断言本 PR 新增了回归:

  1. 确定性 owner 不一致仍会返回 HTTP 500。
    新增错误分支 只处理 INVALID_DOCUMENT,而 registry 的 ensure_document_consistent 会返回 DOCUMENT_INCONSISTENT,最终仍走通用 500。已用真实 registry 验证:alice 的 owner 正文声明 "owner":"did:bns:bob",与登记 owner 不一致,?type=owner 返回 500。设备投影读取父 owner 时也可能在进入 validate_device_slot 前收到这一错误。建议把这类确定性身份/owner 错误统一映射为 invalid + reason,不返回正文;真实依赖失败和投影变化仍保留 5xx。

  2. 新增类型检查吞掉了解析/hash 校验错误,直查路径仍可回答 active。
    这里的两层 if let Ok 忽略了 projected_document 和 parse_did_doc 的失败。直接登记的文档不会经过父槽联合验证,因此无法解析为 OwnerDocument 的正文仍可得到 active。另外,模拟上游返回 hash 不匹配的完整 OwnerDocument 时,HTTP 仍返回 active 和正文,只省略 docHash;实际 NameClient 会从正文补算 hash,仍成功选中该 owner。建议显式处理失败分支,避免已发现错误的内容继续成为权威 active 回答。
    边界说明:正常 SQLite 写入会拒绝 hash 不匹配;hash 反例通过 mock API 注入损坏的上游投影,验证的是 HTTP 适配层的拒绝行为,不表示正常发布能写入这种状态。

  3. 缺省类型仍固定为 zone,与当前协议的归一规则不一致。
    查询解析代码 仍将缺省类型设为 zone,本 PR 的 BNS-API 文档 也继续规定这一行为。协议要求 BNS 根据 active 类型集合选择默认类型:唯一时选它,多类型按默认/歧义规则处理。已验证只有 owner 文档的名字:无 type 返回 404 zone missing,显式 type=owner 返回 200 active。建议把“显式 zone 不投影 device”和“未指定类型如何选择”分开实现并补测试。

机制方面还需保持独立跟踪。 AuthorityCurrent 必须取得本轮权威证据,所以 BNS 不可用时拒绝握手是明确的策略取舍。是否使用 TrustedSnapshot 加后台确认,应作为 RTCP 准入策略单独决定,不能通过放宽类型/身份校验来实现。

但 #207 的 Relay 自转发事故也暴露过机制缺口:设计记录 已明确修订锁跨 I/O 和缺少 invalid 状态的问题。当前设计还要求独立控制通道,而 RTCP 代码 仍留有 IndependentControlPlane TODO。authority_only 限制来源,并不能证明 authority 的 DNS、代理、重定向不依赖目标 Relay。因此本 PR 可以推进协议修复,但不能作为整个回流问题已经闭环的验收依据。

验证:在该 PR checkout 上,cargo test --offline -p bns-server --lib did_resolver -- --test-threads=1 的 19 个测试和 cargo test --offline -p cyfs-gateway-lib --lib handshake_document -- --test-threads=1 的 4 个测试均通过;另外 3 个临时反例测试确认了上述实际行为,测试代码随后已恢复。使用的 buckyos-base 为 main 的 1e8544a4。未进行线上验收;关联的 sn-business#48 在当前 GitHub 连接返回 404,因此没有独立核对其现场日志。

@weiqiushi

Copy link
Copy Markdown
Member Author

已按这次 review 在提交 a3b54cae 中补齐三处问题,PR 描述和 BNS API 文档也已同步更新。

  1. 确定性 owner 不一致:DOCUMENT_INCONSISTENT 与 INVALID_DOCUMENT 统一返回 invalid + reason,不返回正文,覆盖直查以及设备投影读取父 owner 的路径。真实依赖故障仍保留 5xx;revoked/tombstoned 的终态优先,继续返回 410。
  2. 直查正文校验:显式处理投影 hash、正文解析、DID 和类型校验的失败,避免损坏正文继续作为 active 回答。补了真实 registry 的非法 Owner 反例,以及 mock API 注入 hash 不匹配投影、NameClient 拒绝该结果的测试;正常 SQLite 写入拒绝错误 hash 的边界保持不变。
  3. 缺省类型选择:两个 HTTP 入口均按当前 active 类型集合选择:唯一类型直接使用;多类型含 zone 时选择 zone 并返回警告;多类型无默认时返回 400 ambiguousDocType。集合排除历史、撤销和过期记录;父设备槽映射仍仅用于显式 type=device。

本地离线回归共 103 passed、3 ignored:

  • bns-server:51 passed、3 ignored。
  • bns-indexer --test centralized_registry:21 passed。
  • bns-client --test rpc_and_controller:27 passed。
  • cyfs-gateway-lib --lib handshake_document:4 passed。

新增反例在修复前可复现、修复后通过,git diff --check 通过。

同意 review 对时间线和验收范围的区分:base 已支持显式 device 投影;本 PR 清理旧的错类型兼容行为并保留两阶段失败原因,历史查询修正不作为 RTCP current 查询冲突的直接原因。严格类型/身份校验和 AuthorityCurrent 保持不变,IndependentControlPlane、TrustedSnapshot/后台确认继续单独跟踪。本次未做线上验收;真实 keep-tunnel / 公网 HTTPS 验收由 issue 发起者在资产推送和相应程序部署后完成。

@waterflier
waterflier merged commit 3f6d4a8 into buckyos:main Oct 22, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants