fix(lark): oncall 群不再读访客消息额度,恒不限额 - #1217
Merged
Merged
Conversation
`messageQuota.defaultLimit` 的语义是「授权卡 / 自助申请授权放进来的**访客**默认 额度」,但 oncall 群也在读它,导致三个连锁问题: - `evaluateTalk` 的放行腿是顺序短路的,oncall 腿排在 peer / teamBot 之前。oncall 群 + 配了 defaultLimit 时,同团队 peer bot 被这条访客额度连带计量,本该让它 「免 /grant 且不限额」的 teamBot 腿**结构上不可达**。 - 额度耗尽后 `revokeQuotaGrant` 对 `reason='oncall'` 是 no-op(没有 chatGrant 可 删),授权并未真被收回、计数器也不会清,于是**每条后续消息都重发一张「额度已 用尽」卡**。 - 而恢复手段只有「点名带额度」`/grant @x N`:裸 `/grant` 只写 allowedChatGroups (同样被 oncall 短路)且不碰 quotaState,owner 反复授权无效。即「限了额也没法 用 /grant 提额」,护栏在 oncall 场景下只会把群锁死。 因此 `oncallTalk` 改为恒不挂 quotaKey。访客侧不变:chatGrant / globalGrant 腿仍 各自挂 quotaKey 并照常消费 defaultLimit,非 oncall 群的过期授权照旧拒发 + 条件式 清理。会话群的存量兜底分支同步跟随(它本就复用 oncallTalk)。 同步收敛文案:dashboard 帮助文案与状态行、/botconfig 额度卡、bots.json 中英文档 过去都写着「授权卡与 Oncall 共用该额度」,现在明确为「只约束访客,Oncall 恒不限 额」。超上限值的兼容分支不再声称 oncall 按原值执行。 ## 影响面 - 会话类型:仅 oncall 群的额度判定。话题会话 / 普通群 / 私聊的 chatGrant、 globalGrant、p2pOpen、allowedChatGroup 各腿逐字未改。 - 跨 CLI / 跨后端:未触碰 adapters 与 PtyBackend / TmuxBackend,无差异。 - 升级:存量配了 defaultLimit 的 bot,其 oncall 群转为不限额;已落盘的 `quotaState` 记录成为孤儿(该群不再读它),不需要迁移也不会复活判定。 ## 验证 - `npx tsc --noEmit` 0 error;`bun run build` 通过。 - 相关 10 个测试文件全绿(grant-gates / message-quota-enforcement / message-quota-doc-sync / dashboard-grant-defaults / dashboard-bot-defaults-layout / card-builder / card-handler-config / bot-talk-parity / grant-store / session-group-birth-quota)。 - 反变异:把 oncall 读 defaultLimit 的旧实现原样接回,新增的 4 条守卫精确变红 (grant-gates 的「oncall never carries a quotaKey」+ enforcement 的 3 条); 把 bots.json 文档改回旧措辞,doc-sync 守卫变红。确认守卫有牙。 - 新增守卫带阴性对照:同一个 defaultLimit 对**非 oncall** 群的 chatGrant 仍挂 quotaKey,证明测的是「oncall 不读」而非「额度整体失效」。 - 全量 `--project unit` 1191 passed / 7 failed,7 个红全部为本机环境既有问题: clean master 上逐一复现同样失败(pm2 / config-dir / mojo / plugin-mcp-sandbox / plugin-registry-sandbox-read 为 root+bwrap 环境类;worker-dsh 在 clean master 上同样超时;tmux-pipe-backend-exit 单独跑 10/10 绿,属并发负载 flake)。⚠️ 未做真实飞书 e2e:上报该问题的两个 bot 不在本机。
复审指出用户面文案改全了,但**代码注释漏了 6 处**:它们仍在描述「oncall 会按
messageQuota.defaultLimit 挂 quotaKey」这个已不可能发生的语义,与同文件新的
`oncallTalk` 注释直接矛盾。本仓注释是承重资产,说谎的注释比没有注释更危险。
- `event-dispatcher.ts` — `TalkEvaluation.explicitGrantOverride` /
`expiredGrantCleanup` 两个字段注释:改为标明**已无生产产出方**,保留历史语义
说明与「为何保留字段」。
- `daemon.ts` — 交集决策注释块:原先描述的三个分支(explicitGrantOverride /
expiredGrantCleanup / 其余 oncall 兜 default)在生产中已全部不可达。改为说明
`def` 恒为 undefined 的理由:只有 chatGrant / globalGrant 挂 quotaKey,带
`reason==='oncall'` 的判定在 `if (!ev.quotaKey) return true` 就已返回。
- `bot-registry.ts` — `messageQuota` 字段注释删掉「同时作为 oncall 默认额度」。
- `dashboard-ipc-server.ts` — `messageQuotaDefaultLimit` 的路由注释同上。
- `grant-store.ts` — `consumeQuota` 的懒初始化与 `expiredGrant` 文档:标明两者
当前都没有生产调用方(访客额度记录是**发卡那一刻**按 `defaultLimit ?? 3` 写好
的,不依赖懒初始化),参数保留仅为不改签名。
- `session-groups-store.ts` — `originReason` 注释里「a FRESH per-group allowance
when one is」已不再成立。
顺带修一处**误导性标识符**(自查发现,非复审提出):dashboard 兼容分支的 i18n
占位符 `{oncallCount}` 现在承载的是「超过上限的配置值」而不是「oncall 的额度」,
与被清理的那些注释属同一类问题,重命名为 `{configuredCount}`(4 处文案 + 2 处
调用点,中英同步)。
不删死机器:`consumeQuota` 签名、`TalkEvaluation` 的两个字段、以及 grant-store
的相关测试留作独立 cleanup —— 本次只保证注释不再描述已死语义。
## 验证
- `npx tsc --noEmit` 0 error;`bun run build` 通过。
- 相关 10 个测试文件全绿(322 条)。
- 反变异复跑:把 `oncallTalk` 改成挂 quotaKey ⟹ grant-gates 与
message-quota-enforcement 的 5 条守卫精确变红;还原后复绿。确认本次注释改动
没有削弱行为守卫。
|
🚀 Released in v3.18.14 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
messageQuota.defaultLimit的语义是「授权卡 / 自助申请授权放进来的访客默认额度」,但 oncall 群也在读它,导致三个连锁问题:
evaluateTalk的放行腿是顺序短路的,oncall 腿排在 peer / teamBot 之前。oncall群 + 配了 defaultLimit 时,同团队 peer bot 被这条访客额度连带计量,本该让它
「免 /grant 且不限额」的 teamBot 腿结构上不可达。
revokeQuotaGrant对reason='oncall'是 no-op(没有 chatGrant 可删),授权并未真被收回、计数器也不会清,于是每条后续消息都重发一张「额度已
用尽」卡。
/grant @x N:裸/grant只写 allowedChatGroups(同样被 oncall 短路)且不碰 quotaState,owner 反复授权无效。即「限了额也没法
用 /grant 提额」,护栏在 oncall 场景下只会把群锁死。
因此
oncallTalk改为恒不挂 quotaKey。访客侧不变:chatGrant / globalGrant 腿仍各自挂 quotaKey 并照常消费 defaultLimit,非 oncall 群的过期授权照旧拒发 + 条件式
清理。会话群的存量兜底分支同步跟随(它本就复用 oncallTalk)。
同步收敛文案:dashboard 帮助文案与状态行、/botconfig 额度卡、bots.json 中英文档
过去都写着「授权卡与 Oncall 共用该额度」,现在明确为「只约束访客,Oncall 恒不限
额」。超上限值的兼容分支不再声称 oncall 按原值执行。
影响面
globalGrant、p2pOpen、allowedChatGroup 各腿逐字未改。
quotaState记录成为孤儿(该群不再读它),不需要迁移也不会复活判定。验证
npx tsc --noEmit0 error;bun run build通过。message-quota-doc-sync / dashboard-grant-defaults / dashboard-bot-defaults-layout /
card-builder / card-handler-config / bot-talk-parity / grant-store /
session-group-birth-quota)。
(grant-gates 的「oncall never carries a quotaKey」+ enforcement 的 3 条);
把 bots.json 文档改回旧措辞,doc-sync 守卫变红。确认守卫有牙。
quotaKey,证明测的是「oncall 不读」而非「额度整体失效」。
--project unit1191 passed / 7 failed,7 个红全部为本机环境既有问题:clean master 上逐一复现同样失败(pm2 / config-dir / mojo / plugin-mcp-sandbox /
plugin-registry-sandbox-read 为 root+bwrap 环境类;worker-dsh 在 clean master
上同样超时;tmux-pipe-backend-exit 单独跑 10/10 绿,属并发负载 flake)。
🤖 Generated with Claude Code