# 2.22.0 发布准备验收 日期:2026-09-26。候选代码基于 `origin/develop@801a71d7402f5d4b582318ed88ad00633357a531`,主包和面板版本统一为 `2.22.0`。本文件记录验收证据,不代表已经发布。 ## 自动化与构建 - 新增 5 项日志弹窗回归:大日志结束后读完分页、尾部截取不重复取历史、运行中空日志继续轮询、关闭取消定时器/丢弃在途响应、旧响应和不前进偏移不死循环。 - 用真实日志读取器写入 600 KiB 后结束任务:原 develop 在新增回归中失败,修复后 5 项全通过。 - macOS arm64、Node 20、按冻结锁文件独立安装依赖:228 项测试,225 通过、3 项平台相关跳过、0 失败。后端 TypeScript 与前端生产构建通过;前端有已有的大包体提示。 - `npm pack --dry-run` 成功,包含前后端产物,主包版本为 2.22.0;npm registry 查询该版本返回 E404(尚未占用,发布时仍需重新核实)。 - 上游基线 Linux CI 为 223 项回归全部通过;CLI Node 22.12/24 流水线通过,Node 24 的 291 项测试全部通过。该结果属于上游提交,不冒充本分支新的 CI 结果。 - GitNexus 对 `getCronLog` 修改前影响分析:LOW,直接调用者 `CronLogModal`,1 条流程。最终差异分析涉及日志弹窗流程;行号移动也将 `autoScroll` 列出,但该函数实现未修改。 ## 容器升级与回退 测试仅使用新建账号、新建任务和隔离容器数据,不接触真实用户数据。 - 已发布旧版镜像 `whyour/qinglong:2.21.0` digest:`sha256:e72f77d855a86cfabf774de76b030731c38540b251a0c888038810fbcf256c48`。镜像内源码为 `9b37f064d815baf49b1869445bbd60e4209bacc9`,与当前 master 提交不同;这是已发布镜像到候选版的实际升级验收。 - 候选运行环境为 `whyour/qinglong:develop` digest:`sha256:35c5b9f2d0666ab7fcde954f175087c097e93fa852306360aa07b8aa0a5d0481`,revision 标签对应 `801a71d7402f5d4b582318ed88ad00633357a531`。装入本分支本地构建的前后端及版本文件。因此验证了候选代码的容器运行,不等同于最终发行镜像的完整构建验收。 - 旧版创建账号及真实 Shell 脚本任务并验证独立输出,停机复制完整 `/ql/data` 作为一致的升级前备份。 - 候选版读取该备份后原密码可登录、原任务仍存在并能真实执行,数据库已增加迁移表,测试账号密码已转为 scrypt(仅检查布尔值,未记录凭据)。 - 长运行脚本启动后确认实际 PID;停止后确认该进程不存在;立即重跑并再次停止成功。状态字段恢复为空闲;不把历史 PID 字段当作进程存活判断。 - 两步验证启用、密码阶段返回挑战、OTP 登录、同一验证码重放拒绝、关闭两步验证及重新登录均通过。 - 每 5 秒调度的测试脚本产生持续输出;本容器 HTTP 夹具订阅下载 V1 文件成功。 - 订阅夹具更新为 V2 后再次同步,落盘内容已变为 V2。 - 容器重启前调度标记 34 行,重启后 41 行,HTTP/gRPC 健康且可重新登录,确认定时注册恢复。 - 将升级前完整备份恢复到全新的 2.21.0 容器,原密码登录、原任务保留及真实脚本输出均通过。 ## 生产依赖审计:仍需处理 在无共享 node_modules 的临时目录,使用候选 `package.json` 和 `pnpm-lock.yaml` 执行 `pnpm audit --prod --json`:414 个依赖,报告 3 Critical、38 High、49 Moderate、9 Low。数量是扫描公告命中,不等于独立漏洞数量或均能在面板中利用。审计时间与数据库变化会影响结果。 | Critical 命中 | 生产依赖路径 | 初步适用性与处理 | | --- | --- | --- | | protobufjs 7.5.4 | `@grpc/proto-loader → protobufjs` | 公告要求攻击者能控制加载的 schema/descriptor;当前主要使用仓库内生成的协议,尚未证实外部可控 schema 入口。仍应升级到修复版本并验证 gRPC。 | | websocket-driver 0.7.4 | `sockjs → websocket-driver` / `faye-websocket` | 处理网络协议帧,不能用面板业务鉴权替代协议层修复;应升级到至少 0.7.5 并回归 WebSocket。 | | tar 6.2.1 | `@whyour/sqlite3 → tar`、`@mapbox/node-pre-gyp → tar` | 主要涉及安装/构建解压链,不能直接等同于面板上传接口漏洞。修复跨 tar 主版本,需验证 SQLite 预编译下载和源码编译路径;另有 tar 7.5.20 的后续公告。 | 参考:[protobufjs 公告](https://github.com/advisories/GHSA-xq3m-2v4x-88gg)、[websocket-driver 公告](https://github.com/advisories/GHSA-xv26-6w52-cph6)、[tar 公告](https://github.com/advisories/GHSA-23hp-3jrh-7fpw)。 High 命中还涉及 gRPC、multer、js-yaml、JWT 的 jws、undici 等运行时依赖。当前准备改动没有批量升级依赖;不能宣称安全扫描通过。正式发布仍需完成依赖升级与可达性评估、回归,或由维护者明确记录接受的风险。 ## 尚未放行的发布步骤 - 本分支新的 Linux CI 尚待执行。 - Python 3.10 镜像和全部架构的最终候选构建尚未验证;上游 develop 工作流跳过这些发布专用任务。 - 主包及 CLI 的 npm Trusted Publisher 设置属于 npm 账户配置,未通过代码或只读公开 registry 验证;不得把 `id-token: write` 视作已完成授权。 - 最终发版时确认 `publishTime` 与实际发布时间一致,并重新核对版本是否可发布。 - 完成上述事项前不合并到 master、不打正式 tag、不执行 `shell/pub.sh`。