Files
UHD_Media_Tool/docs/runbook/dev.md
T
rootandClaude Opus 5.5 9858b8494d feat(server): ServerModule skeleton with shared ServerContext, worker runs engine + outbox relay (B6)
modules/{auth-settings,sources-identity,acquisition-organize,agent} placeholders listed in
SERVER_MODULES; ServerModule registers routes (under /api/v1, authenticated), tasks,
outbox routes, capabilities and background loops. bootstrap() builds ServerContext (db,
config, logger, events, engine, outbox writer, secrets placeholder, settings reader,
capability registry), fills unregistered tasks with stubs and rejects duplicate task or
outbox ownership. worker starts the OpenWorkflow worker, OutboxRelay and module start().
--role migrate also migrates the engine schema; api/worker connect without migrating.
tasks: TaskRegistry.has, migrateEngineSchema.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 19:30:55 +08:00

5.1 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"

常用命令

命令 作用
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,非 root(uid 10001),约 270 MB。
  • 入口 docker/entrypoint.sh:迁移 → 自检 → 同时起 api 与 worker 两个进程;任一退出则停掉另一个并以非 0 退出,由 restart: unless-stopped 拉起。
  • 二进制编译时固定权限:--allow-net --allow-env --allow-sys --allow-read=/app,不给 --allow-run / 写权限。
  • 构建版本号: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);若发现明文,属于缺陷。