Repository navigation
fix(lark): share fresh source verification within reply operations - #6715
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机
使用已绑定 App 等待原消息答复的用户,以及维护发送、回执读回和恢复路径的操作者。
旧路径对同一次回传重复核验 App,且普通来源读取途中撤权后仍可能发送;新路径每次重新完成一次来源校验,并在全部读取结束后拒绝已撤销的绑定。
File/Core 与正常 wheel 的回归证实:同次发送和恢复各核验一次 App,来源拒绝不记投递意图,读回丢失后沿原 attempt 恢复且不重复发送。
本 PR 不认证真实 provider 延迟、完整停止时限或 Web 首次可见,也不改变入站授权、用户设置、数据格式或消息消费者。
原服务的完整停止回执和及时 Web 可见性仍须独立验收;本次合成传输结果不能关闭这些缺口。
改动思路
完整来源校验已经由原生绑定和传输路径共同拥有,复用其当次观测比新增身份缓存、CLI 分支或第二消费者更小,也保留失败时的授权边界。
本 PR 交付发送、编辑与恢复的一致来源事务和读取期间撤权拒绝;原生 Core 的入站 fence、旧 Inbox 路径及安装态延迟验收各保留原责任。
新发送、编辑和恢复仍沿原消息进入既有 Inbox 投递事务。Core 核验当前 App 与授权,传输层核验原消息、发送者和话题根,随后才允许记录意图及写 provider。一次操作内分别消费身份和来源结果,不能跨操作复用。旧 membership callback 只证明会话关系,因此继续独立核验 Bot,不能借此省略身份边界。
以下为本 head 的源码路径比较,执行证据另见测试结果;无新增界面或交互轮数:
| 触发 | 原路径 | 当前路径 |
|---|---|---|
| 原生新发送/恢复 | 通用身份检查后再做完整来源检查 | 完整来源检查提供当次身份及来源结果 |
| 来源读取途中撤权 | 普通读取可能消费旧绑定 | 全部读取结束后重读原绑定并拒绝 |
| 已写出但读回丢失 | 保留原 attempt | 同样保留,重新验源后只读回 |
| 旧通用 Inbox 调用 | 独立身份与会话检查 | 保持完整结果和底层命令一致 |
具体改动
审查 head:b548e95d3783601850731d2d487e9ace29c20796。依据修改前已接受的 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,spec_revision 为 cd148933bb0cb00232cb3cc494f898a171ffe36c,不能用本 PR 新增文字反向定义通过标准。以下审查标签对应原文未编号的条款:source-app(原 App 重新验源)已实现;revocation(撤权阻止后续回传)已实现;uncertain-return(不确定写入只读回、不盲重发)已实现;qualification-boundary(源码与 live 验收分开)仍保留独立验收缺口。对应的固定版本规范包含原有私聊、选定群话题和最终结果恢复要求。
关键代码讲解
_verified_sender_and_source统一发送、读回和编辑的校验入口。只有内部完整来源 callback 才消费同次 Core 观测;空 callback 走原身份及 membership 检查。它校验返回形状,并把已验证身份与来源拒绝分开,避免错误触发名称刷新。_source_message继续核验真实来源、发送者、父/root/thread 和根消息提及。只把当前 Core resolve 观测的名称放到临时输出;来源读取结束后比较确切绑定。该补查只在 outbound 生效,入站仍由 Core 原有 fence 返回原错误状态。_source_authority把 callback 绑定到本次 profile/chat/message,外来路由在 provider IO 前拒绝。每次使用新的局部容器,成功过的旧请求不能为以后请求授权;名称匹配也不能替代完整来源 verdict。_deliver复用原发送、编辑与 verify 分支和持久化 attempt。失去读回的已知消息只验证同一 ID;未知效果不重发。最终编辑仍读回完整原结果,恢复测试已核验真实可见内容、原目标及唯一性,不再把创建历史误当消息现状。
精确 diff 是两处生产 extension、两份持久回归及中英 RFC,未引入生成文件、状态库或迁移。所有生产入口都有既有调用者,不是仅测试可达的接口。
对主干的风险
主要风险是省略必要的新鲜身份检查、来源失败误分类,以及读取期间撤权后仍发出回复。当前结果保留 Core 当前授权、原消息来源和 attempt journal,旧通用调用在预览、发送、恢复、membership 和拒绝身份五类场景的完整 JSON、回执及底层 argv 均与基线一致,未删字段或归一化失败细节。内部分支不是 HTTP、CLI 或用户可写的授权开关。
本 head 受影响的 12 个测试文件共 532 项通过;正常 wheel 的实际模块导入、安装 doctor 和 18 项 File/Core 事务用例通过。标准 premerge 的 6 个直接检查及 14 个选定检查全过,包括中英配对、公开边界、维护性和完整语义检查。当前 Goal 的独立 change-quality receipt policy 为 disabled,不伪造回执;按合同未查询或等待 CI。
反例不仅检查 helper:相同公开 fixture 运行原 base,复现三类重复身份调用和读取途中撤权后仍发送,合计四个预期失败;移除最终绑定比较也使真实 _deliver 的独立 no-send 断言失败。source-denial 诊断在原 base 通过、作者旧 head 失败,当前 head 修正且保留不写 intent 的断言。早期 wrapper、调度、入站错误状态和创建历史 oracle 的失败均已留存,修正后覆盖原暴露条件;没有放宽时限或冻结阈值。
语义与 CI 对齐
这里复用现有绑定、来源与回执语义;新增 tuple 只在 extension 内传递一次观测,不创建共享词表、缓存权限或存储格式。开发 advisory 无支持的新词表载体只是有限扫描结果,完整 semantic gate 和调用者比较另行通过。合成 provider/native protocol 不代表真实网络、模型执行、停止 SLA 或及时 Web 可见性;这些限制保留,不能据此发布社区准出或扩权。
我的整体评价
未发现本 head 的阻断问题。long_horizon 改善来自减少重复 IO、恢复仍使用原 attempt 及撤权后拒绝副作用;user_experience 改善来自零额外用户交互及准确保留来源失败语义。代码继续使用既有 Core/Inbox 责任层,保留通用兼容路径有实际调用者依据,没有第二套 authority。
这是 justified_increment:验源事务可单独测试、回滚且无迁移,但并未完成原服务 live 时限及整体社区验收。当前保留所选边界,下一步由既有安装/发布责任方按准确版本验证受影响的原消息旅程。原有失败和未验项仍有效,源码合并与 provider 性能结论分开判断。
English verdict: APPROVE - b548e95. One fresh source-bound verification per native reply operation preserves legacy authentication and readback recovery; late binding revocation blocks sends. 532 affected regressions, 18 normal-wheel cases, whole-result parity and exact-head premerge passed. Live provider/stop/Web qualification remains separate.
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
New Lark replies and receipt recovery authenticate the Bot separately from the native source check, although that check already verifies the current App and Core grant. They now consume one fresh source-bound verification for the exact profile, chat and message within each operation. Identity and source verdicts remain distinct, and retries verify again. Legacy membership callbacks retain independent sender authentication. A final outbound binding read rejects revocation while source reads are in flight, before recording a delivery intent or sending.
The change reuses the existing private conversation transport, Inbox delivery journal and native Core owner. Admission, stored formats, CLI flags and consumer ownership remain unchanged. Lost readback keeps the original attempt without resending. The paired RFC separates this transport slice from live provider latency, the complete stop SLA and first-visible Web acceptance.
After integrating current main, 554 regressions across 15 affected files and 18 normal-wheel File/Core cases passed. Standard premerge passed 6 direct and 14 selected checks, including semantic vocabulary, maintainability, bilingual RFC and public boundary. Complete JSON/argv parity holds in five legacy scenarios. Exact-base and removed-check counterfactuals reproduce duplicate authentication and late-revocation sends; the source-denial diagnostic control also distinguishes the authored intermediate failure from the fix. Tests inspect the actual final provider body and original receipt, including edits, rather than creation history alone.
The inherited File/SQLite authority paths additionally passed 109 tests; 25 real PostgreSQL variants were explicitly skipped because no isolated PostgreSQL was configured. They do not qualify PostgreSQL or a complete migration release. The current and previous packaged Web/PWA assets passed actual installed HTTP readback. Maintainer-merged d25c40d has the exact tree qualified at 12e5221. Live service adoption and timing remain separate operational acceptance.