fix: 放行NapCat新设备审查规则

This commit is contained in:
sunlei 2026-06-15 06:15:33 +08:00
parent ae2231d508
commit 81d8fc67f8
3 changed files with 34 additions and 7 deletions

View File

@ -149,7 +149,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
- 要收尾时调用 `kt_finish_task`,默认只生成计划和 review需要执行验证时显式传 `runValidation=true`
- 大方向结束前调用 `kt_workstream_closeout``pnpm run workstream-closeout`;必须分别传入 `--review` 的 KT 全局审查证据和 `--superpowers-review` 的 Superpowers code review 证据;如果识别到测试流、卡点、误报、清理、部署观测或命令模板,要先升级对应 ktWorkflow 规则再报告完成。
- 文件改动完成并验证后调用 `kt_global_code_review`,或运行 `pnpm run global-review`;它只读扫描,不删除文件、不提交代码。`findings` 先判定真实风险或工具误报,真实风险修业务代码,误报修 `mcp/ktWorkflow/src/tools/review.ts` 并复跑。
- QQBot NapCat 登录 review 会检查验证码 pending、Docker 日志窗口、API Pod 读取超时,以及 `needNewDevice/jumpUrl` 是否被保留为 `deviceVerifyUrl` pending 状态。
- QQBot NapCat 登录 review 会检查验证码 pending、Docker 日志窗口、API Pod 读取超时,以及 `needNewDevice/jumpUrl` 是否进入 `GetNewDeviceQRCode -> PollNewDeviceQR -> NewDeviceLogin` 或兼容的 `deviceVerifyUrl` pending 状态。
- 代码或配置改动后调用 `kt_change_doc_sync`,把需要同步的 README/API/AGENTS/docs/Obsidian/skill/ktWorkflow 入口补齐;无需同步时把原因写进收尾证据。
- 报告非平凡任务完成前调用 `kt_workflow_loop_audit`,确认测试证据、文档同步、历史清理最终 `deleted=0`、问题固化、ktWorkflow 升级、KT 全局 review 和 Superpowers code review 都过门;清理证据必须显式传入,不能依赖缺省值。
- 要提交或推送时先调用 `kt_commit_plan` / `kt_push_plan`,按仓库分组确认范围。

View File

@ -256,11 +256,17 @@ export async function runSelfTest(): Promise<void> {
" }",
"}",
"if (captchaResult?.needNewDevice && captchaResult.jumpUrl) {",
" return this.keepDeviceVerifyPending(session, captchaResult.jumpUrl, '验证码已通过');",
" return this.startNewDeviceVerification(session, container, captchaResult);",
"}",
"private keepDeviceVerifyPending(session, deviceVerifyUrl) {",
" session.deviceVerifyUrl = deviceVerifyUrl;",
"private async startNewDeviceVerification(session, container, captchaResult) {",
" session.deviceVerifyUrl = captchaResult.jumpUrl;",
" session.captchaUrl = undefined;",
" session.newDeviceQrcode = await this.client.GetNewDeviceQRCode();",
" session.newDeviceStatus = 'qr-pending';",
"}",
"private async pollNewDeviceVerification(session) {",
" await this.client.PollNewDeviceQR();",
" await this.client.NewDeviceLogin();",
"}",
"private async detectPasswordCaptchaUrl(container, sinceMs, allowTailFallback = true) {",
" await this.containerService.detectRuntimeCaptchaUrl(container, sinceMs);",
@ -290,7 +296,8 @@ export async function runSelfTest(): Promise<void> {
(item) =>
item.category === "qqbot-napcat-captcha-log-window-late" ||
item.category === "qqbot-napcat-captcha-status-before-log-url" ||
item.category === "qqbot-napcat-captcha-status-clears-pending",
item.category === "qqbot-napcat-captcha-status-clears-pending" ||
item.category === "qqbot-napcat-new-device-drops-pending",
)
) {
throw new Error("QQBot captcha flow valid self-check produced false positive");

View File

@ -560,10 +560,30 @@ export function findQqbotNapcatCaptchaFlowFindings(
});
}
const hasLegacyDeviceVerifyPending =
content.includes("keepDeviceVerifyPending") &&
content.includes("deviceVerifyUrl");
const hasNapcatNewDeviceApiFlow =
content.includes("GetNewDeviceQRCode") &&
content.includes("PollNewDeviceQR") &&
content.includes("NewDeviceLogin") &&
content.includes("deviceVerifyUrl") &&
content.includes("newDeviceQrcode") &&
content.includes("newDeviceStatus") &&
content.includes("session.captchaUrl = undefined");
const hasNapcatNewDeviceWrapperFlow =
content.includes("startNewDeviceVerification") &&
content.includes("pollNewDeviceVerification") &&
content.includes("completePasswordLoginAfterChallenge") &&
content.includes("deviceVerifyUrl") &&
content.includes("newDeviceQrcode") &&
content.includes("newDeviceStatus") &&
content.includes("session.captchaUrl = undefined");
if (
content.includes("needNewDevice") &&
(!content.includes("keepDeviceVerifyPending") ||
!content.includes("deviceVerifyUrl"))
!hasLegacyDeviceVerifyPending &&
!hasNapcatNewDeviceApiFlow &&
!hasNapcatNewDeviceWrapperFlow
) {
findings.push({
category: "qqbot-napcat-new-device-drops-pending",