Skip to content

Releases

v0.2.1 — trace 凭据脱敏 · 回调诊断接通 · 回退树实测

Choose a tag to compare

@EJDRONE EJDRONE released this 10 Oct 06:50

三条都来自 docs/ISSUES.md「规范化一轮」的记录,其中第一条是已在真实产生泄露的安全问题。

1. 🔴 ISSUE-13 · trace.log 不再记录引擎工具调用的原标题(安全修复)

  • 问题:<stateDir>/trace.log 把 ACP 引擎的工具调用标题原文落盘,实测含 mcp_… token、
    sk-… API key、账号邮箱与明文密码。这是"出问题就贴进 issue"的那种文件 → 用户分享日志即泄露。
  • 修复(三层,缺一层都不够):
    1. 中央脱敏(唯一落盘点):lib/trace.js 的 trace() 写盘前一律过 redact() ——
      按键名(token/secret/password/apiKey/authorization/bearer/credential/cookie
      → 整值 <redacted>;sessionId 故意不在其列,它是诊断主键)、
      按值的形状(sk-…/mcp_…/gh?…/xox…/AKIA…/PEM/JWT/Bearer …/
      自由文本里的 token=…·--password …·密码 <值>/邮箱 → <email>)、
      以及长度上限(单串 300 字符、6 层深、40 字段宽)。
      放在收口点而不是调用方,是为了让"下一个忘了脱敏的调用方"也过不去。
    2. 调用方:acp.tool-call 不再记 title,改记 titleLen(lib/acp-turn-runner.js)。
      需要标题正文时看会话日志(产品自己的记录)。
    3. 开关:新增插件配置 trace = true(默认) / false·'off' / '<path>'。
      Desktop 用户改不了环境变量(从快捷方式启动),所以配置是唯一可及开关;
      DSH_MULTI_ACP_TRACE 仍生效,优先级 config > env > 默认。
  • 新测试:test/trace-redaction.test.mjs(7 例)—— 含"真实泄漏形状"用例与
    "非敏感字段必须原样保留"(脱敏不得毁掉诊断能力)。凭据一律用合成替身(AGENTS.md §8)。
  • ⚠️ 历史文件须自行处置(修复只挡新写入):本机
    trace.log.bak-20261010-105701-pre-issue13(464KB)仍含 196 条 title,
    其中 4 个 mcp_ token / 6 个 sk- key / 2 个邮箱。它是用户的备份,
    本插件不擅自动它 —— 建议删除并轮换那些 key。现存 trace.log 已核对为干净(5 条遗留 title
    均 9 字符、无凭据形状)。

2. 🟡 ISSUE-17 · "客户端回调计数"从两端都断改为接通

  • 补测发现:不只是那个 phantom 的 rawLines.recordCallback ——
    AcpClient._sinkCounts 创建后从未被读写,sink.counts 也零读者。
    整条通道是"建造但未连接"。
  • 接线:未知回调计入同一张表 → unknown:<回调名>(与既有 sessionUpdate:<类型> 并列),
    只记名字与次数、不记 args(args 可能含凭据)。AcpClient 持活引用,
    经 capabilities().callbacks → tryConnect 试连报告 → GET /engines 能力快照
    (lib/routes.js 显式加进白名单,避免又被静默丢弃)。
  • phantom 参数 rawLines 已从签名与 JSDoc 删除;createCallbackSink 改为导出(仅供测试/诊断),
    新增 test/acp-callback-sink.test.mjs(7 例,其中 2 例钉住安全默认:
    无 onPermission 必须拒绝、无 fs handler 必须如实回空并记警告)。
  • 有意未做:UI 未单独渲染这段计数(数据已在 API 面上,渲染是产品选择,不为"看起来被用上"改 UI)。

3. 🟠 ISSUE-14 · 宿主外回退树:实测推翻了 Issue 里的假设

诊断脚本新增「回退树审计」段(--json → fallbackTrees)。实测(本机,--expect 0.2.0-rc.2):

树 顶层条目 @deepseek-ai 链接 悬空 过期
<profile>/node_modules 404 3 0 0 3
<DSH_HOME>/profiles/node_modules(共享) 200 244 244 47 197
  • 旧版宿主包来自共享树(不是 profile 本地那 3 条实目录);
    本仓库实际会解析到且过期的只有 6 个:cordis dsh-agent dsh-llm dsh-scope
    dsh-session schemastery —— 护栏保护的正是这 6 个。
  • 推翻:「nvm use 换版本会让树悬空」是假设;实测不必换版本,244 条里已悬空 47 条
    (dsh-acp、dsh-api-*、dsh-chunked-list …)。链接钉死在 nvm v22.20.0,active 是 v24.21.0。
  • 未测(明确标注):那 47 个名字是否被任何已装插件消费(宿主 loader 领域,ADR-0003 禁止手工改树)。
    本仓库自身解析路径不受影响。
  • 处置仍是"不手工改那棵树"(DSH 维护、40+ 插件共享)—— 本轮只增加测量能力。

4. 文档与配置面

  • README.md:配置表新增 trace 行 + 「诊断追踪与脱敏」小节(脱敏口径写全)。
  • CONTEXT.md:新增术语 回退树(Fallback Tree),新增 §六 安全(中央脱敏 / 诊断开关)。
  • cordis.patch.yml:按同文件既有风格注明 trace 开关与其在两个 nvm/patch 场景下的注意事项。

