317 lines
26 KiB
Markdown
317 lines
26 KiB
Markdown
# DeepSeek Harness 多租户容器管理平台 — 设计文档
|
||
|
||
> 当前发布方式为管理员检查Git发布并确认精确commit,本地构建runtime;release.json、image/与初始化测试仅在dockerfile发布分支维护。旧npm/实验构建和构建预约已移除,详见§5。历史验收不自动适用于当前架构,验证范围见ACCEPTANCE.md,部署操作见OPERATIONS.md。
|
||
|
||
> 状态:当前代码具备可信团队管理面板核心流程;历史真实 Docker 验收仅适用于各自记录的版本,不代表当前 Git 发布与全部新增功能已验收。本文“当前实现基线”优先于后面的历史设计;未实现规划不作为已交付能力。验收证据与缺口见 ACCEPTANCE.md。
|
||
> 目标项目:`deepseek-ai/deepseek-harness`(npm CLI `@deepseek-ai/dsh`,命令 `dsh web`)
|
||
> 控制面技术栈:Go + 前端 SPA
|
||
> 部署形态:单机 Docker daemon;面板自身亦运行于容器中
|
||
> 鉴权/配额:内置账号 + 目录配额
|
||
|
||
---
|
||
|
||
## 当前实现基线(本次源码核对)
|
||
|
||
本节描述仓库代码,而不是部署状态。本次本地测试与构建结果见 ACCEPTANCE.md 当前记录;代码已实现和自动化通过均不等于真实环境已验证。正文标为“当前实现”的章节是现行方案,历史调研与可选规划另行标注。
|
||
|
||
### 技术栈与历史 Flutter 的边界
|
||
|
||
- 当前前端是 `web/` 下的 React 19 + TypeScript + Vite,Tailwind CSS v4、Radix 原语的 shadcn 风格组件、lucide 图标及按需加载的本地 Monaco;入口为 `web/src/main.tsx`、`web/src/App.tsx`。登录默认进入内嵌 DSH,桌面侧栏与移动底栏共用响应式页面;主题跟随系统。
|
||
- Flutter/Android 属于历史本地工程痕迹:工作区可能仍有 `android/`、`.dart_tool/`、`build/`、IDE 文件,但当前 Git 跟踪文件没有 Dart 源码或 pubspec。它们不是现行应用、构建输入或受支持的 Android 发布产物,不能据目录存在宣称 Flutter 客户端仍在维护。
|
||
- 后端模块要求 Go 1.25(`go.mod`),Docker 构建阶段使用 Go 1.26;标准库 `net/http` + 自有 Docker Engine HTTP client(API v1.47),不是官方 Docker SDK。SQLite 使用 `modernc.org/sqlite`,密码为 bcrypt,配置备份采用 Argon2id + AES-GCM。
|
||
|
||
```text
|
||
cmd/server/ Go 启动、静态 web/dist 服务
|
||
internal/api/ HTTP、鉴权、发布构建、实例/文件/代理/配置/升级/恢复编排
|
||
internal/docker/ 标准库 Docker Engine HTTP client
|
||
internal/backup/ 配置打包与加密
|
||
internal/store/ SQLite、会话、实例名额事务
|
||
web/src/ React 页面、组件、样式与前端测试
|
||
scripts/ 本地检查及需显式运行的集成/镜像冒烟脚本
|
||
Dockerfile 构建面板及 React 静态资源,不构建 DSH runtime
|
||
compose.yaml 当前面板部署模板
|
||
```
|
||
|
||
`internal/store/intents.go` 当前承载实例名额事务,不表示仍有预约 API。runtime 的 `release.json`、`image/` 与初始化测试在 `dockerfile` 发布分支,main 不包含这些构建资产。
|
||
|
||
### 架构与功能边界索引
|
||
|
||
现行网络、路径、目录、构建、生命周期与认证详见§2–8;文件/配置/升级见§9–12。特别注意:每实例home独立,实例删除会清理自身数据及备份;共享文件入口与构建预约均已移除;旧不确定创建“宽限期后404释放”策略已被替代。
|
||
|
||
### 当前发布与准入流程(详见 §5)
|
||
|
||
1. 管理员通过 `GET /api/releases/latest` 检查配置的 Git 发布仓库/分支及 manifest;通过 `POST /api/releases/build` 确认精确 commit。分支已变化返回冲突,需重新检查。
|
||
2. 构建任务绑定仓库、commit、release ID、版本、部署协议与平台;执行时重新验证信任源和管理员权限,获取锁定 commit 的上下文,本地构建并验证,保留分页历史及详情日志(`releases.go`、`releases_git.go`、`images.go`、`builds_read.go`)。不自动升级已有实例。
|
||
3. 镜像准入仍区分推荐、兼容、仅存量与禁止;验证记录及实际镜像身份必须匹配。当前 `supportedLayout` 仅接受协议/模板 7(`admission.go`),不能套用历史“模板 3–6 可正向准入并使用双挂载”的记录。
|
||
4. 普通用户仅选择可用本地镜像。旧 latest/compatibility、写 builds、全部 intents 接口已经移除;实验构建、构建预约、旧任务续跑不属于当前能力。
|
||
|
||
### 当前部署、未实现规划与验证边界
|
||
|
||
- 当前 `compose.yaml` 为面板 UID/GID 1000、socket 附加组、只读根、tmpfs、资源限制,默认发布 `127.0.0.1:8088`;需配置数据根、DockerRootDir、公开 URL 与可信代理。部署说明见 §16、仓库实际 Compose 和 OPERATIONS.md。
|
||
- XFS/ZFS 硬配额、特权配额 sidecar、socket-proxy、子域名入口属于未交付的可选设计,不是现行默认能力;实际公网 TLS/代理、真机与长期稳定性需独立验收。软配额不能阻止容器直接写盘瞬时超限。
|
||
- `scripts/check-trial.sh` 当前检查 Go 测试/race/vet/build、前端测试/build 和集成脚本语法,不自动运行真实 Docker、浏览器或发布分支初始化测试。完整新 Git 发布链路及部署验证的通过状态以 ACCEPTANCE.md 的当前矩阵为准,不由历史 M1–M7 结案推导。
|
||
|
||
---
|
||
|
||
## 详细设计与历史调研
|
||
|
||
下文当前实现章节已同步;§0为历史上游调研,§9中的硬配额为可选规划。上游链接及版本调研未在本轮重新验证,不能据此推断未来发行版行为。
|
||
|
||
## 0. 历史上游调研结论与硬约束
|
||
|
||
> 实现阶段实测更正:本地 npm `0.2.0-rc.2` 支持 `--trusted-host`,但拒绝 `--public-url`;下文基于 upstream master 的 public-url 描述不能直接用于该发行版。实际启动仅传 web/no-open/port/trusted-host,代理负责外部路径。`scripts/probe-runtime.mjs` 已验证默认 token 交换为 303 + cookie、认证首页 200;完整代理以集成测试为准。
|
||
|
||
针对本体 `deepseek-ai/deepseek-harness`(npm CLI `@deepseek-ai/dsh`,命令 `dsh web`)确认:
|
||
|
||
| 事实 | 来源 | 对设计的影响 |
|
||
|---|---|---|
|
||
| **无官方 Docker 镜像/Dockerfile** | repo 根、`apps/`、`.gitlab-ci.yml` 均无 | 必须自建镜像包装 `dsh web` |
|
||
| **`dsh web` 默认监听 `127.0.0.1:3080`,且启动时拒绝 `--host 0.0.0.0`**(安全原因) | `packages/bundle/web-app/README.md` | 容器内必须跑反向代理绑 `0.0.0.0` 转发到 loopback |
|
||
| 端口/主机是 **CLI flag**(`--port/--host/--public-url/--trusted-host/--no-open`),**无 `DSH_PORT/DSH_HOST` 环境变量** | 同上 | 容器启动参数化靠 CMD args,不靠 env |
|
||
| 数据根 = `$DSH_HOME`(默认 `~/.dsh`) | `docs/user/guide/providers.md`、CLI README | 每实例独立 `DSH_HOME`,bind-mount 即可保留数据 |
|
||
| **多实例硬约束:每个容器必须独立 `DSH_HOME` + 独立端口**(task-board 单写者) | architecture.md | 一用户两容器 ⇒ 两个 `DSH_HOME`,不能共享 |
|
||
| 模型/API Key 存储:密钥在 `$DSH_HOME/.credentials.yaml`(YAML,上游配置接口的 write-only 语义不限制本面板所有者文件访问),模型/provider 配置在 `$DSH_HOME/profiles/<profile>/cordis.patch.yml`;`cordis.patch.yml` 只存 `apiKeyEnv` 引用 | `providers.md` | 备份"模型"= 备份这两个文件 |
|
||
| **"profile 文件" = `profiles/web/cordis.patch.yml`(YAML,用户可编辑的 patch 层)**;profile 目录还有 `package.json`(含插件依赖 + `dsh.profile` bundle 清单)+ `node_modules`(pnpm 装的插件,可重建) | `apps/cli/README.md` | 编辑 profile = 编辑 `cordis.patch.yml`;插件清单在 `package.json` |
|
||
| 升级:用户数据全在 `DSH_HOME`(npm 安装树之外),升级 `@deepseek-ai/dsh` 后数据保留;`node_modules` 由 pnpm 重建 | README、CLI README | "保留数据 + 重启新版容器"可行 |
|
||
| 公网部署:`--public-url <url/mount/>` + `--trusted-host`;代理必须 **剥前缀、保留 Host、把 `Path=/` 的 cookie 改写为 mount + 加 Secure** | `docs/user/guide/public-deployments.md` | 面板反代要处理 cookie/前缀,是最复杂点 |
|
||
| 启动 URL 带 **per-process token**,首次访问换签名 cookie | 同上 | 面板需从容器日志取 token,服务端代换 cookie |
|
||
|
||
> 结论:DSH 不是为容器多租户设计,但靠"自建镜像 + 容器内反代 + 面板反代桥接 token/cookie + 每实例独立 DSH_HOME"可稳态支撑。
|
||
|
||
---
|
||
|
||
## 1. 目标与范围
|
||
|
||
### 已确认的访问与镜像策略
|
||
|
||
- 面向可信团队,实例所有者可通过文件管理读取、下载、修改完整 DSH_HOME,包括自己的凭据。面板不承诺凭据 write-only;跨用户隔离、路径安全、配额与恢复状态保护保持不变。下载文件/打包目录会提示泄密风险,提示属于交互防误操作,不是阻止所有者访问的安全边界。
|
||
- 专用 Profile 编辑器提供 YAML 校验与受控停启流程,但通用文件操作、DSH 终端和 agent 不强制经过该流程;修改运行中配置存在不一致风险,建议先停机并备份。
|
||
- 镜像准入分为推荐、仍兼容、仅存量运行、禁止使用。兼容依据绑定精确版本、模板修订、平台与镜像身份;不再仅因历史模板不是当前模板就一律判为不可用,也不能仅因历史构建成功就认定兼容。
|
||
- 新版本仅通过管理员 Git 发布流程构建;实验构建已移除。管理员正向准入须填写验收依据并记录审计,不绕过布局、平台、实际镜像身份与验证记录检查。
|
||
|
||
- 通过 docker.sock 在单机上**创建/启停/删除**多个 `dsh web` 容器,**每用户最多 2 个**。
|
||
- 每实例独立完整 home,支持文件上传/下载/删除/重命名、文本编辑和图片预览,按账号统计软配额。
|
||
- 实例 home 挂入自身容器的 /workspace,不与同账号其他实例共享挂载。
|
||
- **备份/还原 dsh 配置**(含模型与插件清单)。
|
||
- **编辑 profile 文件**(`cordis.patch.yml`)。
|
||
- **升级**:保留数据,用新版本镜像重启容器。
|
||
- **本地镜像管理**:管理员检查 Git 发布并确认精确 commit 构建;用户选择经验证且准入的本地镜像创建,不提供构建预约。不推送生成的镜像。
|
||
- 控制面:Go 后端 + SPA 前端;内置账号 + 目录配额;**面板自身容器化运行**。
|
||
|
||
---
|
||
|
||
## 2. 总体架构(当前实现)
|
||
|
||
面板是通过 docker.sock 编排 sibling runtime 的 Go 容器,提供 React 静态资源、API、路径反代和 SQLite 持久化。每个实例独立 bridge,面板接入对应网络,runtime 不发布主机端口。容器内 DSH 监听 loopback:3080,由发布镜像内 Caddy 在8080转发;镜像内部实现须以精确发布 commit 为准。
|
||
|
||
浏览器 → 面板 SPA/API 或 /dsh/<id>/ → 实例专属 bridge → runtime:8080 → DSH:3080。
|
||
|
||
socket-proxy 仍为可选规划,当前 Compose 直接挂 socket,不代表具备宿主级隔离。
|
||
|
||
---
|
||
|
||
## 3. 宿主路径 ↔ 面板内路径映射(当前实现)
|
||
|
||
Docker bind.Source 必须使用 daemon 宿主路径。面板文件操作使用 CONTAINER_DATA_ROOT(Compose 为 /data),通过 internal/api/paths.go 的 toHostPath 映射到 HOST_DATA_ROOT。
|
||
|
||
| 用途 | 面板路径 | Docker bind.Source / Target |
|
||
|---|---|---|
|
||
| 实例完整 home | /data/workspaces/<uid>/instances/<id>/home | <HOST_DATA_ROOT>/workspaces/<uid>/instances/<id>/home → /workspace |
|
||
| 配置备份 | /data/backups/<uid>/<id>/ | 不挂入 runtime |
|
||
|
||
构建上下文是从锁定 Git commit 获取并提交的归档流,不应把历史内置 image/ 当作宿主 bind 源。
|
||
|
||
---
|
||
|
||
## 4. 数据与目录布局(当前实现)
|
||
|
||
```
|
||
<HOST_DATA_ROOT>/
|
||
db.sqlite
|
||
workspaces/<uid>/
|
||
instances/<instId>/home/ # 完整 DSH_HOME → /workspace
|
||
.credentials.yaml
|
||
cordis.patch.yml
|
||
profiles/web/ # 配置、插件清单、可重建依赖
|
||
storages/ # 实例工作区数据等
|
||
files/ # 可能遗留;当前无共享入口或新容器挂载
|
||
backups/<uid>/<instId>/ # 加密配置备份;不是完整 home 快照备份
|
||
```
|
||
|
||
账号软配额统计 workspaces/<uid>/,并非只统计当前实例。实例删除会清理该实例目录及对应备份;历史共享 files 不自动合并到 home。旧目录结构和旧删除保留策略不能作为现行承诺。
|
||
|
||
---
|
||
|
||
## 5. 自建 DSH 镜像(当前 Git 发布流程)
|
||
|
||
管理员检查 GET /api/releases/latest,再以 POST /api/releases/build 确认精确 commit;分支变化必须重新确认。后端从受信任仓库锁定 commit 获取 release.json 与 image/,校验部署协议7及当前面板平台,构建本地镜像并验证。构建记录绑定仓库/commit/release ID/版本/平台,任务去重、限频、容量检查与失败记录仍保留。GET /api/builds 及 GET /api/builds/{id} 提供历史与日志。
|
||
|
||
不再从npm查询latest,不接受普通用户实验构建,不打包main内置image/,不提供构建后创建预约。创建实例必须另行选择经验证且准入的本地image ID;管理员构建成功不等于已完成完整兼容验收或自动升级实例。
|
||
|
||
镜像准入绑定实际身份和成功验证记录;supportedLayout只接受模板7,平台须匹配当前面板平台,内置defaultAdmission规则另有限定linux/amd64。旧模板记录可以保留,不意味着可通过填写说明正向准入。镜像清理保护有效引用,不自动全局prune。构建仍可能需要基础镜像和依赖网络,不能宣称离线构建。
|
||
|
||
---
|
||
|
||
## 6. 容器生命周期(当前实现)
|
||
|
||
标准库 Docker HTTP client 使用 API v1.47。创建固定 image ID,事务限制每用户最多两个实例,无构建预约。每实例独立网络与 home,UID/GID 1000,工作目录 /workspace,DSH_HOME/HOME 同为 /workspace,XDG 路径位于其内。启动参数为 web --no-open --port 3080 --trusted-host <host>,不传 --public-url。
|
||
|
||
当前资源约束为只读 rootfs、drop ALL capabilities、no-new-privileges、2GiB 内存、2 CPU、256 PID 及有界可执行 /tmp。实例支持启停、重启、日志、删除;删除回收容器/网络并清理实例数据与备份。创建不确定时保留恢复依据,不能靠一次或超时后的404清除。孤儿资源仅管理员明确确认并核验后处理,不自动纳管。
|
||
|
||
## 7. 网络与访问方式(当前实现)
|
||
|
||
默认已经选择路径前缀代理,不是待拍板选项。面板将 /dsh/<id>/ 转发至对应实例网络中的 runtime:8080;归属检查在代理之前。Compose 默认仅向 loopback 发布面板8088,公网需管理员另配 HTTPS 入口与可信代理。子域名、直接发布 runtime 端口不是当前默认能力。
|
||
|
||
## 8. 访问与认证(当前实现)
|
||
|
||
面板校验账号和实例归属,从启动日志取得 token 并在服务端交换/缓存 DSH cookie;token 按容器身份/启动时间加密持久化。反代剥前缀、处理 Host 与转发头,注入服务端 cookie 并移除上游 Set-Cookie,不把 DSH cookie 改写下发给浏览器。客户端持有的是面板认证 cookie。
|
||
|
||
WS/SSE 由反代支持;会话续期由面板/runtime 注入脚本协调。上游拒绝 cookie 时失效缓存,下次请求重新交换,不重放写请求。已建立 WS/SSE 不承诺即时撤销;真实部署的长会话、插件与公开入口仍需分别验证。
|
||
|
||
## 9. 工作区文件管理 + 容量配额
|
||
|
||
**文件 API**(除 usage 外必须提供 instance 并校验归属;path 限于该实例 home,拒穿越、绝对路径和不安全符号链接):
|
||
|
||
- `GET /api/ws/tree?path=` 列目录(带 size/mtime)
|
||
- `POST /api/ws/mkdir`、`POST /api/ws/rename`、`DELETE /api/ws/delete`
|
||
- `POST /api/ws/upload`(有界上传、写前查配额;不是分片续传协议)
|
||
- `GET/PUT /api/ws/text`(文本读取/带版本冲突检查的保存)、`GET /api/ws/image`(受控图片读取)
|
||
- `GET /api/ws/download?path=`(单文件流;目录自动 zip)
|
||
- `GET /api/ws/usage`(当前用量/配额)
|
||
|
||
**配额实现**(容器化面板的约束):
|
||
|
||
- **默认:软配额**。面板写前遍历统计账号目录用量,写入串行化并限制并发,每五分钟巡检记录超限。容器/agent直接写盘不受面板写锁约束,仍可超过软配额;不通过删用户数据恢复容量。
|
||
- **可选硬配额**(二选一,需运维确认):
|
||
- **XFS prjquota**:面板 `--privileged` + `cap_add:[SYS_ADMIN,CHOWN]` + 把宿主 XFS 挂载点 bind 进来,面板内对 `/data` 跑 `xfs_quota`/`chattr -p`。每用户唯一 project ID(uid+1000)。
|
||
- **ZFS refquota**(若宿主用 ZFS):面板 `--privileged` + zfsutils,每用户 `zfs create pool/users/<uid> && zfs set refquota=10G`,再 bind 该 dataset 到 `/data/workspaces/<uid>`。
|
||
- 或在宿主跑**极小特权配额 sidecar**(gRPC/HTTP),面板远程调它做 quota 操作——面板自身保持非特权。
|
||
- 配额值存 DB,按用户可配(默认 10GiB)。面板展示用量。
|
||
|
||
> 当前仅软配额;上述 XFS/ZFS 和特权 sidecar 是未实现规划,不是可直接启用的配置。
|
||
|
||
---
|
||
|
||
## 10. 配置备份与还原(含模型与插件)
|
||
|
||
**备份内容**(tar.gz,**排除可重建/运行态**):
|
||
|
||
| 包含 | 说明 |
|
||
|---|---|
|
||
| `.credentials.yaml` | 模型 API Key(机密)→ 备份包加密 |
|
||
| `cordis.patch.yml`(home 级) | home patch |
|
||
| `profiles/web/package.json` | **插件清单**(含 dsh.profile bundle 列表) |
|
||
| `profiles/web/cordis.patch.yml` | **模型/provider 配置** + apiKeyEnv 引用 |
|
||
| `profiles/web/pnpm-lock.yaml`(若有) | 插件版本锁 |
|
||
| `skins/ pets/ agent-presets/ .agent-presets/` | 用户资源 |
|
||
| `dsh-ssh.json` | SSH 凭据(0600,加密入包) |
|
||
| `manifest.json` | dsh 版本、备份 schema 版、时间戳 |
|
||
|
||
**范围**:仅上述六个固定配置文件、四类资源树和生成的manifest;不是完整home备份,通常位于白名单外的工作区、会话和插件node_modules不会入包。资源树按路径递归纳入普通文件,不根据文件内容识别运行态或凭据;不安全路径、符号链接及特殊文件会被拒绝。
|
||
|
||
**备份包加密**:用用户密码派生密钥(Argon2id → AES-GCM)加密整包;密钥不落库。下载/上传均加密包。
|
||
|
||
**备份流程**:按受控流程停止原本运行的容器,打包白名单并加密落盘,再恢复原运行状态;支持下载。不是任意运行中文件的一致性全量快照。
|
||
|
||
**还原流程**:校验并解密包,受控停机、保存home恢复快照,应用配置与协调插件,启动验证后恢复应有运行状态;失败尝试快照回滚,失败恢复可能需人工介入。实际快照命名和恢复记录以config.go及运维文档为准,不提供任意第三方插件兼容保证。
|
||
|
||
---
|
||
|
||
## 11. profile 文件编辑
|
||
|
||
- 编辑对象:`profiles/web/cordis.patch.yml`(YAML)。
|
||
- 前端用本地 Monaco;后端 `GET` 返回原文,`PUT` 校验 YAML 后原子写入,专用编辑器修改前需停止实例。未实现的 schema 比对不作为已交付能力。
|
||
- 页面“保存并启动”发送 `restart:true`,写入后启动并检查就绪;API省略该参数时仅保存,不自动启动。
|
||
- 只读展示 `dsh.profile`(bundle 清单)与 `--dump-config` 预览(面板 `docker exec` 跑 `dsh --profile web --dump-config` 取回渲染)。
|
||
- 专用配置预览保持脱敏;完整 home 文件管理允许实例所有者读取 `.credentials.yaml` 原文,不承诺 write-only。
|
||
|
||
---
|
||
|
||
## 12. 升级流程(保留数据 + 重启新版容器)
|
||
|
||
```
|
||
1. 用户选择本地可用目标版本;若无目标镜像,先由管理员完成 §5 Git 发布构建。锁定已验证且准入的 image ID 后才进入备份/停机流程
|
||
2. 停止原本运行的旧容器并检查确实已停机(不 remove,保留作回滚)
|
||
3. 创建有界home快照,再用当前登录密码创建 pre-upgrade 配置备份
|
||
4. 保留旧容器回滚依据,创建替换容器:同逻辑实例、同home挂载、新image,不挂共享files
|
||
Cmd 使用 web/no-open/port/trusted-host,不传 --public-url
|
||
5. 启动新容器;发布镜像入口负责插件协调,其离线能力须针对精确镜像验证
|
||
6. 面板抓 token 并验证就绪
|
||
7. 成功删除旧容器;失败尝试清理新容器、恢复home快照及旧容器原运行状态,回滚失败保留恢复依据并提示人工处理
|
||
```
|
||
|
||
历史设计意图:保持 bind 并重建插件依赖以尽量保留数据;**这不保证零丢失或任意插件跨版本兼容**。当前升级还依赖备份、快照、健康检查和回滚,故障及兼容性必须实测。
|
||
|
||
---
|
||
|
||
## 13. 安全与资源
|
||
|
||
- **docker.sock**:面板容器能访问 sock 即等效宿主 root。当前非root进程和只读rootfs不能消除该权限;socket-proxy白名单只是尚未实施的可选增强。
|
||
- dsh 容器:**不 `--privileged`**、去 CAP_NET_RAW 等、只读 rootfs、tmpfs /tmp、mem/cpu 限制、不挂 sock。
|
||
- 面板账号:bcrypt + JWT(短期 access + refresh),失败锁定。
|
||
- 配置备份包加密;实例所有者通过文件 API 下载的凭据或目录 ZIP 不属于加密配置备份,应按机密数据保管。
|
||
- 路径穿越校验、上传大小/类型白名单(可配)。
|
||
- 审计日志:容器操作/备份/还原/升级/profile 改动入库。
|
||
|
||
---
|
||
|
||
## 14. 技术栈与项目结构(当前实现)
|
||
|
||
当前 Go/React 栈和实际目录见文首基线:Go 模块版本1.25、net/http、自有 Docker HTTP client、modernc SQLite;React 19、TypeScript、Vite、Tailwind v4、Radix 原语、Monaco。不是 Flutter 客户端,也不是独立 auth/workspace/proxy/upgrade 包的原设计拆分;多数编排位于 internal/api。
|
||
|
||
旧设想中的 main/image/、deploy/ 不能用于当前构建或部署:runtime 资产在 dockerfile 发布分支,面板使用根目录 Dockerfile 和 compose.yaml。
|
||
|
||
---
|
||
|
||
## 15. 数据模型(当前实现概要)
|
||
|
||
SQLite基础表users、sessions、instances、audit由internal/store初始化;认证轮换、构建/镜像准入、发布身份、runtime创建/网络恢复和升级恢复等表由相应API模块维护。实际字段与迁移以源码为准,不将早期设计的示意DDL当作数据库接口。
|
||
|
||
image_builds包含任务、验证及发布来源信息;image_admissions绑定精确image ID/version/recipe/platform及验收依据;runtime_creates/runtime_networks保留资源恢复依据。旧表或文件名存在不代表旧预约服务仍运行。
|
||
|
||
---
|
||
|
||
## 16. 面板自身部署(当前实现)
|
||
|
||
以根目录 compose.yaml、.env.example 和 OPERATIONS.md 为操作入口,不复制历史80/443或共享bridge样例。默认面板绑定127.0.0.1:8088,运行用户1000:1000,附加宿主socket组;只读rootfs、/tmp tmpfs、1GiB内存、2 CPU、512 PID及健康检查。
|
||
|
||
配置 HOST_DATA_ROOT / CONTAINER_DATA_ROOT、DockerRootDir只读容量探测挂载、PANEL_CONTAINER_ID,以及实际公开URL和可信代理CIDR。裸docker.sock挂载并未被只读rootfs降权,仍需信任面板与账号。当前模板不部署socket-proxy或硬配额sidecar。
|
||
|
||
---
|
||
|
||
## 17. 关键风险与待验证
|
||
|
||
1. **token/cookie 桥接**(§8):需在实际入口验证服务端cookie交换与注入、前缀代理及WS/SSE,不以本地模拟替代部署验收。
|
||
2. **插件首启重建**:跨 dsh 版本 `pnpm install` 在 entrypoint 无网时失败——可能需升级时由面板 `docker exec` 联网重建后再切流量。
|
||
3. **XFS/ZFS 硬配额**依赖宿主 FS 与特权/agent;否则退化为软配额。
|
||
4. **dsh agent 工作目录**:`dsh-fs-local`/`dsh-fs-sandbox` 的根是否等于 cwd——需确认 `/workspace` 作为 cwd 即可让 agent 在工作区操作,或需额外配置 fs root。
|
||
5. dsh 版本仍为 `0.2.0-rc.*`(RC),API/flag 可能变动——需维护版本兼容矩阵。
|
||
6. **sibling bind 路径翻译**:`toHostPath` 出错会导致 bind 挂错目录或挂空目录,需单测覆盖。
|
||
7. **Git 发布构建**:须验证精确 commit 确认与分支变化、信任源/权限变化、构建去重及恢复、外部删除镜像、容量及网络故障。构建成功不等于完整兼容验收,不存在旧构建预约释放名额流程。
|
||
|
||
---
|
||
|
||
## 18. 已决策与后续规划
|
||
|
||
已选择每实例独立bridge、路径前缀反代、服务端cookie桥接、账号软配额、React响应式Web及管理员Git发布本地镜像。旧npm最新构建/预约、共享工作区和Flutter发布不是当前路线。
|
||
|
||
可选后续增强:XFS/ZFS硬配额或宿主配额sidecar、socket-proxy、独立域名隔离。上述未纳入当前默认交付;是否实施需另行设计、授权和验收,不能以文档列出视为支持。
|
||
|
||
## 19. 里程碑与交付判定
|
||
|
||
M1镜像、M2账号/生命周期、M3代理、M4文件/软配额、M5配置备份、M6升级回滚、M7界面/管理安全保留为能力分组,不再以旧npm构建及预约作为当前M2标准。当前Git发布、实例home独占、删除清理、文本编辑/图片预览与主题等变更须按ACCEPTANCE.md当前矩阵分别补证据。
|
||
|
||
历史M1–M7结案不等于当前commit或真实部署整体通过;本地测试通过、真实Docker通过、浏览器通过与公网验收必须分开记录。
|
||
|
||
---
|
||
|
||
## 附:调研依据(关键 URL)
|
||
|
||
- 仓库:https://github.com/deepseek-ai/deepseek-harness
|
||
- README:https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/README.md
|
||
- CLI README:https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/apps/cli/README.md
|
||
- web-app README:https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/packages/bundle/web-app/README.md
|
||
- providers 指南:https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/docs/user/guide/providers.md
|
||
- 公网部署指南:https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/master/docs/user/guide/public-deployments.md
|
||
- npm 包:https://registry.npmjs.org/@deepseek-ai/dsh/latest
|