docs(changelog): 回填「检查更新」修复的真机复验与守卫口径

CHANGELOG 与 docs/console-plan.md 的该节写于「15 用例 / 248KB」时点(随后被隐私脱敏
提交一并带走),已落后于代码,且当时「经代理成功」那一组受宿主线路拥塞未取到。
本次回填三处:

- 用例数 15 → **16**,补第 15 条守卫(错误映射:连接被中途重置不得报成「请求超时」)
  及其注入验证行。
- 补记**第三个缺陷**:ECONNRESET 被误归 abort 类 → 真机耗时 82.9s 却报「请求超时
  (120000ms 内未完成)」,把「对端掐断连接」这条最有价值的信息抹掉。
- 产物 248KB → **249KB**;真机复验表补 D/E 两组(Win11 ARM64 VM,用随包 node.exe 直跑
  dist/sidecar.mjs,两侧 sha256 一致):
  · D 对照(不配系统代理、不给任何环境变量)→ 30877ms 失败,但报真实原因 socket hang up,
    data 带 via=直连 / timeout_ms / 可操作提示;
  · E 实验(只设 WinINET 系统代理、仍不给任何环境变量)→ **成功 28883ms**,
    via_proxy=system、日志「(来源 system)」、退出码 0。
  实验组走通的正是本次新增的系统代理发现;其 28.9s 耗时同时反证旧 20s 内部超时必然失败。
  复验后 VM 的 ProxyEnable/ProxyServer 已原样还原。

无代码改动。
This commit is contained in:
jkooe committed 2026-10-13 22:47:36 +08:00
1 parent b34e8c73e0
commit 590f62e968
2 files changed
+34 -8

No files matched your search

