Repository navigation
Releases
v0.2.1 — trace 凭据脱敏 · 回调诊断接通 · 回退树实测
三条都来自 docs/ISSUES.md「规范化一轮」的记录,其中第一条是已在真实产生泄露的安全问题。
1. 🔴 ISSUE-13 · trace.log 不再记录引擎工具调用的原标题(安全修复)
- 问题:
<stateDir>/trace.log把 ACP 引擎的工具调用标题原文落盘,实测含mcp_…token、
sk-…API key、账号邮箱与明文密码。这是"出问题就贴进 issue"的那种文件 → 用户分享日志即泄露。 - 修复(三层,缺一层都不够):
- 中央脱敏(唯一落盘点):
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 字段宽)。
放在收口点而不是调用方,是为了让"下一个忘了脱敏的调用方"也过不去。 - 调用方:
acp.tool-call不再记title,改记titleLen(lib/acp-turn-runner.js)。
需要标题正文时看会话日志(产品自己的记录)。 - 开关:新增插件配置
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 个:cordisdsh-agentdsh-llmdsh-scope
dsh-sessionschemastery—— 护栏保护的正是这 6 个。 - 推翻:「
nvm use换版本会让树悬空」是假设;实测不必换版本,244 条里已悬空 47 条
(dsh-acp、dsh-api-*、dsh-chunked-list…)。链接钉死在 nvmv22.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 test84/84(新增 16 例:sink 7 + 脱敏 7 + 配置 2);npm run check通过;
npm run typecheck0 错误(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 — 规范化:按官方/社区规范重构
v0.2.0 — 规范化
按 DSH 官方教程与社区插件规范做的一轮重构:不改运行时行为(除下面明列的两条配置语义变更),
改的是可验证性、可维护性与合规性。
合规
package.json 补齐市场/官方要求的清单字段(dsh.plugin/kind、顶层 engines.dsh、files、
repository);peerDependencies 由 * 改为有界范围;宿主接口包只在 peer+dev 双声明。
配置面
迁到宿主 @deepseek-ai/schemastery 的 Config + 边界/跨字段校验;求值失败降级为
Config === undefined 并留一条可见诊断(响亮降级)。新增三类跨字段告警,
修掉一处静默降级(presetTools 的未知分组以前被无声过滤)。
修掉三个真缺陷
-
profile 的 patch 是整体替换 config —— 一份只写 2 个键的覆盖把 A16 的
promptTimeoutMs: 0静默清掉了,也就是说"防墙钟误杀长任务"在本机从未生效。 -
宿主包解析的假阴性 —— 宿主内解析到
0.2.0-rc.2、宿主外解析到0.1.1-rc.2;现在所有宿主契约结论都必须带解析路径与版本。
-
诊断数据被自己的测试污染 —— 测试会把假宿主事件写进用户的真
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 —— 事件桥在真实会话里工作。
行为变更(明列)
-
配置类型错误现在会硬失败(旧实现对任何非法值都静默回落默认值)。
-
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
逐字节相同 —— 用户安装到的东西没有变化,新版本号只会造成一次无意义的更新提示。