f6acd20325ad7ff291867d540125c548fda6a496
dsh-sync — DeepSeek Harness 团队同步服务端
为 DeepSeek Harness 提供 团队设置 / 用户设置 / 插件分发 的私有同步服务。 架构设计见 ARCHITECTURE.md,移动端见 MOBILE_APP.md。 已完成并通过 55 个 pytest 用例(PostgreSQL 16)+ 真实 HTTP 冒烟验证。
目录结构
server/
dsh_sync/
main.py # 应用组装(配置 / 中间件 / 路由注册)
config.py # 环境变量配置(含 DSH_DATABASE_URL)
db.py # PostgreSQL schema + 审计写入(psycopg 3)
auth.py # token 签发 / 认证 / 请求上下文
storage.py # 制品与 APK 的路径解析
ratelimit.py # 邀请码兑换限流
routers/ # 按资源拆分的路由(pages/connect/tokens/users/settings/plugins/audit)
static/ # mobile.html(PWA)、apk.html(安装页)、sw.js
tests/ # pytest 套件(55 例,跑在专用测试库 postgres_test 上)
client/
dsh_sync_client.py # 参考客户端(移植进 harness 用)
android/ # 安卓 WebView 壳工程 + build.sh
data/dist/ # APK 构建产物(dsh-sync.apk + 元数据)
Dockerfile / docker-compose.yml / Caddyfile
安卓 App
bash android/build.sh # 需要 JDK 17 + Android SDK 34 + Gradle 8.7
构建后访问 http://<服务器>:8020/apk 下载安装(免登录页面,含二维码与安装步骤)。
本地运行(开发)
需要一份 PostgreSQL(本地服务或容器均可):
# 一次性测试库(二选一):
# a) Docker:docker run -d --rm --name dsh-test-pg -p 15433:5432 \
# -e POSTGRES_USER=dsh -e POSTGRES_PASSWORD=dsh -e POSTGRES_DB=dsh_test postgres:16-alpine
# b) 任意已有 PG:建一个空库即可
cd server
python -m venv .venv
.venv/Scripts/pip install -r requirements.txt -r requirements-dev.txt # Windows
# Linux/macOS: .venv/bin/pip install ...
# 测试。默认用生产实例上的独立库 postgres_test(不存在会自动建)。
# 注意:测试库每个用例都会 DROP SCHEMA 重建,所以 conftest 会在
# DSH_TEST_DATABASE_URL 指向生产库时直接拒绝运行。
.venv/Scripts/python -m pytest -q
DSH_DATABASE_URL="postgresql://dsh:secret@127.0.0.1:5432/dsh" \
DSH_BOOTSTRAP_ADMIN_TOKEN=<随机串> DSH_INVITE_CODE=<邀请码> \
.venv/Scripts/python -m uvicorn dsh_sync.main:app --reload --port 8000
注意 DSN 里用
127.0.0.1而不是localhost:部分 Windows 机器localhost先解析到 IPv6, 若 PG 未监听 IPv6 会导致每次连接白等一个 connect_timeout。
Docker 部署
cp .env.example .env # 填入 POSTGRES_PASSWORD / DSH_BOOTSTRAP_ADMIN_TOKEN / DSH_INVITE_CODE / DSH_SYNC_DOMAIN
docker compose up -d --build
compose 会启动三个服务:postgres:16(数据存 pg_data 卷,带健康检查)→ dsh-sync(等库就绪后启动)→ caddy。
- 公网部署:Caddy 按
DSH_SYNC_DOMAIN自动签发 TLS 证书。 - 更推荐内网 / Tailscale 部署(见 Caddyfile 中
:8080注释块),不暴露公网。 - 备份:
docker compose exec postgres pg_dump -U dsh dsh > backup.sql+ 打包./data/(插件制品)。
环境变量
| 变量 | 说明 | 默认 |
|---|---|---|
DSH_DATABASE_URL |
PostgreSQL 连接串(必填),建议用 127.0.0.1 而非 localhost |
无 |
DSH_DATA_DIR |
插件制品存储目录 | ./data(容器内 /data) |
DSH_BOOTSTRAP_ADMIN_TOKEN |
首次启动时为 admin 用户创建的固定 token(幂等) | 无则跳过 |
DSH_ADMIN_USERNAME |
admin 用户名 | admin |
DSH_INVITE_CODE |
团队邀请码,成员自助注册用;不设则关闭邀请注册 | 无 |
DSH_MAX_PLUGIN_MB |
插件制品上传上限(MB) | 20 |
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB |
compose 创建 PG 实例用 | dsh / 必填 / dsh |
API 一览(Bearer token 认证)
GET /healthz # 探活
POST /v1/tokens # 邀请码换 token(仅新用户)
POST /v1/tokens/self # 给自己加签 token
GET /v1/tokens # 列自己的 token
DELETE /v1/tokens/{token_hash} # 撤销 token(本人或 admin)
POST /v1/users # admin 直接建用户发 token
GET /v1/me # 身份信息
GET /v1/connect/info # admin:扫码连接数据(内网地址候选 + 邀请码)
GET /v1/connect/qr?host=x.x.x.x # admin:连接二维码(SVG,深链 /app#invite=…)
GET /v1/settings # team ∪ user 合并视图,带 ETag(304 缓存)
PUT /v1/settings/user/{key} # 写自己的设置,body {value, base_version?}
PUT /v1/settings/team/{key} # admin 写团队设置
GET /v1/plugins?harness_version=x.y # 插件列表(按最低 harness 版本过滤)
GET /v1/plugins/{id}/{version} # 插件详情(manifest + sha256)
GET /v1/plugins/{id}/{version}/download # 下载制品,响应头 X-Sha256
POST /v1/plugins/{id} # admin 上传新版本(tar.gz,内含 manifest.json)
DELETE /v1/plugins/{id}/{version} # admin 删除版本
GET /v1/audit # admin 审计日志
错误语义:401 未认证 / 403 无权限 / 404 不存在 / 409 版本冲突或重复 / 400 参数非法。
manifest.json 格式(打包在 tar.gz 根目录或单一顶层目录内)
{
"id": "demo",
"version": "1.0.0",
"name": "Demo Plugin",
"description": "…",
"channel": "stable",
"min_harness_version": "0.0.0",
"files": ["main.py"]
}
客户端(参考实现)
client/dsh_sync_client.py 演示了完整协议,可整体移植进 harness 的 sync 模块:
python client/dsh_sync_client.py login http://127.0.0.1:8000 <邀请码> --username alice
python client/dsh_sync_client.py pull
python client/dsh_sync_client.py push theme '"dark"'
python client/dsh_sync_client.py install demo --harness-version 1.0.0
python client/dsh_sync_client.py status
要点(与 ARCHITECTURE.md §6/§7 对应):
- 配置层叠:
defaults < team < user < 本地覆盖;本地覆盖永不上传。 pull带 ETag,304 或服务器不可达时回退本地缓存并标记stale。push携带base_version,409 冲突时提示重新拉取,不静默覆盖。install强校验 sha256 与大小,防 zip-slip,临时目录解压后原子替换。- API Key 永远不要放进来:每人自己的 DeepSeek Key 存本地(keychain/环境变量);团队统一管 Key 请前置 LLM 网关(one-api / LiteLLM)。
已验证
server/tests:27 个用例(认证、token 撤销、设置合并/冲突/权限、插件上传下载/哈希/路径穿越/版本过滤/渠道优先、扫码连接 info/qr/权限/HTTPS 场景、审计)在 PostgreSQL 16 上全部通过。- 真实 uvicorn + PostgreSQL 启动 + curl 全链路冒烟:健康检查、admin 认证、团队设置写入、邀请码注册、插件上传、成员下载,sha256 两侧一致。
- 扫码连接(PWA「设置 → 连接手机」):二维码深链 + 候选地址切换 +
#invite=自动预填,已在 390×844 手机视口实测(截图dsh-app-connect-qr.png)。
Languages
Python
67%
HTML
16.4%
Shell
7.1%
Java
6%
Batchfile
2.5%
Other
1%