+20 -6
View File
@@ -591,7 +591,12 @@ sidecar 这条路径一直没被覆盖。
**隧道与 TLS 握手阶段没有接 abort 信号** —— 那个阶段外层 `http.request` 还没建立,
`signal`/`timeout` 都无人受理。真机形态:配置 75s 超时,**实际挂了 109s** 才失败。
**守卫**(`tests/unit/sidecar-proxy.test.mjs`,15 用例)+ 注入验证:
**第三个缺陷**(同一轮真机暴露):**`ECONNRESET` 被误归入 abort 类**,于是连接被中途重置时
报的是「请求超时」——真机形态是耗时 **82.9s**(预算 120s)却报「请求超时(120000ms 内未完成)」,
把「对端把连接掐断了」这条最有价值的信息抹掉。改为**只认真正的 abort**(`AbortError`/`ABORT_ERR`),
其余网络错误单列翻译(`ENOTFOUND`/`EAI_AGAIN`/`ECONNREFUSED`/`ECONNRESET`/`EPIPE`)。
**守卫**(`tests/unit/sidecar-proxy.test.mjs`,16 用例)+ 注入验证:
| # | 守什么 | 注入故障实测 |
|---|---|---|
@@ -599,14 +604,23 @@ sidecar 这条路径一直没被覆盖。
| 9–12 | 真发请求(**离线本地服务器**):直连跟随 302、经代理走绝对形态、**代理不通必须报错**(防静默降级)、CONNECT 可用 / 被拒报错、**隧道+TLS 阶段 abort 必须立即生效**(带看门狗,故障时失败而非挂死) | 去掉隧道阶段 abort 挂载 → 用例 12 红(`实际 4002ms`) |
| 13 | **端到端**:真 spawn sidecar 进程走 JSON-RPC 跑 `check_update`,断言返回正确且 **`via_proxy` 正确**、代理**真收到了**请求;反面对照(代理指死端口)必须失败 | 把 `check_update` 退回裸 `fetch` → 用例 13 红(`代理必须真收到这次请求`)+ 用例 14 红 |
| 14 | 形态守卫:sidecar 源码不得再出现裸 `fetch(`(防止修复被无声改回去) | 同上 |
| 15 | 错误映射:连接被**中途重置**时不得报成「请求超时」(真机踩过) | 把 `ECONNRESET` 塞回 abort 类 → 用例 15 红 |
**真机复验**(重打 sidecar 产物 248KB,用**打包后的 `dist/sidecar.mjs`** 直跑):
**真机复验**(重打 sidecar 产物 249KB,用**打包后的 `dist/sidecar.mjs`** 直跑):
| 组 | 配置 | 结果 |
| 组 | 平台 / 配置 | 结果 |
|---|---|---|
| C | 无代理 | **成功 2169ms** → 最新版本 `v2.0.3`、已是最新;日志正确报出「系统代理使用 PAC 自动配置脚本…已按无代理处理」(macOS `scutil` 探测真实生效) |
| A | `NA_PROXY=http://127.0.0.1:1`(死端口) | **51ms 明确失败**:`connect ECONNREFUSED 127.0.0.1:1(经代理 http://127.0.0.1:1/,耗时 5ms)`;`data` 里带全 `via`/`proxy`/`proxy_source`/`timeout_ms`/`hint` |
| B | `NA_PROXY=http://127.0.0.1:<代理端口>` | 代理路径被正确选中(日志 `经代理 …(来源 NA_PROXY)`);该次宿主代理线路拥塞未在预算内完成 —— **线路本身的问题**,错误信息如实说明「代理已生效但仍失败」 |
| C | macOS / 无代理 | **成功 2169ms** → 最新版本 `v2.0.3`、已是最新;日志正确报出「系统代理使用 PAC 自动配置脚本…已按无代理处理」(`scutil` 探测真实生效) |
| A | macOS / `NA_PROXY=http://127.0.0.1:1`(死端口) | **51ms 明确失败**:`connect ECONNREFUSED 127.0.0.1:1(经代理 http://127.0.0.1:1/,耗时 5ms)`;`data` 里带全 `via`/`proxy`/`proxy_source`/`timeout_ms`/`hint` |
| B | macOS / `NA_PROXY=http://127.0.0.1:<代理端口>` | 代理路径被正确选中(日志 `经代理 …(来源 NA_PROXY)`);该次宿主代理线路拥塞未在预算内完成 —— **线路本身的问题**,错误信息如实说明「代理已生效但仍失败」 |
| D | **Win11 ARM64 VM** / 未配系统代理、未给任何环境变量(直连) | **30877ms 失败**,但报的是真实原因:`socket hang up(连接被对端中途断开…)`,`data` 明确给出 `via=直连`、`proxy=null`、`timeout_ms=120000` 与一句可操作提示「请在系统里开启『系统代理』,或设置 `HTTPS_PROXY=…` 后重启控制台」 |
| E | **Win11 ARM64 VM** / 只设 **WinINET 系统代理**指向转发端点(**不给任何环境变量**) | **成功 28883ms** → `v2.0.3`、`has_update=false`;日志 `检查更新:经代理 http://…(来源 system)`、结果 `via_proxy=system`,**退出码 0** |
> 组 D/E 用的是**随包 `node.exe`**(`%LOCALAPPDATA%\nodeagent-console\node.exe`)直跑
> `dist/sidecar.mjs`,两侧 sha256 一致(`07dd592b…`);E 组**没有任何环境变量参与**,
> 走通的正是本次新增的**系统代理发现**(`reg query` → `来源 system`)。
> E 组耗时 28.9s 同时反证根因 3:旧实现固定 20s 的内部超时对这条链路**必然**失败。
> 复验后 VM 的 `ProxyEnable`/`ProxyServer` 已**原样还原**(复原为 `0x0` / 值不存在)。
> **未覆盖(如实记档)**:**https 目标经 CONNECT 隧道的 TLS 叠层**没有离线自动化用例 ——
> 需要一个受信任证书的本地 TLS 源站,而本仓库没有证书夹具(`selfsigned` 只装在被控端包内,
+14 -2
View File
@@ -604,9 +604,21 @@ Node 内建 `fetch`,于是境内**必然**失败,且失败原因永远是笼
这条关系写成**编译期不变式**,因为一旦破坏,用户只会看到「check_update 超时」这种**丢掉真实原因**的假失败。
120s 的依据是真机实测的重定向链耗时分布(2.0 / 10.0 / 39.7 / 68.6 / >109 秒),不是拍脑袋。
守卫:`tests/unit/sidecar-proxy.test.mjs`(15 用例)= 纯函数解析(夹具取自真机)+ 离线真发请求
守卫:`tests/unit/sidecar-proxy.test.mjs`(16 用例)= 纯函数解析(夹具取自真机)+ 离线真发请求
(直连/绝对形态/CONNECT/**隧道+TLS 阶段 abort 必须立即生效**)+ 真 spawn sidecar 走 JSON-RPC 的端到端
+ 「sidecar 源码不得再出现裸 `fetch(`」形态守卫。全部做过注入故障实测。
+ 「sidecar 源码不得再出现裸 `fetch(`」形态守卫 + 「连接被中途重置不得报成请求超时」的错误映射守卫。
全部做过注入故障实测(含还原后逐字节一致)。
**真机已闭环**(Win11 ARM64 VM,用随包 `node.exe` 直跑 `dist/sidecar.mjs`,两侧 sha256 一致):
| 组 | 配置 | 结果 |
|---|---|---|
| 对照 | 未配系统代理、**不给任何环境变量**(直连) | **30877ms 失败**,但报的是真实原因 `socket hang up`,`data` 带 `via=直连`/`timeout_ms` 与可操作提示 |
| 实验 | 只设 **WinINET 系统代理**指向转发端点、**仍不给任何环境变量** | **成功 28883ms** → `v2.0.3`、`via_proxy=system`,日志 `(来源 system)`,退出码 0 |
→ 实验组走通的正是本次新增的**系统代理发现**(`reg query` → `来源 system`);
其 28.9s 耗时同时反证旧实现固定 20s 的内部超时对这条链路**必然**失败。
复验后 VM 的 `ProxyEnable`/`ProxyServer` 已**原样还原**。
## Windows 端控制台(2026-10-11)