P0 MVP: - 认证:login/refresh/logout/forgot/reset + tokenVersion - RBAC:角色到权限映射 + requirePermission - 发票池:upload/bind/signed-url + 判重(VALID_003/VALID_005) - 报销:create/view/submit + 单号生成 - 工作流:approve + department_manager 解析 P1 扩展: - 动作:reject/return/withdraw(含 comment) - transfer:任务转审 + 链路上限 3 - pay:approved -> paid + 发票归档 used_complete - 动态审批链:approval_rules 驱动 回归脚本: - smoke-test.sh / regression-dedup.sh / regression-workflow-actions.sh
hyb-oa Server Runbook (P0/P1)
1. 环境准备
- Node.js:
>=20 - Docker + Docker Compose
- 本地工具:
curl、jq - 配置文件:从
server/.env.example复制为server/.env并按需修改
cd /home/shunli/Projects/hyb-oa/server
cp .env.example .env
2. Gate 基线命令(必须顺序执行)
2.1 启动数据库
cd /home/shunli/Projects/hyb-oa
docker compose up -d db
2.2 应用迁移
cd /home/shunli/Projects/hyb-oa/server
npm run prisma:migrate:deploy
2.3 执行 seed(幂等)
cd /home/shunli/Projects/hyb-oa/server
npm run seed:dev
2.4 启动服务
cd /home/shunli/Projects/hyb-oa/server
npm run dev
2.5 冒烟验证
cd /home/shunli/Projects/hyb-oa/server
./scripts/smoke-test.sh
3. 1 分钟快速验证
cd /home/shunli/Projects/hyb-oa/server
./scripts/smoke-test.sh
4. 回归入口
4.1 脚本回归(推荐)
cd /home/shunli/Projects/hyb-oa/server
BASE_URL=http://127.0.0.1:3000 ./scripts/smoke-test.sh
4.2 判重专项回归(dedup)
cd /home/shunli/Projects/hyb-oa/server
DATABASE_URL='postgresql://hyboa_user:[email protected]:5432/hyb_oa?schema=public' \
BASE_URL=http://127.0.0.1:3000 ./scripts/regression-dedup.sh
4.3 工作流动作回归
cd /home/shunli/Projects/hyb-oa/server
./scripts/regression-workflow-actions.sh
覆盖场景:
reject:实例=rejected,报销=rejectedreturn:实例=terminated,报销=draftwithdraw:审批未处理前可撤回return后二次submit:创建新实例PERM_002:非 assignee 无法操作no_actionable_approver:全链无可执行审批人阻断negative_not_allowed:负金额防御manager skip:直属上级缺失时跳过并记录transfer:转审成功(任务改派 + 任务/转审记录/history 三处证据)transfer参数校验:reason<10 返回VALID_002transfer同人转审:返回VALID_001(same_assignee_not_allowed)transfer链路上限:同 task 第 4 次转审阻断(chain_limit_exceeded)transfer目标校验:目标审批人须 active 且具备expense.approvepay:财务付款成功(approved -> paid,发票bound -> archived(used_complete))pay权限:非财务返回PERM_001pay状态校验:非approved/paid返回VALID_001pay幂等:重复付款返回 200(archivedInvoiceCount可为 0)
4.4 一键全量回归
cd /home/shunli/Projects/hyb-oa/server
./scripts/regression-all.sh
串联 smoke-test.sh + regression-dedup.sh + regression-workflow-actions.sh,适用于 CI 或发版前检查。
4.5 Postman 回归
- Collection:
server/postman/hyb-oa.postman_collection.json - Environment:
server/postman/hyb-oa.postman_environment.json - 核心链路:
- Login Employee
- Create Reimbursement
- Upload Invoice
- Bind Invoice
- Submit Reimbursement
- Login CEO
- Approve Workflow Task
- Get Signed URL
5. 关键环境变量
DATABASE_URL: PostgreSQL 连接串JWT_SECRET: JWT & signed-url token 签名密钥APP_TIMEZONE: 默认Asia/ShanghaiSTORAGE_DIR: 默认generated/storage(相对server/)SIGNED_URL_TTL_SECONDS: 默认600MAX_UPLOAD_SIZE_BYTES: 默认10485760(10MB)
生产提示:大表加索引需评估
CREATE INDEX CONCURRENTLY,避免锁表影响。
6. 常见失败排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
prisma migrate deploy 失败 |
DATABASE_URL 未配置/不可达 |
检查 server/.env 与数据库容器状态 |
npm run seed:dev 重复执行报错 |
seed 脚本被改坏,未保持幂等 | 检查 seed-config.js/seed-dev.js 的 upsert / skipDuplicates |
| signed-url 接口返回 403 | JWT_SECRET 不一致、token 过期、访问人无权限 |
统一服务密钥、确认 URL 在 TTL 内、检查账号角色 |
上传返回 file_too_large |
文件超 MAX_UPLOAD_SIZE_BYTES |
调整环境变量或使用更小文件 |
| 上传失败且报目录/权限错误 | STORAGE_DIR 不存在或不可写 |
创建目录并修正权限;Docker 需确认 volume 挂载 |
7. 手工故障注入(非阻塞)
7.1 STORAGE_DIR 不可写路径
- 临时将
STORAGE_DIR指向只读目录,执行上传接口,确认错误可观测(日志+返回码)。
7.2 磁盘空间不足(ENOSPC)
- 在受控环境中制造磁盘满条件后重试上传。
- 预期:错误路径可观测(日志中能定位到 I/O 错误),不要求纳入日常 CI 冒烟。