文档 · 开发者

08 错误码、版本策略与安全注意事项

错误码表、版本与兼容策略、安全注意事项。

文档来源本栏目是公开仓库 rfdiosuao/lom-desktop 中 docs/open/phone-access/ 的原文,提交 92044e2;本页对应 08-errors-security.md。以 GitHub 上的最新版为准。

错误码表

错误码格式统一为 <域>.<原因>。按 code 做逻辑判断,不要解析 error 文字。 文案栏给出推荐的用户可见中文提示(来自云端 / 桌面的实际文案),你也可以映射成自己的文案或多语言文案。

A. 云端 HTTP 接口返回的错误

响应体:{ "success": false, "code": "…", "error": "…" },HTTP 状态码见表。

错误码HTTP出现在含义推荐文案手机应该做什么
pairing.qr_invalid403inspect / claimclaim_token 错误(同一会话累计 5 次作废)这不是有效的麓鸣配对码。提示重新扫码
pairing.not_found404配对各接口会话不存在配对会话不存在,请在电脑上刷新。提示在电脑上刷新二维码
pairing.expired410配对各接口会话已过期(创建后 5 分钟)配对码已过期,请在电脑上刷新。同上,并使确认按钮失效
pairing.cancelled409配对各接口会话已被作废 / 取消配对已取消,请在电脑上刷新。同上
pairing.failed409配对各接口桌面核对 key_proof 失败,或 claim_token 错误过多配对校验失败,请刷新二维码重试。同上
pairing.already_claimed409inspect / claim / 其他会话已被认领或已确认这个配对码已被使用,请在电脑上刷新。同上
pairing.awaiting_desktop409confirm扫码路径:桌面还没核对完 key_proof正在等待电脑核对,请稍候。每秒重试,最多 15 次(03)
pairing.secret_invalid403confirm / cancelclaim_secret 不对配对凭据无效,请重新扫码。重新开始配对
pairing.code_invalid400claim-by-code配对码格式不对 / 不存在 / 已过期 / 已被认领配对码不正确。让用户重新输入
pairing.request_invalid400claim / claim-by-code请求字段非法(公钥串不合法、与桌面公钥相同、key_proof 长度不对…)配对请求格式不正确属于实现错误,检查 04
pairing.rate_limited429inspect / claim / claim-by-code同一 IP 每分钟认领类请求超过 10 次尝试次数过多,请稍后再试。提示稍后再试,下一分钟再发
device.owned_by_other_account409claim / confirm这组公钥已属于另一个账户这台手机已连接到另一个账户,请先在手机上解除配对。引导用户先在原账户移除这台手机
sub.phone_limit409confirm账户订阅可接入的手机台数已满已达到手机上限,升级订阅可以连接更多手机。提示用户在电脑上升级订阅或移除旧手机
relay.unauthorized401设备凭据请求头缺失 / 格式错误;WebSocket 握手令牌无效或过期凭据或令牌无效中转连接凭据无效,请重新连接。握手时:重新换中转令牌再连;请求头问题:修实现
relay.device_revoked401换令牌、握手设备凭据无效 / 过期 / 设备已被移除这台手机已解除配对,请重新扫码连接。清除凭据,回到未配对,不再重连(05 §6)
server.internal500任意云端内部错误服务暂时不可用,请稍后重试。退避重试
非 JSON 响应(网关错误页、框架级 4xx / 5xx)按失败处理,映射为本地 pairing.response_invalid,退避重试。

B. 桌面经云端调用手机时可能出现的云端错误(手机不会收到,列出便于理解桌面表现)

错误码HTTP含义
device.not_found404设备不存在,或不属于该账户,或 recipient 与设备登记的公钥串不一致
relay.invalid_request400信封格式无效(id 不是 32 位十六进制、sender 不是 86 字符等)
relay.offline409手机当前没有 WebSocket 连接(云端不排队)。「手机离线,请打开手机应用。」
relay.duplicate_request409同一个信封 id 正在等待回复
relay.busy429该手机在途请求已达 8 个
relay.disconnected502请求发出后、回复前手机连接断了——执行结果未知
relay.reply_timeout50415 秒内没收到回复——执行结果未知(含手机丢弃了不可信信封、回复太大被丢弃等情形)

C. 手机本地错误(不来自云端,建议使用同名错误码)

错误码含义推荐文案
pairing.qr_invalid二维码格式 / 版本 / 主机白名单 / 字段长度不合法(此时不发网络请求)这不是有效的麓鸣配对码。
pairing.key_mismatchinspect 返回的桌面公钥指纹与二维码 f 不一致,或 pairing_id 对不上配对信息不一致,请重新扫码。
pairing.already_paired手机已配对,需先解除这台手机已经连接了一台电脑,请先解除配对。
pairing.desktop_timeoutawaiting_desktop 重试 15 次仍未通过电脑迟迟没有确认,请重新扫码。
pairing.store_failed凭据落盘失败保存连接信息失败,请重试。
pairing.response_invalid响应不是预期的 JSON / 缺字段服务返回了无法识别的内容,请稍后重试。
net.unreachable网络不可达 / 超时无法连接麓鸣服务,请检查网络。

D. 手机在 RPC 回复里返回的错误码

信封内的 RpcResponse.error(06 §7):

类别错误码定义位置
协议级remote.expired remote.revoked remote.replayed remote.not_ready remote.method_unknown remote.operation_failed06 §7
通用sync.conflict sync.invalid_name sync.document_too_large sync.write_failed07
各方法model.* chat.* file.* image.* screen.* skill.* schedule.* subagent.*各方法小节末尾