5. 验证

  • npm test 84/84(新增 16 例:sink 7 + 脱敏 7 + 配置 2);npm run check 通过;
    npm run typecheck 0 错误(CI 阻断项)。
  • 真实会话证据(AGENTS.md §3):宿主 apply.enter + install.factory-installed 见
    2026-10-10T06:28:44Z(= 本机 14:28:44,与 load-report.txt 一致)→ 运行实例已是本版代码;
    随后真实 omp 会话 session-65c90bfa-e3d1-4438-b75e-58f7a0549766(4 个 MCP 继承、
    权限档 workspace-write-asks)在 06:36–06:40Z 产生 7 次 acp.tool-call
    (kind=read/search/execute),trace 里是 titleLen=46/39/49/37/37/87/112、无 title
    —— 即"只记元数据"在真机上生效。
  • 另做真实数据回放:把本机 136 行真实 trace.log 逐行过一遍新 trace() →
    0 个字段被改动(证明脱敏不破坏诊断);现存 trace 里凭据形状计数 = 0。
  • 硬链接同步:tools/install.ps1 -Sync 已跑;逐文件核对 repo ↔ 安装副本同 inode 同内容
    (lib/* + package.json + cordis.patch.yml),安装副本版本 = 0.2.1。

v0.2.0 — 规范化:按官方/社区规范重构

Choose a tag to compare

@EJDRONE EJDRONE released this 10 Oct 04:18

v0.2.0 — 规范化

按 DSH 官方教程与社区插件规范做的一轮重构:不改运行时行为(除下面明列的两条配置语义变更),

改的是可验证性、可维护性与合规性。

合规

package.json 补齐市场/官方要求的清单字段(dsh.plugin/kind、顶层 engines.dsh、files、

repository);peerDependencies 由 * 改为有界范围;宿主接口包只在 peer+dev 双声明。

配置面

迁到宿主 @deepseek-ai/schemastery 的 Config + 边界/跨字段校验;求值失败降级为

Config === undefined 并留一条可见诊断(响亮降级)。新增三类跨字段告警,

修掉一处静默降级(presetTools 的未知分组以前被无声过滤)。

修掉三个真缺陷

  1. profile 的 patch 是整体替换 config —— 一份只写 2 个键的覆盖把 A16 的

    promptTimeoutMs: 0 静默清掉了,也就是说"防墙钟误杀长任务"在本机从未生效。

  2. 宿主包解析的假阴性 —— 宿主内解析到 0.2.0-rc.2、宿主外解析到 0.1.1-rc.2;

    现在所有宿主契约结论都必须带解析路径与版本。

  3. 诊断数据被自己的测试污染 —— 测试会把假宿主事件写进用户的真 trace.log,

    曾让我误判"宿主返回了无法识别的形状",差点放宽一处本来正确的护栏。

类型与结构

  • typecheck 基线 43 → 0,并进 CI 阻断。

  • acp-agent.js(1916 行)拆为 5 个模块:acp-factory / acp-agent(装配)/

    acp-turn-runner(事件桥)/ acp-inbox / agent-contract。

  • 删 4 处死代码。

  • client.js 经评估后不拆(加载器契约决定,拆文件必须引入构建步骤 —— 见 ADR-0005 补记)。

测试与 CI

  • 新增 test/:68 例 node --test(纯函数 / 配置面 / 浏览器 bundle 契约 / 装配冒烟 / 回归)。

  • 新增 CI:test(Node 22/24)+ typecheck 阻断;官方安装路径冒烟(ubuntu)非阻断。

真实会话复验

session-eca8ba23… 由 omp 驱动:MCP 4/4 注入、权限档已映射、上报 166 条引擎命令、

acp.tool-call ×4 —— 事件桥在真实会话里工作。

行为变更(明列)

  1. 配置类型错误现在会硬失败(旧实现对任何非法值都静默回落默认值)。

  2. presetTools 的未知分组从静默丢弃变为告警。

已知未修

<stateDir>/trace.log 会记录引擎工具调用的原标题,其中可能含 token 与明文密码

(docs/ISSUES.md ISSUE-13)。


详见 CHANGELOG.md ·

开发约束见 AGENTS.md ·

术语见 CONTEXT.md ·

决策见 docs/adr/


附注(发布后,2026-10-10)

  • 本 tag 的 CI 运行里 官方安装路径冒烟 这一项失败(非阻断)—— 根因是 runner 上没有 pnpm,
    而 dsh plugin … add 会把它转发给 pnpm:dsh: pnpm was not found → exit 127。
    profile 初始化本身是成功的,连本包都还没被评估到,所以不是打包问题。
    修复见 main 的 fae47d2(工作流加一步 npm i -g pnpm@11.7.0)。修复后的运行该项已绿:
    官方管线能装进干净 web profile,且 --dump-config 与 profile 的 bundles 都验证过。
  • 未为此新开 0.2.1:该提交只改工作流,lib/ / package.json / cordis.patch.yml 与 v0.2.0
    逐字节相同 —— 用户安装到的东西没有变化,新版本号只会造成一次无意义的更新提示。