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)。
S
Description
No description provided
Readme
464 KiB
Languages
Python 67%
HTML 16.4%
Shell 7.1%
Java 6%
Batchfile 2.5%
Other 1%