From 590f62e968ecf91a1a44d982998e734d8efc85fb Mon Sep 17 00:00:00 2001 From: jkooe <62494645+jkooe@users.noreply.github.com> Date: Tue, 13 Oct 2026 22:47:36 +0800 Subject: [PATCH] =?UTF-8?q?docs(changelog):=20=E5=9B=9E=E5=A1=AB=E3=80=8C?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E6=9B=B4=E6=96=B0=E3=80=8D=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=9A=84=E7=9C=9F=E6=9C=BA=E5=A4=8D=E9=AA=8C=E4=B8=8E=E5=AE=88?= =?UTF-8?q?=E5=8D=AB=E5=8F=A3=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 已原样还原。 无代码改动。 --- CHANGELOG.md | 26 ++++++++++++++++++++------ docs/console-plan.md | 16 ++++++++++++++-- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af5c05d..b71a4db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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` 只装在被控端包内, diff --git a/docs/console-plan.md b/docs/console-plan.md index efaa101..303af39 100644 --- a/docs/console-plan.md +++ b/docs/console-plan.md @@ -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)