- DATA_DIR (/data: agent-sessions, backups, exports, tmp); entrypoint chowns it to PUID/PGID then drops privileges via gosu; /app binary stays root read-only - compile with --allow-read --allow-write so mounted library roots are writable - preflight: DATA_DIR/session dir must be writable (fatal); enabled library roots and downloader path mappings checked read/write (warn + audit) - --role export-mappings (mapping manifest JSON, --compare row counts) and --role read-only-on (automation.readOnlyReconcile=true + audit) - scripts/backup.sh (pg_dump custom + mappings + agent sessions, SHA256SUMS, BACKUP_KEEP rotation) and scripts/restore.sh (checksum, refuses with live connections, psql single-transaction replay compatible with PG16, read-only reconcile on, row-count verification) - compose: app + postgres only, data volume, env example with key generation - docs: runbook deploy.md, backup-restore.md with verification record Co-Authored-By: Claude Opus 5.5 <[email protected]>
5.3 KiB
开发环境运行手册
前置
- Deno 2.9.7(锁定;
curl -fsSL https://deno.land/install.sh | sh -s v2.9.7)、Docker。不需要 Node.js / pnpm。 - 端口:web 5180、API 4380、PG 55433。本机 3000/5175/5176/55432 已被其他项目占用,不要改用。
首次启动
cp .env.example .env # 按需修改;server 与 db 脚本都读仓库根 .env
deno task db:up # 起 postgres:16-alpine(docker-compose.dev.yml,数据卷 umt-pg-data)
deno install # 按 deno.lock 装依赖到 node_modules(成员包软链到 node_modules/@umt/*)
deno task db:migrate # 执行 packages/db/migrations 下全部迁移
deno task dev # 同时起 server(4380)与 web(5180)
单独起:deno task dev:server(deno run --watch,默认 --role all,API + worker 同进程)、deno task dev:web。
验证
curl localhost:4380/api/v1/health
# 开发模式可用 .env 的 DEV_ADMIN_KEY 作 admin
curl -N -H "Authorization: Bearer umt-dev-admin-key" "localhost:4380/api/v1/events?after=0"
- OpenAPI:http://localhost:4380/api/openapi.json,文档页 http://localhost:4380/api/docs
- 控制台:http://localhost:5180,右上角钥匙按钮设置 API Key(存 localStorage
umt-api-key)
常用命令
| 命令 | 作用 |
|---|---|
deno task ci |
typecheck(tsc 7.0.2 + deno check)→ lint(biome)→ test(vitest)→ check:tokens → build,提交前必须全绿 |
deno task typecheck |
deno types 生成 types/deno.d.ts 后,逐个成员跑 tsc 7.0.2,再跑 deno check(Deno 内置 TS 6.0.3) |
deno task lint / deno task fmt |
biome 检查 / 自动修复(含 import 排序;相对 import 必须带扩展名) |
deno task test |
逐个成员跑 vitest(deno run -A npm:vitest run);单包:cd packages/<x> && deno task test |
deno task db:reset |
清空 public schema 并重新迁移(生产环境拒绝执行) |
deno task gen:types |
从已迁移的库反射生成 packages/db/src/types.ts |
deno task gen:tokens |
改了 app.css 后重新生成 token 登记表 |
deno task build |
web 构建到 apps/web/build/client + server 编译为单文件 dist/umt-server |
cd apps/server && deno task start |
以受限权限(net/env/sys/read)直接跑源码 |
依赖:npm 包版本只在根 deno.json 的 imports 里登记(web 的前端依赖仍在 apps/web/package.json)。改完跑 deno install 更新 deno.lock。有安装脚本的新依赖需要 deno approve-scripts 显式批准。
进程角色
umt-server --role api|worker|all(源码:deno run ... apps/server/src/main.ts --role ...)。all 下 worker 心跳会发布到进程内事件总线,SSE 可见;分进程部署时事件总线需改为 PG 投影(W2)。
启动时 bootstrap() 装配 apps/server/src/modules/ 下的四个业务模块(见 apps/server/README.md),并连接任务引擎;api 角色也连接引擎(入队/信号/取消),worker/all 角色额外启动引擎 worker 与 OutboxRelay。数据库不可达时进程启动失败并退出。
一次性子命令(容器入口用):--role migrate(迁移到最新,迁移文件已编进二进制;随后迁移任务引擎的 openworkflow schema)、--role preflight(启动自检:生产环境拒绝占位符密钥与 root、DB 可达、WEB_ROOT/index.html 存在)、--role probe(打本机 /api/v1/health,HEALTHCHECK 用)。
设置 WEB_ROOT 后 API 进程在同一端口托管 web 构建产物:存在的文件直接返回,其余非 /api 路径回退 index.html。
Docker 单容器部署
export SECRET_MASTER_KEY=$(openssl rand -hex 32) POSTGRES_PASSWORD=$(openssl rand -hex 16)
docker compose up -d --build # 服务:app(4380)+ postgres(数据卷 umt-pg-data)
curl localhost:4380/api/v1/health
- 镜像:
denoland/deno:2.9.7构建 web 与deno compile出二进制,运行时debian:trixie-slim+ gosu + postgresql-client,root 启动修/data属主后降权到 PUID(缺省 10001),约 490 MB。 - 入口
docker/entrypoint.sh:迁移 → 自检 → 同时起 api 与 worker 两个进程;任一退出则停掉另一个并以非 0 退出,由restart: unless-stopped拉起。 - 二进制编译时固定权限:
--allow-net --allow-env --allow-sys --allow-read --allow-write,不给--allow-run;运行期写入落在DATA_DIR(容器内/data)。完整部署说明见 deploy.md。 - 构建版本号:
APP_VERSION=v0.1.0 docker compose build(写入 web 的version.json)。
测试数据库
需要 PG 的测试(db、tasks)默认连 DATABASE_URL 或 55433 开发库,不可达时跳过。tasks 包可用 TASKS_TEST_DATABASE_URL 指定独立库;每个测试文件使用带 pid+随机后缀的独立 schema,结束时删除,多份测试并发跑也不冲突。
排障
配置无效:按提示检查.env,SECRET_MASTER_KEY至少 16 字符,DATABASE_URL必须是 postgres://。- health 返回
db: "down":docker compose -f docker-compose.dev.yml ps看容器健康状态。 deno check报找不到Deno:检查根目录是否误放了tsconfig.json(tsc 基座在config/tsconfig.base.json)。- tsc 报
Deno未定义:先跑deno task types生成types/deno.d.ts(已 gitignore)。 - 日志中的 passkey/token/cookie/authorization/password 字段与 URL query 参数会被替换为
[REDACTED](含logger.child()绑定字段与err的 message/stack);若发现明文,属于缺陷。