Files
admin e6207aa691
build / build-and-scan (push) Waiting to run
chore(仓库对齐): 文档库结构治理 + IM/插件线落地
文档库:目录改为编号制(01-规范/02-架构设计/03-数据库/04-调整方案/
05-交接单/06-ops/07-scripts/08-skills/09-archive),顶层散文件归入 01-规范/;
INDEX.md 与 docs-manifest.json 重刷(档案 146 篇);旧目录名引用全量对齐。

IM 线:src/im/**(SDK / hub / store / presence / ws / gateway-token)、
src/web/routes/im.ts、src/db/plugin-data/**、src/supervisor/plugin-assembly.ts
及对应 test/**。

插件线:poc/{im-agent-bridge,im-connection-gateway,im-conversation-tabs,
business-plugins-im,carbon-mcp-probe}、src/web/routes/{sessions,overlay-device}.ts、
src/net/relay/{device-grant,instance-credential}.ts。

仓库卫生:清出 40 个历史误入库 / 已改名文件(34 个交接单归档 + 6 个旧结构,
本地均有副本);dsh-server-docs/.gitignore 补 tmp/;交接单不入库(政策)。
2026-09-24 07:25:16 +08:00

128 lines
32 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 03 路线图与待办
> 状态(刷新 · 2026-09-12 15:05):本文件长期晚于实际进度(此前停在 09-11 23:05)→ 本次补登记**档案 57–68**、清理已完成行、并把待办口径与 `05-交接单/README.md §一` 对齐(**已规划待执行的以交接单为准**,本文件只保留指针)。原文:**2026-09-11 21:20 合并版**(补回 14~22 与 B1/B2/B3/B4、档案 28、备份加固;保留「MCN 改造暂缓」「白名单源码安装」等新决策)。
## 一、待验证项(Open Questions)结论
| # | 原问题 | 结论(实测日期) |
|---|---|---|
| 1 | `.env` 注入 `DEEPSEEK_API_KEY` vs 用户个人 key 优先级 | ✅ 已定:**统一 admin key 模型**(commit df5cc84,2026-09-09)——resolveApiKey 忽略 userId、取 role=admin 启用 key,spawn env 注入;keys 路由 requireAdmin;无"个人 key 覆盖"场景 |
| 2 | web profile 空 `.dsh` 首启自动初始化(add-user 流程) | ✅ 已解答:dshs 模式无此问题——provision 建 OS 账号 + profile 首次 spawn 即自动初始化;testuser 注册→审核→桌面→DSH 全链路已实测通过 |
| 3 | 前端 loopback 检测能否 `--patch` 放行(用户自配模型) | ✅ 已实测(2026-09-09):proxy.ts 将 Host 伪装为 `127.0.0.1:<port>` → dsh 的 /api trust fence 与 loopback 特权校验**全放行**,Settings 面板在门户代理后可用 → **暴露面成立:登录用户可进 Settings 自配 key/模型**,作为已知安全边界记录(第二道防线),暂无封锁需求 |
| 4 | dshs 对 web Settings 限制 | ✅ 同上实测:Settings 面板可用(portal-entry v0.4.1「平台管理」分区即在此验证) |
| 5 | 容器内 `dsh plugin add` 走 npmmirror | ⏹ 过时归档:架构切换后插件走**宿主全局 dsh + profile 层 pnpm 转发**(`dsh plugin --profile web`);装法 = 本地 `npm pack` 出 tgz → `dsh plugin add <tgz>`(实测 v0.1.0→v0.4.1 全链路) |
## 二、路线图
### 已完成(2026-09-08 ~ 09-09)
- [x] **P0 迁移**:data → users/main(2026-09-08 17:30)
- [x] **P2 调研**:dshs 选型前置调研(2026-09-08)
- [x] **域名接入 + 通配 HTTPS**:dsh.alotbuy.com 通配证书(2026-09-08 18:00-18:40,certbot dns-cloudflare)
- [x] **架构切换**:dshs 多租户 + account 硬隔离(2026-09-08 18:30)
- [x] **登录直达 v1+v2**:POST /api/dsh/enter 按角色分流 + token 自动携带(commit 6f63108 / e39628a / 29c8907)
- [x] **统一 KEY 管理员管控**(df5cc84)
- [x] **用户管理**:注册/审核/删除用户(4943c8c)+ 权限收紧(chmod 系列)
- [x] **实例生命周期**:last-wins 单活跃会话 + idle-reap 常驻上限(928dde1 / 6336c53)
- [x] **门户功能插件化 PoC**:`@dsh-local/portal-entry` v0.4.1 浏览器验收通过(2026-09-09)——设置面板「平台管理」分区(门户地址 + 打开管理台 + 退出登录),档案 05
- [x] **技能管理面**:共享 + 个人技能 API 与页面、zip-only 两阶段替换(2026-09-09,档案 11)
- [x] **文档库路径统一(2026-09-10)**:工作区 `D:\AgentSkill\aliyun-work-space` → `D:\AI技能\aliyun-work-space`;文档目录 `dsh-docker\docs\` → **`dsh-server-docs\`(内容提升到根,与服务器 `/opt/dsh/docs` 同构)**;6 处旧路径改写 + 双端同步,25/25 md5 一致;对账脚本 `07-scripts/docs-sync-check.sh` 落地
- [x] **工作区迁移 D: → E:(2026-09-13)**:工作区 `D:\AI技能\aliyun-dsh-server` → **`E:\ProgramData\AI技能\aliyun-dsh-server`**(`D:\AI技能` 已无实体目录)。同步改的**活路径**:`~/.workbuddy/settings.json`(两个 hook 命令)、`dsh-server-docs/07-scripts/lock-guard-hook.py`(`DSH_DOCS_ROOT` 默认值)、`07-scripts/docs-sync-check.sh`(`DOCS_LOCAL_DIR` 默认值,本库 + 项目根共两份)、`dsh-server-docs/07-scripts/extract-user-voice.py`(目录名示例)、`dsh-server-docs/README.md` 与 `INDEX.md` 的本机路径、档案 73 的 hook 安装片段。**历史档案(01-规范/01-规划与架构 / 04-11 / 04-12 / 09-archive/ 下各篇)中的 `D:\AI技能\...` 保留原值**(写于迁移前,属历史,按「档案只增不改」不回改)。**代码仓 `D:\github\dsh_shenxian` 未变动**(不在 `AI技能` 之下)。
⚠️ 排查期间曾临时建 `D:/AI技能 → E:/ProgramData/AI技能` 目录联接,用于救活**会话启动时快照**里已失效的旧 hook 路径;**已按用户要求移除**。⇒ **改 hook 路径后,已在跑的会话需「完全重启」(关窗 ≠ 退出)或新开会话才生效**(2026-09-13 实测:本会话 06:47 启动、06:55 改配置,07:05 拆联接后写操作仍报旧路径)。
- [x] **档案 78 · 崩溃熔断冷却期与告警(2026-09-13)**:修 **档案 77 §八 遗留 1** —— 原实现熔断即 `resetCrashState()` 清预算 ⇒ 只要有重试路径(用户 F5 / 注入脚本自愈 / 脚本直铺)崩溃循环就能**无限重来**,且只留一行 stderr。改为:熔断态**跨轮存活** + **指数冷却**(10 min → 封顶 6 h),冷却期内 `launch()` 拒绝隐式启动(HTTP 503 `instance_circuit_open`),冷却过后只给**一次**干净预算;熔断**双通道告警**(stderr + `/var/log/dsh-crash-breaker.log`)并把 `breaker` 暴露到 `/api/dsh/status`。改 6 个文件(含 3 条新单测);`npm run build` rc=0、`npm test` **45 pass / 0 fail**。**已部署并验证**(2026-09-13 08:02 重启载入:PID 410287→413817、门户 200、孤儿 scope 0、`/api/dsh/status` 返回新字段 `breaker`)→ 档案 78 §九
- [x] **登录直达冷启动竞态 404 修复(2026-09-10)**:enter 复用/AlreadyRunning 分支等 launch token 到位再返回 URL,杜绝启动窗口 404(commit `fa718d2`,档案 13)
- [x] **敏感信息暴露面审计与加固(2026-09-10,档案 14)**:判定跨租户/提权不成立;封云元数据端点 `100.100.100.200` + 外联观测(`/etc/nftables-dsh-egress.nft` + `dsh-egress.service`)
- [x] **会话失效 401 未跳登录页修复(2026-09-10,档案 15)**:desktop/admin/skills 三页注入 401 守卫;核心插件开关收归 admin
- [x] **页面导航定稿 + 插件三层归属(2026-09-10,档案 16)**:门户 SPA 化、技能/插件独立页面、功能插件候选池投放 + 实例设置启停;阶段 0-2 已实施(`bad6ed7`/`6f86a5f`/`b7fd85d`)
- [x] **实例沙箱隔离(档案 16)**:bwrap + systemd-run scope(512M/CPU 150%/TasksMax 128)+ 私有 /tmp + `--unshare-pid`(commit `449f28b`)
- [x] **工作区选择器暴露面核查(2026-09-10,档案 17)**:判定非越权;记录 P1 写边界=会话 cwd / P2 picker 无根白名单 / P3 nft 文件可读
- [x] **文档库去重 + 单一来源(2026-09-10,档案 19 §D4)**:删根级 05 副本、`04/README.md` 改指针
- [x] **崩溃自愈加固(2026-09-11,档案 20)**:指数退避 + 窗口熔断(5 次/10 min)+ 观测(`restarts`/`lastCrashedAt`)+ handoff 停写;**live 自愈实测通过**(kill → 1 s 后 `[crash-restart]` 拉起);commit `7cba3e3`
- [x] **CI 脚本 + 清理失效 smoke(2026-09-11,档案 19 §C3)**:新增 `07-scripts/ci.sh`;删 `smoke-plugins.mjs`(目标路由已移除)与 `smoke-watchdog.mjs`(watchdog 从不启动)
- [x] **访问域名迁移(2026-09-11,档案 22)**:门户 `alotbuy.com` + 用户 `<用户名>.alotbuy.com`;通配证书 DNS-01(传播 60 s)、CF 真实 IP 还原、旧域 301 含用户名映射
- [x] **nginx 性能修复(2026-09-11,档案 21)**:`proxy_buffering off`(修「一次性输出」)、`gzip_proxied any`(930 KB bundle 压缩)、`/assets/` 30d 缓存
- [x] **官方白名单插件来源(2026-09-11,档案 29)**:门户「插件管理」接入 awesome-dsh-plugin 官方目录(`plugins.json`,3408 条 / 23 分类),admin 搜索/筛选/多选 → 导入功能插件候选池;导入口径 = **仅预构建**(npm registry tarball / release 资产),可导入 **1792 条(52.6%)**、热门插件全覆盖,平台侧不执行任何第三方构建脚本
- [x] **编排器孤儿实例清理(2026-09-11,档案 30)**:spawn 前清 `dsh-<uid>-*` 孤儿 + 启动时清一次;两场景 live 验证通过
- [x] **档案 14~22 全部落地(2026-09-10~11)**:敏感信息暴露面审计(封云元数据端点 + 外联观测)、会话失效 401 跳登录、页面导航定稿 + 功能插件三层归属、实例沙箱隔离(bwrap+scope)、工作区可见面核查、目录选择器收敛 v3、崩溃自愈(退避+熔断+观测)、CI 脚本、**访问域名迁移到 alotbuy.com**(旧域 301)、nginx 性能修复(buffering/gzip/assets)
- [x] **写保护 B1(档案 17 §P1)**:实例内 `--ro-bind-try` 覆盖 `cordis.patch.yml`/`package.json`/`pnpm-lock.yaml`(写测试 ✅ + 真实 dsh 启动验证 ✅)
- [x] **编排器自愈 B2(档案 18 收尾)**:`ensurePickerProfile(userId)` 在 launch 前 + spawn 后各异步补齐(幂等)
- [x] **上传安全扫描分级 B4(档案 19 §C6)**:P0 阻断 / P1 告警 + 扩展名 19→31 + shebang/二进制/8MB(冒烟通过)
- [x] **死代码子集 B3(档案 19 §C5)**:删 `src/runtime.ts`;`folder_plugins`/`workspaces` 加废弃注释(**完整版清理已关闭**:跨 10 文件且含 k8s/PG 未验证路径,删除风险不对称)
- [x] **用户数据清理三件套(档案 28)**:`ws-cleanup`(T1 平台产物 / T2 顶层一次性脚本 >90 天 / T3 永不删)+ `session-gc`(**365 天**保留)+ `purge-trash`(回收站 30 天)+ 每小时用量快照 + 门户「存储用量」面板(`GET /api/admin/storage`)
- [x] **备份可用性修复(档案 02 附录 C.8)**:发现 `backup.sh` **无执行权限且未调度**(最后备份停在 09-08)→ 修好 + SQLite 一致性快照 + 纳入 artifacts/07-scripts/cron/nginx vhost + `/etc/cron.d/dsh-backup` 每周日 05:00(恢复演练已验证)
### 已完成(2026-09-11 ~ 09-12,本次补登记 57–68)
- [x] **档案 57 · 设置面板「用户管理」入口 + 全员安装**(2026-09-12 00:04)
- [x] **档案 58 · 实例内存优化与配额下调**:512M → **384 MiB** + 编译缓存(2026-09-12 00:23)
- [x] **档案 59 · 重连反馈:实例启动中的加载动画**(2026-09-12 01:30)|⚠️ 遗留:`wake.html` 本机 4708B vs 服务器 4591B **待核对同步**
- [x] **档案 60 · 设置面板分区改名「功能插件」→「功能管理」**(2026-09-12 08:30)
- [x] **档案 61 · 插件管理页官方插件列表加高 + 底部留白 200px**(2026-09-12 09:14)
- [x] **档案 62 · 插件目录缓存状态可见化 + 「重新拉取目录」按钮**(2026-09-12 09:21,`be42155`)
- [x] **档案 73 · 让锁真正拦得住人**(2026-09-12 17:0x):复盘发现三把锁**当天被跳过两次**(含本会话)→ 根因①无强制入口(`settings.json` hooks 段为 null)②guard 输出「无锁」被读成「可以开工」。治:① 措辞修正(guard 三处 + 交接单语义)② `07-scripts/lock-guard-hook.py`(PreToolUse 无锁拒写 + SessionStart 提示,**作用域仅本库/本代码库**;四态单点验证通过);⚠️ 钩子待用户在 `/hooks` 审核启用
- [x] **档案 72 · 实例回收/关闭后回到页面自动唤醒并重建连接**(2026-09-12 16:55,`b23e386`):注入脚本原来只认 401,实例回收时代理返回的 `404 not_running` 无人处理 → 用户必须手动刷新。补:① `hit()` 识别 not_running ② `visibilitychange`/`focus`/`pageshow` 时主动探活 `/api/dsh/status` ③ `recover()` 跳 `wake.html`(走 `enter` 拿**新 token**,避免 reload 带旧 token 再撞 401)
- [x] **档案 71 · 插件兼容性预检:导入 / 上传即判定**(2026-09-12 16:35,`8d19e89`):semver 依赖范围 + 运行时导出符号比对,不兼容在导入时即拒收(承接档案 70 的教训)→ 方案 `04-71`
- [x] **档案 70 收尾 · AnySearch 彻底放弃 + 候选池存量体检**(2026-09-12 18:56):用户选 B → 下架 anysearch(`audit` 175);**顺手发现预检只覆盖"新导入"、覆盖不到存量** → 用 `lib/web/plugin-compat.js` 体检池内两条:`dsh-univer-office` = `ok`(保留)、`@liustack/modlens` = `unknown` 且有 `plugin_incident`(audit 172/173)→ 一并下架(`audit` 176,tgz 备份 `/opt/dsh/backups/plugin-pool-20260912/`)。全程**未重启服务、未中断用户**。另落 **R9 红线**(禁止人工删锁/接管)→ 档案 70 §九 · 档案 73 §十一
- [x] **档案 70 · anysearch 插件与 dsh `0.1.2-rc.1` 不兼容 → admin 实例崩溃循环**(2026-09-12 15:32 **已止损**):根因 = 插件在 import 阶段引用 `@deepseek-ai/dsh-llm` 未导出的 `assertNever`,而 dsh 的 plugin tree 加载**全或无** → 启动中止、崩溃自愈反复重启;摘掉该 bundle 即恢复。**✅ 该待办已于 2026-09-12 18:56 关闭**:用户选 B · **彻底放弃**(候选池条目下架 + 存量体检)→ 见本节「档案 70 收尾」行与 §二 待办表「已处置」行
- [x] **档案 69 · 并发治理落地(T04)**(2026-09-12 15:10,`exec-session-C`):文档库 commit 常态化 + 服务器侧操作锁 `/opt/dsh/state/.op-lock/`(实测往返通过)+ 交接单目录权限统一;三把锁进预检脚本 → 单子已归档
- [x] **编号 63 为空号**:该号只出现在当日工作日志的「事故 63」里(清理残留 tgz 致依赖断裂),**无对应档案**,勿补占
- [x] **档案 64 · 接入 AnySearch 搜索 provider(B 方案)**(2026-09-12):平台现用 DeepSeek 官方搜索;AnySearch 前置验证 4 项全绿、**admin 侧已实施**;⚠️ 待办改以**档案 65 §7.3** 为准 —— **2026-09-12 用户拍板:三方插件一律走「admin 导入候选池 → 用户自助启用」,不再向用户 profile 直铺**(§8.3 第 2 条直铺命令已作废)
- [x] **档案 65 · 功能插件启停 ↔ web provider 配置联动**(2026-09-12):根治「候选池一禁用就 `CONFIGURED_MISSING`」→ 平台按当前 bundles **重算托管段**,启/禁两态皆正确;**代码完成 + 两态实测,⏸ 待部署(需 R8 窗口)**
- [x] **档案 66 · 业务插件 P0 误报 → admin 显式信任**(2026-09-12 11:15 已部署):安全检测改 **fail-closed + 逐条回显 + admin 声明信任后放行并留痕**
- [x] **档案 67 · 「功能管理」section 按 UI 规范重做(v0.2.4)**(2026-09-12):用途说明做主视觉 + 字号/组件对齐 `06`
- [x] **档案 68 · 候选池启停的 root 属主污染根治**(2026-09-12):候选池 `install/uninstall` 改 **`setpriv` 降权** + 改插件前自动属主自愈 + 清存量 **561** 项;附带修 `npm pack` 把上一版 tgz 打进产物(加 `.npmignore`)
### 进行中 / 待办
| 优先级 | 事项 | 说明 |
|---|---|---|
| ✅ **已完成** | ~~**档案 65 部署**(功能插件启停 ↔ web provider 托管段联动)~~ | **本就是生效状态**:服务器 `lib/` 00:13 构建 → **00:15:23 重启即已载入**(08:02 再载入);**§7.3 第 3 条已完成**(`ensure-anysearch-admin.cjs` 加硬拦退役,默认 `exit 2`,备份 `.bak-retire-20260913`)|
| ✅ **已完成(留一项 L1)** | ~~**档案 78 部署**(崩溃熔断冷却 + 告警)~~ | **2026-09-13 08:02 已部署并验证**(见档案 78 §九)。**遗留 L1**:故意把实例反复搞崩以验熔断(需 6 次真崩 + 该用户冷却 10 min)→ **留维护窗口**做 |
| ✅ **已完成并归档**(2026-09-13 18:0x) | **T03 · 7 插件整合投放** | **guest 启用已成功**(任务 `c20739a6dbe8975c`:`success`/`restarted=true`;配额自动 672→**800 MiB**); **admin 侧 8 项实证通过**(包结构 v0.3.9 / 上传扫描 P0=0 / 池内 / `[mcn-suite] loaded` 且 duplicate=0 / 旧 7 包已下架 / 技能落 `<home>/08-skills/mcn-short-video` / 幂等跳过 / BRIEF 384M);**剩 6 项需浏览器或造场景**(D 入口逐个点开 / J agent 按名加载 / L 凭据扫描 / N 死引用扫描 / P·Q 撞名三场景)→ 见 `05-交接单/T03` §九 |
| ✅ **已消解(无需窗口)** | ~~**实例内存预算上调**(`--max-old-space-size` 160→256 + cgroup `MemoryMax` 384→512 MiB)~~ | **2026-09-13 13:3x 实测:R1-④ 已把它改成「按插件集合动态计算」,比原方案更优** —— `instanceMemMb()` = 160 + Σ插件预估(clamp 384–1024),`heapMbFor()` = 配额 − 96(cap 256)。运行中实证:guest `NODE_OPTIONS=--max-old-space-size=256` / scope `MemoryMax=544 MiB`(= 160 + univer 384);**admin 也是 256**(不再是 160)。平台 env 里那个写死的 `160` 已被代码侧 `withHeap()` 覆盖、**不是生效值**。⇒ **T03 的 guest 启用不再被容量阻塞**(装上 mcn-suite 后配额会自动变 672 MiB)。原「须重启服务(R8)」的前提已不成立 |
| 🟡 **待排期** | **档案 81 重构总纲的 R2/R4/R5**(**R0/R1/R3 已完成**) | **R2** 管理面就地化 → 🚧 **代码已完成(2026-09-13 17:5x,档案 82)**:插件 `@dsh-local/business-plugins` **0.2.8→0.2.9**,新增原生「平台管理」只读分区(仅 admin;数据调平台只读 API;写操作回跳管理台);`node --check` 通过、tgz 已出;**待投放 + 启用 + 浏览器验收(卡在需 admin 登录态)**;`/admin` 路由族与删 3 桩页**仍未做**。⚠️ **形态已改定(2026-09-13 用户):用「原生弹窗」,不用 iframe**(原话「iframe 不如原生弹窗体验好」)⇒ 改为**在自研插件里原生渲染只读子集**(调平台 `/api/*`,非 iframe 嵌 `portal.html`);仍按 R5 只读优先,登录后 30 天内无需重做门户全量 UI ⇒ 见档案 81 §9.2 修正|**R3** 内部标识统一为 **`dshs`** → ✅ **已完成(2026-09-13 15:4x–16:0x)**:代码 89 文件 / 382 处 + 本机其余 135 文件 / 863 处 + **服务器原子切换**(单元真名 `dshs.service`、`/etc/dshs.env`、`/opt/dshs`、`/var/lib/dshs`、`dshs.db`;含 **WAL 归位**与 DB **VACUUM**);上游具名引用全清(含移除 `git remote upstream`);两仓 git 历史已删重建为单提交|**R4** 文档/代码同仓 → ⏸ **待用户选 a(并入代码仓)/ b(单向导出)**(用户 09-13 反馈「没看懂 R4 要做什么」⇒ 需先讲清动机再选)|**R5** **多语言 i18n** → ✅ **方案已定(2026-09-13 用户):「匹配 dsh 官方方案」= 走官方 locale 体系**(`ctx.locale.addLanguage()` + `register(ns)`,平台页/注入层/自研插件全走官方扩展点、**零官方改动**);⚠️ 覆盖率边界见档案 81 §10.7 ⑥ —— 官方**仍有 20+ 个 UI 包未迁 locale**,那些包切语言不变(属官方自己的待办,不为我们可改范围)|
| ✅ **已修复并验收**(2026-09-13 17:2x) | ~~**档案 76 · `/univer-api/state` 生产持续 400**~~ | **本会话独立复核**:近 2 小时 400 = **0**、近 30 分钟 6 次请求**无 400**;实例 env `UNIVER_DSH_GATEWAY_SOCKET=auto` 已生效(档案 76 追加节=真因+修复+验收)。原述 2026-09-13 07:36 实测:guest 用户在 1 秒内被连续 ~10 次 400(平台侧只记状态码)→ **根因待取响应体**;⚠️ 同时发现 **guest `ws` 下 0 个 `.univer` 文件**(目录在、文件不在)→ 需沿「MCN 生成 `.univer` → Univer 打开」链路查 → 档案 76 追加节 |
| ✅ **已处置** | ~~AnySearch 能力是否保留~~(档案 70 §八) | **用户选 B · 彻底放弃**(2026-09-12 18:56):候选池条目已下架(HTTP 200 / `audit` 175)、凭据无残留、无用户启用过;**顺带体检池内存量** → `dsh-univer-office` = `ok`(保留)、`@liustack/modlens` = `unknown` + 有 incident → 一并下架(`audit` 176,tgz 已备份)。**未重启服务、未中断用户** → 档案 70 §九 |
| ✅ 已完成 | **T05 · 插件兼容性预检**(导入/上传即判定兼容性) | 2026-09-12 16:35 落地(`8d19e89`):判据模块 + 上传/导入双入口接入 + build + 重启;验收全绿 → 方案 `04-71`,单子已归档 |
| **档案内挂起** | 档案 57 四项(picker store 隐患/dep spec 指向 `ws` 会被清理/`portal_ping` 失效工具/插件源码两处存放)|~~档案 59 `wake.html` 本机 4708B vs 服务器 4591B 待核对同步~~ ✅ **2026-09-13 09:4x 实测双端一致**(均 4962 字节、md5 `00b81728…`;变大是因档案 78 给 wake.html 加了熔断文案)|档案 66 三项(官方目录**批量导入**未接信任入口/信任状态未持久化→建议并入 migration v6/`ensure-anysearch-admin.cjs` 覆写段待退役,否则与档案 65 托管段互相覆盖)|档案 68 平台 setpriv 路径待用户会话自然验证|档案 42 三项(③ **已闭环并实测通过**:子代理派发 `bash -c 'echo subagent-ok'` 正常返回 ⇒ shell 可用、平台零改动;见档案 42 末「追加结论 + 实测结果」)/档案 38b 三项/档案 15(`admin.html` 缺页面层 role 拦截)/档案 32(`dsh-market` 可绕过第三层管控,**未成档**) | 详见各档案 §待办段 |
| ✅ **已修复并部署** | ~~**插件启停的两处平台缺陷(档案 79)**~~ | **2026-09-13 13:4x 逐条核实产物(档案 79 §七)**:**D1** `await uninstall(…)` ✅(产物 `:587`/`:617`)|**D2** `remove` 已改 `-w`(`:575`,全仓无效 flag 仅剩 `add` 一处=合法)✅|**加固 a** 路由外层 `.catch()` ✅(`:613`+`:718`)。**D3 已消解**:R1-④ 把堆限与 `MemoryMax` 改为按插件集合动态计算(实测 guest `heap 256` / `MemoryMax 544 MiB`)⇒ 不再需要窗口。⚠️ **仍缺端到端验收**(重现「注定失败的启用」→ 期望 任务 `failed` + profile 回滚 + 服务不退出)→ 建议与 T03 的 guest 启用合并验。**加固 b**(半应用态主动自愈)未做,可选 |
| 触发式 | dsh 升级回归(档案 26 六类耦合点)|会话 GC | 升级 / 容量触发 |
| P3 | 门户「浏览文件」补下载入口 | 档案 56 §七:门户 `#/files` 目前只能列表/上传,可复用 `/api/fs/download` 加"下载"按钮 |
| ✅ | ~~老会话权限档位对齐(检测 + 提示)~~(档案 56) | **已完成(2026-09-11)**:`GET /api/dsh/session-permission` + 实例页顶部提示条(说明原因 + 切档位/新建会话两条路);实测 `stale=true` 触发正常。**不自动改档位**(安全语义变更需用户知情) | 档案 55:档位是**会话级播种** —— 09-10 及更早的会话仍 `workspace-write` → 沙箱 fail-closed,**bash 被拒 11 次**(实测:同一会话 22:16 手动切 `danger-full-access` 后立刻恢复)。建议 `/api/dsh/enter` 检测会话 preset 与平台默认不一致 → **页面提示 + 一键切换**(不自动改) |
| ✅ | ~~实例能力清单(自检)~~(档案 56) | **已完成(2026-09-11)**:`07-scripts/gen-capabilities.cjs`(cron 每日)→ `/opt/dsh/state/capabilities.json` + 共享技能 `platform-capabilities`(agent 可读);实例页「🧭 能力」面板同源展示 | 档案 55:agent 在 16:48 / 18:21 / 22:14 **三轮重复现场探测**,每次撞同样 4 类墙(`/etc` 白名单 / `127.0.0.1` 被 SSRF 拒 / skill 不存在 / 写边界),用户随之三次追问"能力有变化吗" → 平台注入能力说明(可读可写范围、网络边界、工具与技能清单、档位含义) |
| ✅已定 | 平台技能投放现状对齐 | **结论(用户原话):「业务技能要打包进插件里一起安装和使用,不要分开管理」** → 投放方式 = **随功能插件包投放**(见 `05-交接单/T03` §4.1),**不走**门户技能管理单独投放;平台自描述技能 `platform-capabilities` 照旧共享投放。「是否投放待定」的旧表述作废(档案 55 当时的背景是 `bundled-skills` 为空 → agent 撞 `unknown skill`) |
| ❌复核 | ~~管理类插件化~~(档案 05 PoC-2 ①) | **复核结论:不建议做** —— 门户 `portal.html` 已有完整管理面(服务/密钥/用户/技能/插件/运行环境),admin 在会话内经 `portal-entry` 卡片**整页跳门户**;把 admin 能力搬进实例子域反而扩大权限执行面(与档案 39 收窄方向相反) |
| ✅复核 | ~~插件↔门户鉴权令牌~~(档案 05 PoC-2 ②) | **复核结论:已实现(非令牌方式)** —— 共享会话 Cookie(`Domain=.alotbuy.com`)+ `server.ts` 的 CORS 白名单(`isAllowedOrigin` 允许 baseDomain 及其子域 + `Allow-Credentials`),功能插件 v0.2.1 已生产跑通;再做独立令牌属重复建设 |
| ❌复核 | ~~`portal_ping` 端到端~~(档案 05 PoC-2 ③) | **复核结论:原验收项作废** —— 该工具 `fetch(127.0.0.1:3080)`,而档案 39 已封 `127.0.0.0/8`(实测 BLOCKED)→ 必然失败;若要验证"host 插件给 agent 注册工具",需**另立不依赖 loopback 的探针** |
| 暂缓 | **MCN 工作台插件平台化改造**(档案 27)—— **【暂缓】需先测试插件兼容性**(2026-09-11 决策) | 3 处 P0:① `homedir()/.dsh` → `process.env.DSH_HOME ?? …`(config.js 3 处;`mcp.js` 已是正确写法可对照)② 技能路径硬编码 13 处 → 只报技能名 ③ agent preset(`.agent-presets/mcn/`)随包投放;P1:MCP 预装(现在 `npx myai-mcp`)、DB 重建兜底、技能依赖声明 |
| ✅关闭 | ~~白名单源码安装支持~~(档案 29 §七) | **评估结论:不做(2026-09-11)**:源码安装需让第三方构建脚本以 root 在平台机执行(供应链 + 可复现性 + 性能三重风险),与"平台不执行第三方构建脚本"红线冲突。**替代路径**:admin 本地构建后走「上传 tgz」通道(已有 P0/P1 扫描);如需开启须先满足沙箱构建 + `--ignore-scripts` + 仅 admin + 审计等全部前提 |
| 降级 | B5:给 portal-entry / business-plugins 加加载标记 | **降级为"顺手做"(2026-09-11 决策)**:不解决当前问题、源码不在仓库、且仅提升"升级时排查速度";下次改这两个插件时顺手加(零边际成本) |
| ✅ | ~~熔断 live 实测~~(档案 20 附) | **已完成(2026-09-11)**:由真实故障用户(档案 52)的日志完成实测 —— 退避 1000→2000→4000→8000ms、`restartsInWindow` 1→4、第 **5** 次触发 `crash-loop-circuit-open`(窗口 600000ms / 5 of 5),当日 2 次开断;无需再人为 kill 复现 |
| ✅ **已完成**(2026-09-15) | ~~档案 16 阶段 3/4(实例内「我的技能」)~~ → **= 交接单 `T01`,已归档** | **档案 100**|插件 `business-plugins` **0.3.20 → 0.3.21** 已投放两实例。① **形态修正(09-15)**:由「新增 section」改为**并入既有「功能管理」section 内分组**(依据用户口径「不要分开管理」+ 档案 60 分区命名;**仅入口层合并、机制层分离**)→ 见 `T01 §四 决策 6` 与 **`T01 §九`**;② 实现:技能行(名称/来源/状态/事实/动作)+ zip 拖拽上传 + 同名两阶段替换 + 页内确认弹窗 + 锁定行(共享技能)无动作按钮 + zh/en 46 条词条;③ 验收:`npm run verify` 全绿(含新 `07-scripts/verify-my-skills.mjs` 34 条断言)、06 §7 三段式全绿、端到端 **19/19**(409 / 400 守卫通过);④ 阶段 4 收口 = 未新增 section + 未改角色补丁 ⇒ 可见性不变。⚠️ **后续(档案 101)**:该分区已改名「**能力管理**」并改为**页内 tab 分页**(功能插件 / 我的技能)。原述:门户 skills.html 仅 admin → 普通用户需实例内入口 |
| ✅ **已消解** | ~~摘除 guest 仍在启用的已下架插件 `@liustack/modlens`~~ | **09-13 07:0x 实测:已无需处理** —— guest `profile/web` 的 `bundles` **与 `node_modules` 均已无 `@liustack/modlens`**(原「已下架却仍启用」的不一致态已不复存在)。历史:该包 09-12 从候选池下架(档案 70 收尾)时曾留在 bundles |
| ❌已复核 | ~~Cookie 域收窄~~ | **不做(2026-09-12 用户决定:把这条待办删掉)** —— 共享 Cookie(`Domain=.alotbuy.com`)是**有意设计**:支撑「功能插件 ↔ 门户」**免令牌鉴权**(配合 `server.ts` 的 CORS 白名单),功能插件 v0.2.1 已生产跑通 → **收窄会破坏该链路,收益为零**;结论见档案 05 PoC-2 ② |
| 🟡 **待排期** | **T08 集群化的收尾项**(主体与生产切换已完成) | ① `join-worker.sh` 一键装机(现在 join = 装 unit + 起 agent + 注册,三步手工)~~② 隧道服务化~~ ✅ 已收口(本地 20s 定时器自愈,实测 30s 内恢复)③ 集中日志 / metrics ④ `smoke-domain` 定性 ⑤ drop-in 里的 PG 口令建议进一步收权限(现 root 可读)|详见 `05-交接单/T08 §16.5` |
| 🟡 **待排期** | **覆盖网络 / 客户端化这条线**(**本轮零代码、零服务器改动**) | 已落 **档案 103–112**(10 份规划转正式档案;入口 = 工作区根 `接续入口_覆盖网络线_20260916.md`)。📌 **第一件实事 = 把会合 / 中继从 Manager 里拆成可独立部署的组件**(现为绑在 Manager 上的**单中心 SSH 反向隧道**;所有后续多区域 / 多中心 / 骨干层的前置)。**已定口径**:只做技术实现(跨境合规由使用者自负)· **单机自用 ≠ 不需互联** · 按**异构**设计(中继 45% 设计 / 55% 留余量 + **必须补 443/TCP 兜底**)· 权威状态(归属 / 租约 / 资格)**必须单点控制面** · 游戏重点 = **MMORPG(2D/2.5D) / MUD / 传奇类**。⚠️ **唯一待拍板 = 骨干节点服务范围**(A 只服务自己名下设备 / B 服务全网;**倾向 A→B 渐进**,见档案 105 §七)。之后按 **档案 112「只做三件事」** 开工 |
### 历史决策记录(保留,均已落地)
1. **域名决策**(2026-09-08):无域名 → 先解决域名再回来做多用户改造 → 已落地:dsh.alotbuy.com + CF 通配 + 源站 443。
2. **选型决策**(2026-09-08):dshs 模式 A(account 硬隔离)优先,理由:现成密码注册/审核/网页桌面 + 每用户独立实例;替代(自研 Node 网关 + Docker 每用户、dsh-webui-auth 单实例锁)归档为备选。
3. **内存边界**:1.8G 内存 / 2 核 → 1-3 人规模(每用户一个常驻 DSH 子进程),扩容前不超 3 用户。
4. **镜像 v2 / std 技能库归档(2026-09-09)**:旧规划 19 章第十一节的「P1 镜像 v2:内置公共插件 + `std/agents/skills` 标准技能库(rank400 层)」「P1 系统标准技能库内容确认(MCN 脚本创作技能等随镜像/`std/` 分发)」——形态前提是「每用户一个 `dsh-web:<user>` Docker 容器,nginx 按子域/端口分流 + 容器内挂载 `/opt/dsh/std/agents/skills` 兜底层」。**已被 2026-09-08 决策 2(dshs 多租户形态)取代**,无需再做:
- 公共插件分发路径:**profile 层 `dsh plugin --profile <name> add/remove <tgz>`** 官方机制(pnpm 转发,cordis 补丁自动入 bundles);portal-entry v0.1.0→v0.4.3 走的就是这条。
- 标准技能库分发路径:**dsh 原生分层**(项目级 `.dsh/skills` rank100 / `.agents/skills` rank200 / 个人 `~/.dsh/skills` rank300) + 后续「管理员预置 profile-skel 与工作区种子」= 新形态下的 std 技能库等价物(原 P3「编导工作区模板」已于 2026-09-11 删除)。
- 原 dsh-web Docker 容器与镜像(`dsh-web:0.1.2` + `/opt/dsh/dsh-web-0.1.2.tar`)**已全清(2026-09-09)**——确认不回退,回退路径由 `/opt/dsh/backups/` 承担(db.bak 20260909_162739 + profile-web-admin-poc tgz + src-pre-reap tgz)。
- **结论**:原方案归档废弃,不再构建 dsh-web:0.1.x 增强镜像;后续若需"统一技能/插件基线"通过管理员对 profile 模板操作实现,不走镜像层。
---
## 附:红线(硬性,2026-09-09 版)
1. 禁止启动 dsh 时自动获取最新版本;版本升级走独立"升级测试→评估→修复"流程(档案 07)。
2. 不改官方 dsh 主程序与缓存(/usr/local/lib/node_modules/@deepseek-ai/dsh);扩展只走 profile 层 `dsh plugin` 机制。
3. client bundle 严禁 `exports.default`(loader ESM interop 取函数 → 无 inject → 注册静默失败;v0.4.0→v0.4.1 实证)。
4. 服务器 docs 只读归档(root 600);技能/文档同步类红线见各 skill MEMORY 约定。