Files
dsh_shenxian/dsh-server-docs/04-调整方案/44-基础运行时版本冻结.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

4.0 KiB
Raw Blame History

44-基础运行时版本冻结(禁止用户升级 Python/pip/node)(2026-09-11 落地)

背景与动机

用户要求:禁止用户通过任何方式升级 Python 3.12.14 / pip / node 这些基础包, 避免版本差异导致插件功能无法使用。

一、盘点:绝大部分护栏已天然成立(无需新代码)

升级路径 结果 依据
改运行时本体 /usr/local/dsh-runtime/** ❌ /usr 是 ro-bind(实测 touch = Read-only file system)
pip install(默认写平台 site-packages) ❌ 同上
npm install -g / pnpm add -g ❌ /usr/local/lib/node_modules 只读
用 ~/.local/bin 里的 console script ❌ 实例 PATH 固定 /usr/local/bin:/usr/bin:/bin,不含 ~/.local/bin
让 dsh / 插件用自己装的 node ❌ dsh 主进程由 orchestrator spawn,其 PATH 取自 root 环境(scrubEnv),与用户 shell 无关

二、唯一真实缝隙:Python 的 user-site

实测证据:pip install --user 一旦创建 $HOME/.local/lib/python3.12/site-packages, 该目录就会进入 sys.path 且排在平台 site-packages 之前 → 用户装的同名包盖住平台包。实测 import packaging 拿到的是用户版 26.3(ws/.local/...)。 这正是"版本差异导致插件功能不可用"的来源。

注意:初始状态(该目录尚不存在时)user-site 不在 sys.path;是 pip 自己创建目录后才加入的。

三、实现(两条限制性 env,官方机制、互不冲突)

src/supervisor/orchestrator.ts · baseEnv():

PYTHONNOUSERSITE = '1'                                        // user-site 不进 sys.path
PYTHONUSERBASE   = '/usr/local/dsh-runtime/.no-user-install'  // pip --user 写只读位 → 明确报错

src/supervisor/spawn.ts · ALLOWED_ENV 同步放行这两个变量。

两条互相不冲突:PYTHONNOUSERSITE 只管 sys.path,不影响 pip 计算 --user 目标路径; PYTHONUSERBASE 让 --user 的写入落在只读位 → 明确失败而不是"装上了却不生效"。

四、版本漂移巡检

新增 scripts/runtime-baseline.cjs:

  • --accept → 把当前版本写入基线 /opt/dsh/state/runtime-baseline.json;
  • 默认 → 比对,漂移则逐项打印并 exit 1;一致则 ok。
  • cron:/etc/cron.d/dsh-maintenance 每天 05:10 跑,日志 /var/log/dsh-runtime-baseline.log。
  • ⚠️ 有意升级运行时后必须跑 --accept,否则会一直告警。

基线当前值:python3 3.12.14 / pip 26.2.1 / node 22.23.2 / npm 10.9.8 / runtimePinned 3.12.14。

验证记录(沙箱内,uid 100002)

检查 结果
版本基线 python3 3.12.14 / pip 26.2.1 / node v22.23.2 / npm 10.9.8
PYTHONNOUSERSITE / PYTHONUSERBASE 1 / /usr/local/dsh-runtime/.no-user-install
user-site 在 sys.path False
pip install --user 明确拒绝:ERROR: Can not perform a '--user' install. User site-packages are disabled for this Python.
历史污染是否还能盖平台包 ✅ 已失效
pip install --target <ws>/.pylibs + PYTHONPATH ✅ 仍可用(requests 2.34.2)
npm -g / /usr/local/lib/node_modules 只读 ✅
基线巡检 写入 → 第二次比对 ok 运行时版本与基线一致

R5 方向判定

本改动虽触碰 R5 触发文件(spawn.ts 的 ALLOWED_ENV、orchestrator.ts 的 baseEnv), 但方向是收窄(限制用户侧安装能力,不是放开)→ 按 R5 可直接做,已在 commit 与本节留痕。

给用户/AI 的正规替代路径(已写入技能)

需要额外 Python 依赖时:

  • pip install --target <ws>/.pylibs <pkg> + PYTHONPATH=<ws>/.pylibs(实测可用);
  • 或自建 venv(venv 会用平台解释器副本,不影响平台 runtime)。

回滚

删掉 baseEnv 里那两行(及 ALLOWED_ENV 两项)→ npm run build → systemctl restart dshs。 cron 巡检行可单独删除。