桌面侧另有一些只在桌面本机产生的错误码(如 remote.repair_required「本机未找到该手机的配对公钥,请重新配对」、remote.trust_store_unavailable、remote.trust_store_invalid),它们说明桌面端的钥匙串状态,与手机实现无关。

版本与兼容策略

当前协议版本是 v=1。版本号出现在这些地方,它们将一起演进:

位置取值
二维码 / 深链 v 字段1
密码学域分隔字符串LOM-KEY-FP-V1、LOM-PAIR-PROOF-V1、LOM-PAIR-SAS-V1、LOM-REMOTE-V1
中转控制消息的 v 字段1(hello、device.revoked)
测试向量文件名pairing-v1.json、remote-envelope-v1.json

兼容原则(面向第三方的约定):

  1. v=1 范围内只做向前兼容的增量变化:新增 RPC 方法、在请求 / 响应里新增字段、新增中转控制消息类型,都不会改变已有字段的含义。
  2. 你必须这样写,才能吃到这个保证:
    • 解析请求 payload、解密后的 RpcRequest、中转 ctrl 消息时,忽略不认识的字段和 type;
    • 对不认识的 method 返回 remote.method_unknown,不要崩溃、不要静默忽略;
    • 回复信封只含六个字段(云端对信封做严格解析);
    • 不要依赖字段顺序,不要依赖云端返回字段的「只有」这几个。
  3. 破坏性变化会带新版本号:任何改变既有算法、编码或信封字段的修改,会同时提升二维码 v 和对应的 -V1 后缀,并在本目录公布新文档与新向量。
  4. 手机遇到不认识的二维码版本(v 不是 1):协议层按无效处理、不发请求;界面上建议提示「二维码版本较新,请升级 App」而不是「无效」。
  5. 手机落后于桌面的常见情形是桌面新增了你没实现的可选方法——桌面按 07 §1.3 的方式降级展示,不会因此无法使用。建议实现可选方法 device.capabilities,主动声明已实现的方法,桌面就能提前隐藏或置灰不支持的入口。
向后兼容的具体期限(v=2 发布后 v=1 保留多久)尚未对外承诺,将在 v=2 方案公布时一并说明。

安全注意事项

信任模型

  • 手机只信任配对时用户亲手批准的桌面公钥。验签、解密、执行,每一步都建立在「发送方 sender 在已批准集合里」之上。不要根据云端的设备列表、其他消息或任何网络来源追加信任。
  • 官方手机端同一时刻只配对一台桌面:要换桌面,先解除配对再重新扫码。如果你设计成可信多台桌面,也必须让每一台都经过完整的扫码 / 确认码核对,并给用户查看与单独撤销某台桌面的入口。
  • 云端不是可信方:它能看到密文、会话元数据(谁在线、请求大小与时间),但看不到明文,也无法伪造桌面的签名。配对阶段靠 psk 指纹 / 确认码防止云端换成自己的公钥。

秘密的生命周期

秘密存放禁止
身份私钥(X25519 / Ed25519)Keystore 包装的存储,noBackupFilesDir上传、日志、备份、截图
psk、claim_token、claim_secret仅内存,配对结束即丢弃持久化、日志、URL
device_tokenKeystore 保护的存储日志、URL、崩溃报告
relay_token仅内存日志、URL
model.sync 的 api_key加密凭据库(按桌面公钥隔离)日志、会话缓存、错误信息、转发给任何其他服务
  • 所有 HTTP 请求只用 HTTPS / WSS,使用系统证书校验;
  • 令牌放请求体或请求头,不放 URL;
  • 日志里只允许出现 ID(pairing_id、device_id、信封 id 的前几位)、长度、时间、错误码,不允许出现任何令牌、密钥、明文载荷、桌面发来的提示词;
  • 所有令牌 / 指纹 / key_proof 比较用恒定时间比较。

配对阶段

  • 二维码视同临时口令:5 分钟、一次性;主机白名单必须写死在 App 里;
  • 来自深链、相册、他人转发的二维码,一律走完整校验并要求用户在手机上确认,不能自动完成;
  • 扫码路径必须核对指纹,配对码路径必须让用户比对确认码;
  • 已配对时拒绝再次配对(先解除)。

RPC 阶段

  • 先验签再解密,验签 / 信任失败不回复(06 §5);
  • 严格执行 5 分钟时间窗口,并把去重表持久化;
  • 请求里的一切参数都是不可信输入:文件名、路径、ZIP 条目、坐标、包名、会话 ID 都要按 07 的规则校验;绝不执行桌面传来的 shell 命令、不接受任意文件路径;
  • 有副作用的方法(screen.control、schedule.run、chat.send、skills.install、file.save_gallery)必须按幂等键持久化收据,宁可返回「结果未知」也不要重复执行;
  • 屏幕类方法:密码输入框内容一律脱敏;系统禁止截屏的窗口返回失败而不是绕过;
  • 回复大小要自己限制(≤ 350,000 字节明文),不要依赖云端截断;
  • 建议在界面上让用户看得到:当前被哪台电脑授权、最近是否被远程操作,并提供随时「解除配对」的入口。

其他

  • 手机时钟需基本准确(偏差超过 5 分钟会让所有请求被 remote.expired 拒绝);
  • 解除配对后,清除设备凭据与桌面公钥;用户的会话、人格、记忆、技能保留在手机上,不要删除。