R79 收口公网部署与治理事实源
这个提交包含在:
@@ -12,5 +12,5 @@
|
|||||||
"差旅与移动审批","enabled_admin","/travel-requests|/mobile/approvals|/mobile/capture","employee|manager|finance","WECOM_ENTRY_ENABLED","wecom_entry_v1","partial_done","artifacts/r69/acceptance-report.md|client/tests/e2e/travel-payment-flow.spec.ts|client/tests/e2e/travel-reconciliation-flow.spec.ts|client/tests/e2e/mobile-approvals-offline.spec.ts|artifacts/r70/manual-trialrun-report.md","差旅申请、审批、支付、绑票、对账批次,以及移动审批 deep link 离线重放都有自动化证据;R70 人工仅确认移动入口可理解。","真实 IM deep link、真实移动设备拍照上传、多人并发审批未验证。","保留自动化为主;真实设备和 IM 深链并入 A5。"
|
"差旅与移动审批","enabled_admin","/travel-requests|/mobile/approvals|/mobile/capture","employee|manager|finance","WECOM_ENTRY_ENABLED","wecom_entry_v1","partial_done","artifacts/r69/acceptance-report.md|client/tests/e2e/travel-payment-flow.spec.ts|client/tests/e2e/travel-reconciliation-flow.spec.ts|client/tests/e2e/mobile-approvals-offline.spec.ts|artifacts/r70/manual-trialrun-report.md","差旅申请、审批、支付、绑票、对账批次,以及移动审批 deep link 离线重放都有自动化证据;R70 人工仅确认移动入口可理解。","真实 IM deep link、真实移动设备拍照上传、多人并发审批未验证。","保留自动化为主;真实设备和 IM 深链并入 A5。"
|
||||||
"预算、支付批次与 AP 运营","optional","/budgets|/payment-batches|/ap-operations","finance|admin","BUDGET_PRECHECK_ENABLED|PAYMENT_BATCH_ENABLED|ERP_SYNC_ENABLED","budget_precheck_v1|payment_batch_v1|erp_sync","partial_done","issues/2026-03-29_08-07-14-p25-lite-budget-ap.csv|issues/2026-04-06_r52-ap-operations.csv|issues/2026-04-29_10-14-27-r78-reimbursement-payment-tail.csv|client/tests/e2e/reimbursement-payment-batch-flow.spec.ts|server/scripts/regression-payment-batches.sh","支付批次 maker-checker、AP 待付款快捷复核、finance 执行报销付款批次,以及 reimbursement paid 后 ERP preview pending outbox 已在本地 focused regression 跑通;历史 budget/AP 视图与 review 证据仍保留。","预算预检页面级联动、高风险两轮复核、大额批次与非报销实体付款未在本轮 focused local 回归中重跑。","若财务域继续扩大试运行,再补 budget precheck 与高风险二次复核专项;当前 payment batch/AP happy path 已具备本地回归证据。"
|
"预算、支付批次与 AP 运营","optional","/budgets|/payment-batches|/ap-operations","finance|admin","BUDGET_PRECHECK_ENABLED|PAYMENT_BATCH_ENABLED|ERP_SYNC_ENABLED","budget_precheck_v1|payment_batch_v1|erp_sync","partial_done","issues/2026-03-29_08-07-14-p25-lite-budget-ap.csv|issues/2026-04-06_r52-ap-operations.csv|issues/2026-04-29_10-14-27-r78-reimbursement-payment-tail.csv|client/tests/e2e/reimbursement-payment-batch-flow.spec.ts|server/scripts/regression-payment-batches.sh","支付批次 maker-checker、AP 待付款快捷复核、finance 执行报销付款批次,以及 reimbursement paid 后 ERP preview pending outbox 已在本地 focused regression 跑通;历史 budget/AP 视图与 review 证据仍保留。","预算预检页面级联动、高风险两轮复核、大额批次与非报销实体付款未在本轮 focused local 回归中重跑。","若财务域继续扩大试运行,再补 budget precheck 与高风险二次复核专项;当前 payment batch/AP happy path 已具备本地回归证据。"
|
||||||
"ERP 集成与切换控制台","external","/system/integrations/erp|/system/cutover","integration admin|system.settings","ERP_SYNC_ENABLED|CUTOVER_CONSOLE_ENABLED","erp_sync|cutover_console_v1","partial_external","issues/2026-03-08_14-10-53-p19-erp-1-l5-masterdata-journal-bridge.csv|issues/2026-03-21_11-10-00-p29-replacement-readiness-refresh.csv|client/tests/e2e/live-smoke.spec.ts","ERP 管理页、mock/http 回归和只读 live smoke 有历史证据。","当前本地 trialrun 没有真实 ERP 出入站或 cutover 操作验证。","仅在外部环境专项下执行,不进入默认 trialrun gate。"
|
"ERP 集成与切换控制台","external","/system/integrations/erp|/system/cutover","integration admin|system.settings","ERP_SYNC_ENABLED|CUTOVER_CONSOLE_ENABLED","erp_sync|cutover_console_v1","partial_external","issues/2026-03-08_14-10-53-p19-erp-1-l5-masterdata-journal-bridge.csv|issues/2026-03-21_11-10-00-p29-replacement-readiness-refresh.csv|client/tests/e2e/live-smoke.spec.ts","ERP 管理页、mock/http 回归和只读 live smoke 有历史证据。","当前本地 trialrun 没有真实 ERP 出入站或 cutover 操作验证。","仅在外部环境专项下执行,不进入默认 trialrun gate。"
|
||||||
"系统治理、功能开关与审计","enabled_admin","/system/workspace|/system/settings|/system/feature-flags|/system/workflow-definitions|/audit-logs|/system/notification-channels","admin","WORKFLOW_DEFINITION_ADMIN_ENABLED","workflow_definition_admin_v1","partial_done","artifacts/r70/manual-trialrun-report.md|client/tests/e2e/settings-governance.spec.ts|client/tests/e2e/live-smoke.spec.ts|server/src/scripts/smoke-trialrun-runtime.js|client/tests/e2e/r75-automation-gap-fill.spec.ts","工作区设置、系统设置、功能开关、审计日志打开与导航边界有自动化和人工证据;R74 本地门禁已检查 workspace/flag/navigation 基线,R75 已补功能开关备注保存并恢复写路径。","流程定义、通知渠道、工作区其他写操作和审计留痕写入效果仍未在当前 trialrun 做完整专项。","保留 partial_done;后续若治理域纳入试运行,再补通知渠道与流程定义写路径。"
|
"系统治理、功能开关与审计","enabled_admin","/system/workspace|/system/settings|/system/feature-flags|/system/workflow-definitions|/audit-logs|/system/notification-channels","admin","WORKFLOW_DEFINITION_ADMIN_ENABLED","workflow_definition_admin_v1","partial_done","artifacts/r70/manual-trialrun-report.md|client/tests/e2e/settings-governance.spec.ts|client/tests/e2e/live-smoke.spec.ts|server/src/scripts/smoke-trialrun-runtime.js|client/tests/e2e/r75-automation-gap-fill.spec.ts","工作区设置、系统设置、功能开关、审计日志打开与导航边界有自动化和人工证据;R74 本地门禁已检查 workspace/flag/navigation 基线,R75 已补功能开关备注保存并恢复写路径。2026-05-04 只读 deploy 巡检已确认公网工作区仍为 `small_team_internal`,但远端 DB 中 `announcements_v1` / `global_search_v1` 仍是 `force_off`。","流程定义、通知渠道、工作区其他写操作和审计留痕写入效果仍未在当前 trialrun 做完整专项;公网部署态还存在 feature flag 与期望 workspace 导航不一致的问题。","保留 partial_done;先收口公网 feature flag 基线,再补通知渠道与流程定义写路径。"
|
||||||
"企微、HTTPS、部署态与并发","external","/login(企微入口)|部署运行时|多账号并发","all roles","APP_ORIGIN|COOKIE_SECURE|WECOM_*|PUBLIC_SECURITY_HARDENING_ENABLED","wecom_entry_v1|public_security_hardening_v1","blocked_external","deploy/trialrun/runbook.md|client/tests/e2e/wecom-entry.spec.ts|client/tests/e2e/live-smoke.spec.ts|server/src/scripts/smoke-trialrun-runtime.js|issues/2026-04-29_08-39-22-r76-external-trialrun-closeout.csv","本地/只读 smoke、env contract、导航/入口提示与 local runtime gate 已就绪。","真实企微 OAuth、HTTPS cookie secure、多用户并发协同仍缺环境级成功证据。腾讯 OCR 鉴权已确认不是当前主阻塞点:旧项目 `.env` 中至少一组凭证可用,当前主阻塞已转为应用层未传 PDF 参数导致的 `ImageDecodeFailed`。","企微/HTTPS/并发仍按 A3/A4 外部专项推进;OCR 从“外部凭证阻塞”切换为 R77 内部修复项,修完后再回到 live trialrun。"
|
"企微、HTTPS、部署态与并发","external","/login(企微入口)|部署运行时|多账号并发","all roles","APP_ORIGIN|COOKIE_SECURE|WECOM_*|PUBLIC_SECURITY_HARDENING_ENABLED","wecom_entry_v1|public_security_hardening_v1","blocked_external","deploy/trialrun/runbook.md|client/tests/e2e/wecom-entry.spec.ts|client/tests/e2e/live-smoke.spec.ts|server/src/scripts/smoke-trialrun-runtime.js|issues/2026-04-29_08-39-22-r76-external-trialrun-closeout.csv|issues/2026-05-04_13-11-16-r79-governance-live-readiness.csv","本地/只读 smoke、env contract、导航/入口提示与 local runtime gate 已就绪;`https://oa.hyinda.com/ready` 也已通过只读探活。","真实企微 OAuth、HTTPS cookie secure、多用户并发协同仍缺环境级成功证据。2026-05-04 公网部署巡检已确认 `WECOM_ENABLED=false`、`WECOM_ENTRY_ENABLED=false`、`WECOM_OAUTH_ENABLED=false`、`OCR_PROVIDER=mock`,且 DB 中 `wecom_entry_v1` 为 `force_off`;当前 live runtime smoke 还会因 `announcements_v1` 为 `force_off` 而失败。","企微/HTTPS/并发仍按 A4/A5 外部专项推进;先准备独立 smoke 账号并补齐企微后台配置,再修正公网 feature flag 基线后重跑 live smoke。"
|
||||||
|
|||||||
|
+14
-10
@@ -6,18 +6,20 @@
|
|||||||
- [ ] 已确认官网继续走 `hyinda.com / www.hyinda.com`,OA 使用独立二级域名(建议 `oa.hyinda.com`)
|
- [ ] 已确认官网继续走 `hyinda.com / www.hyinda.com`,OA 使用独立二级域名(建议 `oa.hyinda.com`)
|
||||||
- [ ] 服务器已执行 `bash deploy/trialrun/setup-server.sh`
|
- [ ] 服务器已执行 `bash deploy/trialrun/setup-server.sh`
|
||||||
- [ ] 已在服务器创建 OA 目录(默认 `/opt/hyb-oa-trialrun`)
|
- [ ] 已在服务器创建 OA 目录(默认 `/opt/hyb-oa-trialrun`)
|
||||||
|
- [ ] 已确认常规 SSH 用户为 `deploy`,系统配置用户为 `root`;当前不依赖 `shunli` 登录
|
||||||
- [ ] 已准备 `deploy/trialrun/.env`,并将 `APP_ORIGIN` 改为 OA 公网域名
|
- [ ] 已准备 `deploy/trialrun/.env`,并将 `APP_ORIGIN` 改为 OA 公网域名
|
||||||
- [ ] 已将 `COOKIE_SECURE` 设为 `true`
|
- [ ] 已将 `COOKIE_SECURE` 设为 `true`
|
||||||
- [ ] 已确认 `deploy/trialrun/.env` 作为部署事实源,新增环境变量优先补到该文件
|
- [ ] 已确认 `deploy/trialrun/.env` 作为部署事实源,新增环境变量优先补到该文件
|
||||||
- [ ] 已尽量使用无引号 env 值;历史带引号值当前兼容,但建议逐步清理
|
- [ ] 已尽量使用无引号 env 值;历史带引号值当前兼容,但建议逐步清理
|
||||||
- [ ] 已将 OA Nginx 配置放到 `/etc/nginx/sites-available/hyb-oa`
|
- [ ] 已将 OA `Caddyfile` 站点块配置到 `/etc/caddy/Caddyfile`
|
||||||
- [ ] 已上传 OA 域名证书到 `/etc/nginx/ssl/<oa-domain>/`
|
- [ ] 已确认 `oa.hyinda.com { reverse_proxy 127.0.0.1:3000 }` 生效
|
||||||
- [ ] 已执行 `nginx -t && systemctl reload nginx`
|
- [ ] 已执行 `systemctl reload caddy`
|
||||||
- [ ] 已从本地执行 `bash scripts/qa/run-release-gate.sh all` 或至少执行 `bash deploy/trialrun/deploy.sh`
|
- [ ] 已从本地执行 `bash scripts/qa/run-release-gate.sh all` 或至少执行 `bash deploy/trialrun/deploy.sh`
|
||||||
- [ ] 已通过 `https://<oa-domain>/ready` 或首页登录完成最小探活
|
- [ ] 已通过 `https://<oa-domain>/ready` 或首页登录完成最小探活
|
||||||
- [ ] 首次上线先执行系统初始化(migration + seed),不要直接导入旧库整库备份
|
- [ ] 首次上线先执行系统初始化(migration + seed),不要直接导入旧库整库备份
|
||||||
- [ ] 若要导数据,仅准备最小主数据:部门、员工、角色、在用资产、活跃项目、合同元数据
|
- [ ] 若要导数据,仅准备最小主数据:部门、员工、角色、在用资产、活跃项目、合同元数据
|
||||||
- [ ] 不导入历史审批单、通知历史、审计日志、聊天记录和涉密正文附件
|
- [ ] 不导入历史审批单、通知历史、审计日志、聊天记录和涉密正文附件
|
||||||
|
- [ ] 已确认远端部署目录 `/opt/hyb-oa-trialrun` 不是 git 工作树,发布优先走 `bash deploy/trialrun/deploy.sh`
|
||||||
|
|
||||||
## A. 发布前(Pre-flight)
|
## A. 发布前(Pre-flight)
|
||||||
- [ ] 确认当前版本已打 tag:`git tag -a trialrun-YYYYMMDD-NN -m "trialrun release"`
|
- [ ] 确认当前版本已打 tag:`git tag -a trialrun-YYYYMMDD-NN -m "trialrun release"`
|
||||||
@@ -32,16 +34,18 @@
|
|||||||
- [ ] `./scripts/backup-storage.sh`(记录输出文件名)
|
- [ ] `./scripts/backup-storage.sh`(记录输出文件名)
|
||||||
|
|
||||||
## B. 发布(Deploy)
|
## B. 发布(Deploy)
|
||||||
- [ ] `git checkout <tag>`
|
- [ ] 在本地仓库切到目标版本:`git checkout <tag>`,然后执行 `bash deploy/trialrun/deploy.sh`
|
||||||
- [ ] 构建并启动:
|
- [ ] 构建并启动:
|
||||||
- [ ] `docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server`
|
- [ ] `docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server`
|
||||||
- [ ] `docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env run --rm init`
|
- [ ] `docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env run --rm init`
|
||||||
- [ ] 探活:
|
- [ ] 探活:
|
||||||
- [ ] `curl -fsS http://127.0.0.1:3000/ready`
|
- [ ] `curl -fsS http://127.0.0.1:3000/ready`
|
||||||
- [ ] Runtime smoke:
|
- [ ] Runtime smoke:
|
||||||
- [ ] `docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-trialrun-runtime.js`
|
- [ ] `docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-trialrun-runtime.js`
|
||||||
|
- [ ] 若 runtime smoke 报 `announcements_v1` 或 `global_search_v1` 为 `force_off`,已记录为发布阻塞,不忽略通过
|
||||||
- [ ] external deps smoke:
|
- [ ] external deps smoke:
|
||||||
- [ ] `docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-external-deps.js`
|
- [ ] `docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-external-deps.js`
|
||||||
|
- [ ] 若 external deps smoke 通过,已确认通过前提不是“企微关闭 + OCR mock”误通过
|
||||||
- [ ] 登录验证已由 live smoke 与 release gate 覆盖;仅首次接入或第三方后台配置变更时补做人工确认
|
- [ ] 登录验证已由 live smoke 与 release gate 覆盖;仅首次接入或第三方后台配置变更时补做人工确认
|
||||||
|
|
||||||
## C. 发布后(Post-check)
|
## C. 发布后(Post-check)
|
||||||
@@ -56,12 +60,12 @@
|
|||||||
## D. 回滚(Rollback)
|
## D. 回滚(Rollback)
|
||||||
> 原则:如果涉及迁移,最快回滚通常是 “恢复备份 + 回到上个 tag”。
|
> 原则:如果涉及迁移,最快回滚通常是 “恢复备份 + 回到上个 tag”。
|
||||||
|
|
||||||
- [ ] 停止 server:`docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env stop server`
|
- [ ] 停止 server:`docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env stop server`
|
||||||
- [ ] 恢复 DB:`./scripts/restore-db.sh <db.dump>`
|
- [ ] 恢复 DB:`./scripts/restore-db.sh <db.dump>`
|
||||||
- [ ] 恢复存储:`./scripts/restore-storage.sh <storage.tar.gz> deploy/trialrun/data/storage`
|
- [ ] 恢复存储:`./scripts/restore-storage.sh <storage.tar.gz> deploy/trialrun/data/storage`
|
||||||
- [ ] 回到上个版本:`git checkout <previous-tag>`
|
- [ ] 回到上个版本:`git checkout <previous-tag>`
|
||||||
- [ ] 重启并探活:
|
- [ ] 重启并探活:
|
||||||
- [ ] `docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server`
|
- [ ] `docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server`
|
||||||
- [ ] `curl -fsS http://127.0.0.1:3000/ready`
|
- [ ] `curl -fsS http://127.0.0.1:3000/ready`
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# hyb-oa - 同机部署脚本(本地执行)
|
# hyb-oa - 远端单机部署脚本(本地执行,rsync 同步)
|
||||||
# ============================================================
|
# ============================================================
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -191,4 +191,4 @@ echo " 远端目录: ${REMOTE_DIR}"
|
|||||||
echo " 环境文件: ${REMOTE_ENV_FILE}"
|
echo " 环境文件: ${REMOTE_ENV_FILE}"
|
||||||
echo " 已自动执行:契约校验 + /ready + external deps smoke + runtime smoke"
|
echo " 已自动执行:契约校验 + /ready + external deps smoke + runtime smoke"
|
||||||
echo " 若本地已配置 LIVE_SMOKE_*,部署后会自动补跑网页 live smoke"
|
echo " 若本地已配置 LIVE_SMOKE_*,部署后会自动补跑网页 live smoke"
|
||||||
echo " 请确认 Nginx 已把 OA 域名反代到 127.0.0.1:3000"
|
echo " 请确认 Caddy 或等效反向代理已把 OA 域名反代到 127.0.0.1:3000"
|
||||||
|
|||||||
+32
-19
@@ -6,15 +6,26 @@
|
|||||||
- 官网继续保持 `hyinda.com / www.hyinda.com` 静态托管,不要改官网目录和配置。
|
- 官网继续保持 `hyinda.com / www.hyinda.com` 静态托管,不要改官网目录和配置。
|
||||||
- OA 新增独立二级域名,例如 `oa.hyinda.com`。
|
- OA 新增独立二级域名,例如 `oa.hyinda.com`。
|
||||||
- OA 推荐部署目录:`/opt/hyb-oa-trialrun`。
|
- OA 推荐部署目录:`/opt/hyb-oa-trialrun`。
|
||||||
- OA 推荐访问方式:`Nginx(443) -> 127.0.0.1:3000 -> docker compose(server)`。
|
- OA 推荐访问方式:`Caddy(443) -> 127.0.0.1:3000 -> docker-compose(server)`。
|
||||||
- 首次初始化时:
|
- 首次初始化时:
|
||||||
1. 服务器以 root 执行 `bash deploy/trialrun/setup-server.sh`
|
1. 服务器以 root 执行 `bash deploy/trialrun/setup-server.sh`
|
||||||
2. 手工创建 `deploy/trialrun/.env`
|
2. 手工创建 `deploy/trialrun/.env`
|
||||||
3. 手工放置 OA 的 Nginx 站点配置和证书
|
3. 手工更新 OA 的 `Caddyfile` 站点块并确认 TLS 正常
|
||||||
4. 本地执行 `bash scripts/qa/run-release-gate.sh all`(或至少执行 `bash deploy/trialrun/deploy.sh`)
|
4. 本地执行 `bash scripts/qa/run-release-gate.sh all`(或至少执行 `bash deploy/trialrun/deploy.sh`)
|
||||||
|
|
||||||
|
## 0B. 当前已核实的 `118.89.77.218` 部署基线(2026-05-04)
|
||||||
|
- SSH 用户:
|
||||||
|
- 常规部署:`[email protected]`
|
||||||
|
- 系统配置:`[email protected]`
|
||||||
|
- `shunli` 当前不可免密登录
|
||||||
|
- 反向代理:`caddy` 正在运行,`oa.hyinda.com` 已反代到 `127.0.0.1:3000`
|
||||||
|
- 部署目录:`/opt/hyb-oa-trialrun`
|
||||||
|
- 远端目录当前不是 git 工作树;发布应优先从本地执行 `bash deploy/trialrun/deploy.sh`,由脚本 `rsync` 到服务器
|
||||||
|
- 远端容器编排当前实际为 `docker-compose 1.29.2`;本 runbook 命令以 `docker-compose` 为准
|
||||||
|
- 当前公网 `.env` 已确认:`APP_ORIGIN=https://oa.hyinda.com`、`COOKIE_SECURE=true`、`PUBLIC_SECURITY_HARDENING_ENABLED=true`,但 `WECOM_*` 仍为 `false`,`OCR_PROVIDER=mock`
|
||||||
|
|
||||||
## 0. 前置条件
|
## 0. 前置条件
|
||||||
- Docker + Docker Compose(v2)
|
- Docker + Docker Compose(v1/v2 任一可用)
|
||||||
- 机器时间正确(影响 token / cron / OCR)
|
- 机器时间正确(影响 token / cron / OCR)
|
||||||
|
|
||||||
## 1. 首次启动(推荐:单域托管)
|
## 1. 首次启动(推荐:单域托管)
|
||||||
@@ -48,14 +59,14 @@ cp deploy/trialrun/.env.example deploy/trialrun/.env
|
|||||||
```bash
|
```bash
|
||||||
cd /path/to/hyb-oa
|
cd /path/to/hyb-oa
|
||||||
node deploy/trialrun/validate-env-contract.js
|
node deploy/trialrun/validate-env-contract.js
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d db
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d db
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server
|
||||||
```
|
```
|
||||||
|
|
||||||
可选:启用 MinIO(对象存储,F21):
|
可选:启用 MinIO(对象存储,F21):
|
||||||
```bash
|
```bash
|
||||||
cd /path/to/hyb-oa
|
cd /path/to/hyb-oa
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env --profile minio up -d minio minio_init
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env --profile minio up -d minio minio_init
|
||||||
```
|
```
|
||||||
|
|
||||||
可选:启用 Worker 进程(推荐在试运行/多进程模式使用):
|
可选:启用 Worker 进程(推荐在试运行/多进程模式使用):
|
||||||
@@ -63,13 +74,13 @@ docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/
|
|||||||
cd /path/to/hyb-oa
|
cd /path/to/hyb-oa
|
||||||
# 1) 在 deploy/trialrun/.env 中设置:JOBS_ENABLED="false"
|
# 1) 在 deploy/trialrun/.env 中设置:JOBS_ENABLED="false"
|
||||||
# 2) 启用 worker profile(会额外启动 worker 容器)
|
# 2) 启用 worker profile(会额外启动 worker 容器)
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env --profile worker up -d --build server worker
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env --profile worker up -d --build server worker
|
||||||
```
|
```
|
||||||
|
|
||||||
### 1.3 初始化(迁移 + 配置 seed + 试运行管理员)
|
### 1.3 初始化(迁移 + 配置 seed + 试运行管理员)
|
||||||
```bash
|
```bash
|
||||||
cd /path/to/hyb-oa
|
cd /path/to/hyb-oa
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env run --rm init
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env run --rm init
|
||||||
```
|
```
|
||||||
|
|
||||||
说明:
|
说明:
|
||||||
@@ -84,7 +95,7 @@ docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/
|
|||||||
curl -fsS http://127.0.0.1:3000/health
|
curl -fsS http://127.0.0.1:3000/health
|
||||||
curl -fsS http://127.0.0.1:3000/ready
|
curl -fsS http://127.0.0.1:3000/ready
|
||||||
curl -fsS http://127.0.0.1:3000/metrics | head
|
curl -fsS http://127.0.0.1:3000/metrics | head
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-trialrun-runtime.js
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-trialrun-runtime.js
|
||||||
```
|
```
|
||||||
|
|
||||||
说明:
|
说明:
|
||||||
@@ -92,6 +103,7 @@ docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/
|
|||||||
- 若本地存在完整 `LIVE_SMOKE_*` 环境变量,部署脚本会继续执行 `client npm run test:e2e:live`,用于公网只读 smoke。
|
- 若本地存在完整 `LIVE_SMOKE_*` 环境变量,部署脚本会继续执行 `client npm run test:e2e:live`,用于公网只读 smoke。
|
||||||
- 推荐直接执行 `bash scripts/qa/run-release-gate.sh all`,让 static / local smoke / full-local / deploy / live smoke 形成单一放行链。
|
- 推荐直接执行 `bash scripts/qa/run-release-gate.sh all`,让 static / local smoke / full-local / deploy / live smoke 形成单一放行链。
|
||||||
- 若再出现“数据库开了但功能被环境硬关”的情况,部署会直接失败,不再等到手工点页面才发现。
|
- 若再出现“数据库开了但功能被环境硬关”的情况,部署会直接失败,不再等到手工点页面才发现。
|
||||||
|
- 2026-05-04 公网只读巡检显示:`smoke-external-deps.js` 可以通过,但前提是 `WECOM_*` 未启用且 `OCR_PROVIDER=mock`;`smoke-trialrun-runtime.js` 当前会因 `announcements_v1` 为 `force_off` 失败。
|
||||||
|
|
||||||
浏览器访问:
|
浏览器访问:
|
||||||
- `http://127.0.0.1:3000`(单域托管前端)
|
- `http://127.0.0.1:3000`(单域托管前端)
|
||||||
@@ -116,7 +128,7 @@ set +a
|
|||||||
### 1.5.2 恢复(到同一台机器或新机器)
|
### 1.5.2 恢复(到同一台机器或新机器)
|
||||||
1) 先停止 server:
|
1) 先停止 server:
|
||||||
```bash
|
```bash
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env stop server
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env stop server
|
||||||
```
|
```
|
||||||
|
|
||||||
2) 恢复 DB:
|
2) 恢复 DB:
|
||||||
@@ -135,7 +147,7 @@ set +a
|
|||||||
|
|
||||||
4) 重启并验收:
|
4) 重启并验收:
|
||||||
```bash
|
```bash
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d server
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d server
|
||||||
curl -fsS http://127.0.0.1:3000/ready
|
curl -fsS http://127.0.0.1:3000/ready
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -174,11 +186,11 @@ curl -fsS http://127.0.0.1:3000/ready
|
|||||||
|
|
||||||
步骤:
|
步骤:
|
||||||
1) 先做备份(见 E14 脚本)
|
1) 先做备份(见 E14 脚本)
|
||||||
2) 拉取代码:`git pull` / `git checkout <tag>`
|
2) 从本地仓库执行 `bash deploy/trialrun/deploy.sh`(推荐);该脚本会把当前工作树 `rsync` 到 `/opt/hyb-oa-trialrun`,不依赖远端 `git pull`
|
||||||
3) 构建并重启:
|
3) 构建并重启:
|
||||||
```bash
|
```bash
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env run --rm init
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env run --rm init
|
||||||
```
|
```
|
||||||
|
|
||||||
发布/回滚 Checklist:
|
发布/回滚 Checklist:
|
||||||
@@ -189,14 +201,15 @@ docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/
|
|||||||
|
|
||||||
### 3.1 仅回滚代码
|
### 3.1 仅回滚代码
|
||||||
```bash
|
```bash
|
||||||
git checkout <previous-tag>
|
# 远端目录不是 git 工作树,推荐在本地切到目标 tag 后重新执行 deploy.sh
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server
|
# git checkout <previous-tag>
|
||||||
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3.2 需要 DB 回滚(推荐做法)
|
### 3.2 需要 DB 回滚(推荐做法)
|
||||||
1) 停止服务:
|
1) 停止服务:
|
||||||
```bash
|
```bash
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env stop server
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env stop server
|
||||||
```
|
```
|
||||||
2) 按 E14 恢复 DB + 文件存储备份
|
2) 按 E14 恢复 DB + 文件存储备份
|
||||||
3) 启动服务并验收 `/ready` 与登录
|
3) 启动服务并验收 `/ready` 与登录
|
||||||
@@ -210,7 +223,7 @@ docker logs -f hyb-oa-trialrun-server
|
|||||||
|
|
||||||
## 5. 优雅停机(E21)
|
## 5. 优雅停机(E21)
|
||||||
说明:
|
说明:
|
||||||
- `docker compose stop server` 会发送 `SIGTERM`,server 会尝试在 10s 内完成:
|
- `docker-compose stop server` 会发送 `SIGTERM`,server 会尝试在 10s 内完成:
|
||||||
- 停止 OCR/委派回收定时任务
|
- 停止 OCR/委派回收定时任务
|
||||||
- 关闭 HTTP 监听
|
- 关闭 HTTP 监听
|
||||||
- 断开 Prisma/PG 连接
|
- 断开 Prisma/PG 连接
|
||||||
@@ -325,7 +338,7 @@ npm run test:e2e -- tests/e2e/manual/live-invoice-ocr-batch.spec.ts
|
|||||||
- `OPENAPI_DOCS_ENABLED=false`
|
- `OPENAPI_DOCS_ENABLED=false`
|
||||||
3. 重新执行:
|
3. 重新执行:
|
||||||
```bash
|
```bash
|
||||||
docker compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server
|
docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env up -d --build server
|
||||||
```
|
```
|
||||||
4. 验证浏览器和企业微信 WebView 都能正常登录、刷新 token 与退出登录。
|
4. 验证浏览器和企业微信 WebView 都能正常登录、刷新 token 与退出登录。
|
||||||
|
|
||||||
|
|||||||
+18
-10
@@ -1,14 +1,14 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# hyb-oa - 同机部署服务器初始化脚本(在服务器上执行)
|
# hyb-oa - 同机部署服务器初始化脚本(在服务器上执行)
|
||||||
# 适用:官网 hyb-web 已在同机运行,现新增 OA 子域名
|
# 适用:官网 hyb-web 已在同机运行,现新增 OA 子域名;默认使用 Caddy 做反向代理
|
||||||
# ============================================================
|
# ============================================================
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
DEPLOY_USER="${DEPLOY_USER:-deploy}"
|
DEPLOY_USER="${DEPLOY_USER:-deploy}"
|
||||||
REMOTE_DIR="${REMOTE_DIR:-/opt/hyb-oa-trialrun}"
|
REMOTE_DIR="${REMOTE_DIR:-/opt/hyb-oa-trialrun}"
|
||||||
OA_HOST="${OA_HOST:-oa.hyinda.com}"
|
OA_HOST="${OA_HOST:-oa.hyinda.com}"
|
||||||
NGINX_SITE_NAME="${NGINX_SITE_NAME:-hyb-oa}"
|
CADDY_CONFIG_PATH="${CADDY_CONFIG_PATH:-/etc/caddy/Caddyfile}"
|
||||||
|
|
||||||
need_cmd() {
|
need_cmd() {
|
||||||
command -v "$1" >/dev/null 2>&1 || {
|
command -v "$1" >/dev/null 2>&1 || {
|
||||||
@@ -22,11 +22,17 @@ if [[ "$(id -u)" -ne 0 ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ">>> 1. 安装 Docker / Compose 插件 / rsync"
|
echo ">>> 1. 安装 Docker / Compose 插件 / rsync / Caddy"
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
apt-get update -y
|
apt-get update -y
|
||||||
apt-get install -y docker.io rsync
|
apt-get install -y docker.io rsync
|
||||||
|
|
||||||
|
if apt-cache show caddy >/dev/null 2>&1; then
|
||||||
|
apt-get install -y caddy
|
||||||
|
else
|
||||||
|
echo "[WARN] 未在当前软件源找到 caddy,请后续手工安装。" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
if apt-cache show docker-compose-plugin >/dev/null 2>&1; then
|
if apt-cache show docker-compose-plugin >/dev/null 2>&1; then
|
||||||
apt-get install -y docker-compose-plugin
|
apt-get install -y docker-compose-plugin
|
||||||
elif apt-cache show docker-compose-v2 >/dev/null 2>&1; then
|
elif apt-cache show docker-compose-v2 >/dev/null 2>&1; then
|
||||||
@@ -38,6 +44,10 @@ else
|
|||||||
fi
|
fi
|
||||||
systemctl enable docker
|
systemctl enable docker
|
||||||
systemctl start docker
|
systemctl start docker
|
||||||
|
if systemctl list-unit-files caddy.service >/dev/null 2>&1; then
|
||||||
|
systemctl enable caddy || true
|
||||||
|
systemctl start caddy || true
|
||||||
|
fi
|
||||||
|
|
||||||
echo ">>> 2. 让 ${DEPLOY_USER} 可运行 Docker"
|
echo ">>> 2. 让 ${DEPLOY_USER} 可运行 Docker"
|
||||||
id "${DEPLOY_USER}" >/dev/null 2>&1 || {
|
id "${DEPLOY_USER}" >/dev/null 2>&1 || {
|
||||||
@@ -50,13 +60,11 @@ echo ">>> 3. 创建 OA 目录"
|
|||||||
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/postgres"
|
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/postgres"
|
||||||
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/storage"
|
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/storage"
|
||||||
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/minio"
|
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/minio"
|
||||||
mkdir -p "/etc/nginx/ssl/${OA_HOST}"
|
|
||||||
chown -R "${DEPLOY_USER}:${DEPLOY_USER}" "${REMOTE_DIR}"
|
chown -R "${DEPLOY_USER}:${DEPLOY_USER}" "${REMOTE_DIR}"
|
||||||
|
|
||||||
echo ">>> 4. 初始化完成,后续手工操作:"
|
echo ">>> 4. 初始化完成,后续手工操作:"
|
||||||
echo " 1) 把 OA Nginx 配置放到 /etc/nginx/sites-available/${NGINX_SITE_NAME}"
|
echo " 1) 在 ${CADDY_CONFIG_PATH} 增加站点块:${OA_HOST} { reverse_proxy 127.0.0.1:3000 }"
|
||||||
echo " 2) ln -sf /etc/nginx/sites-available/${NGINX_SITE_NAME} /etc/nginx/sites-enabled/${NGINX_SITE_NAME}"
|
echo " 2) 执行 systemctl reload caddy"
|
||||||
echo " 3) 上传证书到 /etc/nginx/ssl/${OA_HOST}/server.crt 和 server.key"
|
echo " 3) 在 ${REMOTE_DIR}/deploy/trialrun/.env 写入 OA 环境变量"
|
||||||
echo " 4) 在 ${REMOTE_DIR}/deploy/trialrun/.env 写入 OA 环境变量"
|
echo " 4) 切换到 deploy 用户后,从本地执行 deploy/trialrun/deploy.sh"
|
||||||
echo " 5) 切换到 deploy 用户后,从本地执行 deploy/trialrun/deploy.sh"
|
echo " 5) 用 curl -I https://${OA_HOST}/ready 或首页访问做最小探活"
|
||||||
echo " 6) 执行 nginx -t && systemctl reload nginx"
|
|
||||||
|
|||||||
+17
-6
@@ -1,12 +1,22 @@
|
|||||||
# hyb-oa 系统架构概览
|
# hyb-oa 系统架构概览
|
||||||
|
|
||||||
**版本**:1.2
|
**版本**:1.3
|
||||||
**日期**:2026-02-09
|
**日期**:2026-05-04
|
||||||
**目的**:描述系统当前实现(P5/F25 完备态)并为未来演进提供参考。
|
**目的**:描述系统当前实现、当前部署基线和仍待外部环境闭环的部分,为试运行与后续演进提供参考。
|
||||||
|
|
||||||
**相关文档**:
|
**相关文档**:
|
||||||
- [需求规格说明书](./requirements-specification.md)
|
- [需求规格说明书](./requirements-specification.md)
|
||||||
- [实现状态矩阵(P5-P10)](./feature-matrix.md)
|
- [实现状态矩阵](./feature-matrix.md)
|
||||||
|
- [试运行覆盖矩阵](../artifacts/r75/coverage-matrix.csv)
|
||||||
|
- [人工试运行报告](../artifacts/r70/manual-trialrun-report.md)
|
||||||
|
|
||||||
|
**2026-05-04 已核实部署基线**:
|
||||||
|
- 公网入口:`https://oa.hyinda.com`
|
||||||
|
- 反向代理:`caddy`,当前配置为 `oa.hyinda.com -> reverse_proxy 127.0.0.1:3000`
|
||||||
|
- 部署用户:`deploy`(常规) / `root`(系统配置),`shunli` 当前不可免密登录
|
||||||
|
- 部署目录:`/opt/hyb-oa-trialrun`
|
||||||
|
- 部署方式:本地执行 `deploy/trialrun/deploy.sh`,通过 `rsync` 同步到远端;远端目录不是 git 工作树
|
||||||
|
- 容器编排:脚本兼容 `docker compose` 与 `docker-compose`,当前服务器实际为 `docker-compose 1.29.2`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -21,7 +31,7 @@ graph TB
|
|||||||
end
|
end
|
||||||
|
|
||||||
subgraph Cluster["部署环境 (Docker Compose Profiles)"]
|
subgraph Cluster["部署环境 (Docker Compose Profiles)"]
|
||||||
Proxy["可选:Nginx/Caddy\nTLS/反代/前端托管"]
|
Proxy["Caddy\nTLS/反代/前端托管"]
|
||||||
|
|
||||||
subgraph Server_Nodes["计算层"]
|
subgraph Server_Nodes["计算层"]
|
||||||
API["Fastify API\n(JOBS_ENABLED=false)"]
|
API["Fastify API\n(JOBS_ENABLED=false)"]
|
||||||
@@ -54,9 +64,10 @@ graph TB
|
|||||||
```
|
```
|
||||||
|
|
||||||
**关键变更说明**:
|
**关键变更说明**:
|
||||||
- **Worker 进程独立**:支持通过 `docker compose --profile worker` 拆分 API 与定时作业进程。
|
- **Worker 进程独立**:支持通过 `docker compose --profile worker` 或 `docker-compose --profile worker` 拆分 API 与定时作业进程。
|
||||||
- **存储抽象层**:适配本地文件系统与 S3/MinIO,通过 `STORAGE_DRIVER` 切换。
|
- **存储抽象层**:适配本地文件系统与 S3/MinIO,通过 `STORAGE_DRIVER` 切换。
|
||||||
- **治理接入**:内置 Prometheus 指标采集 `/metrics`。
|
- **治理接入**:内置 Prometheus 指标采集 `/metrics`。
|
||||||
|
- **远端发布模型**:当前生产化试运行通过 `deploy/trialrun/deploy.sh` 从本地 `rsync` 到服务器,不依赖远端 `git pull`。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+10
-3
@@ -1,8 +1,15 @@
|
|||||||
# hyb-oa 实现状态矩阵(P5-P19+IM-1+ERP-3+R10+MCP-1+AI-1+TRAVEL-1+TRAVEL-2+TRAVEL-3+PWA-1+PWA-2+PROD-1+R11)
|
# hyb-oa 实现状态矩阵(历史主表 + R70-R79 试运行补充)
|
||||||
|
|
||||||
**快照日期**:2026-03-13
|
**快照日期**:2026-05-04
|
||||||
**范围**:`F1-F42`(含 `F19b/F19c/F19d`) + `R1-S2` + `P9A1-P9D1` + `P10E1-P10G1` + `G0-G6` + `H1` + `M1-M4` + `P13-0-P13-8` + `P14-0-P14-8` + `P15A-0-P15A-5` + `P15B-0-P15B-6` + `P16A-0-P16A-6` + `P16B-0-P16B-6` + `P16C-0-P16C-6` + `R9-0-R9-3` + `G2-0-G2-6` + `P17A-0-P17A-6` + `P17B-0-P17B-6` + `P18A-0-P18A-6` + `P18B-0-P18B-6` + `P19-0-P19-6` + `P19IM1-0-P19IM1-6` + `P19ERP1-0-P19ERP1-6` + `P19ERP2-0-P19ERP2-6` + `P19ERP3-0-P19ERP3-6` + `R10-0-R10-4` + `P19MCP1-0-P19MCP1-4` + `P19AI1-0-P19AI1-5` + `P20TRAVEL1-0-P20TRAVEL1-5` + `P20TRAVEL2-0-P20TRAVEL2-5` + `P20TRAVEL3-0-P20TRAVEL3-5` + `P21PWA1-0-P21PWA1-5` + `P21PWA2-0-P21PWA2-5` + `P22PROD1-0-P22PROD1-5` + `R11-0-R11-5`,共 278 项。
|
**范围**:`F1-F42`(含 `F19b/F19c/F19d`) + `R1-S2` + `P9A1-P9D1` + `P10E1-P10G1` + `G0-G6` + `H1` + `M1-M4` + `P13-0-P13-8` + `P14-0-P14-8` + `P15A-0-P15A-5` + `P15B-0-P15B-6` + `P16A-0-P16A-6` + `P16B-0-P16B-6` + `P16C-0-P16C-6` + `R9-0-R9-3` + `G2-0-G2-6` + `P17A-0-P17A-6` + `P17B-0-P17B-6` + `P18A-0-P18A-6` + `P18B-0-P18B-6` + `P19-0-P19-6` + `P19IM1-0-P19IM1-6` + `P19ERP1-0-P19ERP1-6` + `P19ERP2-0-P19ERP2-6` + `P19ERP3-0-P19ERP3-6` + `R10-0-R10-4` + `P19MCP1-0-P19MCP1-4` + `P19AI1-0-P19AI1-5` + `P20TRAVEL1-0-P20TRAVEL1-5` + `P20TRAVEL2-0-P20TRAVEL2-5` + `P20TRAVEL3-0-P20TRAVEL3-5` + `P21PWA1-0-P21PWA1-5` + `P21PWA2-0-P21PWA2-5` + `P22PROD1-0-P22PROD1-5` + `R11-0-R11-5`,共 278 项。
|
||||||
**事实源**:`issues/2026-02-09_13-39-02-p5-blueprint-v3.csv` + `issues/2026-02-09_23-30-00-p6-p8-remaining-work-master.csv` + `issues/2026-02-10_09-42-31-p9-maintenance-performance-matrix.csv` + `issues/2026-02-10_10-35-30-p10-production-hardening.csv` + `issues/2026-02-11-p11-p12-governance-mobile.csv` + `issues/2026-02-12_01-09-41-p13-l5-governance.csv` + `issues/2026-02-13_00-11-56-p14-l5-operationalization.csv` + `issues/2026-03-06_14-30-00-p15a-l5-permission-decouple.csv` + `issues/2026-03-06_14-30-00-p15b-l5-leave-v1.csv` + `issues/2026-03-07_13-47-05-p16a-l5-master-data-core.csv` + `issues/2026-03-07_16-22-07-p16b-l5-holiday-calendar.csv` + `issues/2026-03-07_17-14-39-p16c-l5-suppliers.csv` + `issues/2026-03-07_18-15-03-r9-g2-p19-roadmap-refresh.csv` + `issues/2026-03-07_18-16-00-g2-l5-cross-domain-bridge.csv` + `issues/2026-03-07_19-33-09-p17a-l5-procurement-core.csv` + `issues/2026-03-07_21-00-37-p17b-l5-procurement-budget-archive.csv` + `issues/2026-03-07_22-02-09-p18a-l5-asset-registry-core.csv` + `issues/2026-03-07_22-34-03-p18b-l5-asset-movements-inventory.csv` + `issues/2026-03-07_23-22-00-p19-l4-integration-readiness.csv` + `issues/2026-03-08_12-18-10-p19-im-1-l5-collaboration-adapter.csv` + `issues/2026-03-08_14-10-53-p19-erp-1-l5-masterdata-journal-bridge.csv` + `issues/2026-03-08_22-46-51-p19-erp-2-l5-procurement-commitment-archive.csv` + `issues/2026-03-09_00-10-00-p19-erp-3-l5-asset-ledger-summary.csv` + `issues/2026-03-09_10-15-00-r10-post-erp3-roadmap-refresh.csv` + `issues/2026-03-09_10-25-00-p19-mcp-1-l4-readonly-tools-baseline.csv` + `issues/2026-03-10_12-54-30-p19-ai-1-l5-suggestion-workbench-refresh.csv` + `issues/2026-03-10_17-32-21-p20-travel-1-l5-request-intake-refresh.csv` + `issues/2026-03-10_21-05-59-p20-travel-2-l5-corporate-payments-refresh.csv` + `issues/2026-03-11_09-57-28-p20-travel-3-l5-reconciliation-erp-bridge-refresh.csv` + `issues/2026-03-11_17-50-39-p21-pwa-1-l5-asset-scan-refresh.csv` + `issues/2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv` + `issues/2026-03-12_16-58-44-p22-prod-1-l5-production-hardening.csv` + `issues/2026-03-13_10-30-00-r11-contract-reconciliation-and-spec-refresh.csv`(执行合同)
|
**事实源**:`issues/2026-02-09_13-39-02-p5-blueprint-v3.csv` + `issues/2026-02-09_23-30-00-p6-p8-remaining-work-master.csv` + `issues/2026-02-10_09-42-31-p9-maintenance-performance-matrix.csv` + `issues/2026-02-10_10-35-30-p10-production-hardening.csv` + `issues/2026-02-11-p11-p12-governance-mobile.csv` + `issues/2026-02-12_01-09-41-p13-l5-governance.csv` + `issues/2026-02-13_00-11-56-p14-l5-operationalization.csv` + `issues/2026-03-06_14-30-00-p15a-l5-permission-decouple.csv` + `issues/2026-03-06_14-30-00-p15b-l5-leave-v1.csv` + `issues/2026-03-07_13-47-05-p16a-l5-master-data-core.csv` + `issues/2026-03-07_16-22-07-p16b-l5-holiday-calendar.csv` + `issues/2026-03-07_17-14-39-p16c-l5-suppliers.csv` + `issues/2026-03-07_18-15-03-r9-g2-p19-roadmap-refresh.csv` + `issues/2026-03-07_18-16-00-g2-l5-cross-domain-bridge.csv` + `issues/2026-03-07_19-33-09-p17a-l5-procurement-core.csv` + `issues/2026-03-07_21-00-37-p17b-l5-procurement-budget-archive.csv` + `issues/2026-03-07_22-02-09-p18a-l5-asset-registry-core.csv` + `issues/2026-03-07_22-34-03-p18b-l5-asset-movements-inventory.csv` + `issues/2026-03-07_23-22-00-p19-l4-integration-readiness.csv` + `issues/2026-03-08_12-18-10-p19-im-1-l5-collaboration-adapter.csv` + `issues/2026-03-08_14-10-53-p19-erp-1-l5-masterdata-journal-bridge.csv` + `issues/2026-03-08_22-46-51-p19-erp-2-l5-procurement-commitment-archive.csv` + `issues/2026-03-09_00-10-00-p19-erp-3-l5-asset-ledger-summary.csv` + `issues/2026-03-09_10-15-00-r10-post-erp3-roadmap-refresh.csv` + `issues/2026-03-09_10-25-00-p19-mcp-1-l4-readonly-tools-baseline.csv` + `issues/2026-03-10_12-54-30-p19-ai-1-l5-suggestion-workbench-refresh.csv` + `issues/2026-03-10_17-32-21-p20-travel-1-l5-request-intake-refresh.csv` + `issues/2026-03-10_21-05-59-p20-travel-2-l5-corporate-payments-refresh.csv` + `issues/2026-03-11_09-57-28-p20-travel-3-l5-reconciliation-erp-bridge-refresh.csv` + `issues/2026-03-11_17-50-39-p21-pwa-1-l5-asset-scan-refresh.csv` + `issues/2026-03-12_04-32-13-p21-pwa-2-l5-offline-deeplink-refresh.csv` + `issues/2026-03-12_16-58-44-p22-prod-1-l5-production-hardening.csv` + `issues/2026-03-13_10-30-00-r11-contract-reconciliation-and-spec-refresh.csv` + `issues/2026-04-26_r70-manual-trialrun.csv` + `issues/2026-04-29_08-39-22-r76-external-trialrun-closeout.csv` + `issues/2026-04-29_09-19-07-r77-ocr-pdf-first.csv` + `issues/2026-04-29_10-14-27-r78-reimbursement-payment-tail.csv` + `issues/2026-05-04_13-11-16-r79-governance-live-readiness.csv` + `artifacts/r75/coverage-matrix.csv`(执行合同与覆盖证据)
|
||||||
|
|
||||||
|
## R70-R79 试运行与外部环境补充(2026-04-28 至 2026-05-04)
|
||||||
|
|
||||||
|
- **本地核心链路**:员工/经理/管理员的本地 trialrun 主链路已在 R70/R71 通过;R73-R78 进一步补齐了真实 PDF OCR、深层业务辅助回归和财务支付尾链 focused regression。
|
||||||
|
- **当前公网部署基线**:`oa.hyinda.com` 已接到 `caddy -> 127.0.0.1:3000`,远端目录为 `/opt/hyb-oa-trialrun`,部署由本地 `rsync` 驱动,远端不是 git 工作树。
|
||||||
|
- **当前外部阻塞**:截至 2026-05-04,公网 `.env` 仍为 `WECOM_ENABLED=false`、`WECOM_ENTRY_ENABLED=false`、`WECOM_OAUTH_ENABLED=false`、`OCR_PROVIDER=mock`;同时远端 `feature_flags` 中 `announcements_v1`、`global_search_v1`、`wecom_entry_v1` 为 `force_off`,导致 runtime smoke 未通过。
|
||||||
|
- **阅读方式**:本文件的主表仍保留历史主线;与 trialrun、覆盖率、外部环境有关的现状判断,应结合 `artifacts/r75/coverage-matrix.csv` 与 `artifacts/r70/manual-trialrun-report.md` 一起看。
|
||||||
|
|
||||||
## R12 增量能力(2026-03-21)
|
## R12 增量能力(2026-03-21)
|
||||||
|
|
||||||
|
|||||||
+22
-5
@@ -1,13 +1,30 @@
|
|||||||
# hyb-oa 实施计划(Phase 1 / P0)
|
# hyb-oa 实施计划(历史 Phase 1 引导 + 当前执行口径)
|
||||||
|
|
||||||
**日期**:2026-02-06
|
**日期**:2026-05-04
|
||||||
**范围**:报销系统及其依赖模块(员工/权限/工作流/附件)
|
**范围**:保留 2026-02 的引导性实施计划,同时补充当前试运行收口与外部环境闭环口径。
|
||||||
|
|
||||||
|
## 当前阶段(2026-05-04)
|
||||||
|
|
||||||
|
- 当前系统已不处于 `Phase 1 / P0` 开发阶段;本地核心 happy path、真实 PDF OCR 和报销付款尾链已具备回归证据。
|
||||||
|
- 当前优先级不是继续堆新功能,而是:
|
||||||
|
1. 治理事实源刷新
|
||||||
|
2. 外部环境闭环(HTTPS / 企微 / live smoke / 并发)
|
||||||
|
3. 发布门禁与部署 runbook 收口
|
||||||
|
- 当前执行事实源优先级:
|
||||||
|
- 最新执行合同:`issues/*.csv`
|
||||||
|
- 业务覆盖:`artifacts/r75/coverage-matrix.csv`
|
||||||
|
- 试运行结论:`artifacts/r70/manual-trialrun-report.md`
|
||||||
|
- 全局状态矩阵:`docs/feature-matrix.md`
|
||||||
|
|
||||||
|
## 历史说明
|
||||||
|
|
||||||
|
下文保留的是 2026-02 的 Phase 1 引导计划,主要用于追溯设计出发点、资产复用和里程碑拆解;它**不是**当前最优先的执行合同。
|
||||||
|
|
||||||
## 0. 前置结论(不可再分叉)
|
## 0. 前置结论(不可再分叉)
|
||||||
- 技术栈:Fastify + Prisma + PostgreSQL(见 `docs/tech_stack_report.md`)
|
- 技术栈:Fastify + Prisma + PostgreSQL(见 `docs/tech_stack_report.md`)
|
||||||
- 规格书:以 `docs/requirements-specification.md` 为单一事实源
|
- 规格书:以 `docs/requirements-specification.md` 为单一事实源
|
||||||
|
|
||||||
## 1. 复用资产清单(从 shenzhou-business-suite 迁移到 hyb-oa)
|
## 1. 历史:复用资产清单(从 shenzhou-business-suite 迁移到 hyb-oa)
|
||||||
| 资产 | 来源 | 复用方式 | 需要改造 |
|
| 资产 | 来源 | 复用方式 | 需要改造 |
|
||||||
| :--- | :--- | :--- | :--- |
|
| :--- | :--- | :--- | :--- |
|
||||||
| 工作流 4 表结构 | `shenzhou-business-suite/supabase/schema/70_workflow/01_workflow_02_tables.sql` | 转 Prisma schema | Supabase/RPC → Fastify service 事务 |
|
| 工作流 4 表结构 | `shenzhou-business-suite/supabase/schema/70_workflow/01_workflow_02_tables.sql` | 转 Prisma schema | Supabase/RPC → Fastify service 事务 |
|
||||||
@@ -22,7 +39,7 @@
|
|||||||
| UI 组件 | `shenzhou-business-suite/src/components/ui/*` | 实现阶段复制到 `client/src/` | 替换路由/样式变量;移除 Supabase 依赖 |
|
| UI 组件 | `shenzhou-business-suite/src/components/ui/*` | 实现阶段复制到 `client/src/` | 替换路由/样式变量;移除 Supabase 依赖 |
|
||||||
| 测试基建 | `playwright` + `vitest` 配置 | 实现阶段迁移 | P0 覆盖鉴权/工作流/判重核心路径 |
|
| 测试基建 | `playwright` + `vitest` 配置 | 实现阶段迁移 | P0 覆盖鉴权/工作流/判重核心路径 |
|
||||||
|
|
||||||
## 2. Phase 1(P0)里程碑拆解(按可开工顺序)
|
## 2. 历史:Phase 1(P0)里程碑拆解(按可开工顺序)
|
||||||
|
|
||||||
### Milestone 1:Prisma schema 草稿 + 评审
|
### Milestone 1:Prisma schema 草稿 + 评审
|
||||||
**目标**:把关键表结构确定下来(后续开发不再反复改 schema)。
|
**目标**:把关键表结构确定下来(后续开发不再反复改 schema)。
|
||||||
|
|||||||
@@ -1303,7 +1303,7 @@ cancelled (作废/终止,终态)
|
|||||||
| 响应式 | PC + 移动端(响应式 Web) |
|
| 响应式 | PC + 移动端(响应式 Web) |
|
||||||
| 性能 | 页面加载 <2s,API 响应 <500ms(P95) |
|
| 性能 | 页面加载 <2s,API 响应 <500ms(P95) |
|
||||||
| 安全 | JWT(access+refresh rotation)、RBAC 权限码、审计日志、敏感字段加密与脱敏 |
|
| 安全 | JWT(access+refresh rotation)、RBAC 权限码、审计日志、敏感字段加密与脱敏 |
|
||||||
| 部署 | Docker + Nginx(反向代理),域名 oa.hyinda.com |
|
| 部署 | Docker + Caddy/Nginx(反向代理),域名 oa.hyinda.com |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
| 认证 | JWT(access + refresh rotation),refresh 以 httpOnly Cookie 传输 |
|
| 认证 | JWT(access + refresh rotation),refresh 以 httpOnly Cookie 传输 |
|
||||||
| 权限 | RBAC(权限码) |
|
| 权限 | RBAC(权限码) |
|
||||||
| 审计 | `workflow_history`(流程)+ `audit_logs`(安全与关键变更) |
|
| 审计 | `workflow_history`(流程)+ `audit_logs`(安全与关键变更) |
|
||||||
| 部署 | Docker + Nginx(反向代理) |
|
| 部署 | Docker + Caddy/Nginx(反向代理) |
|
||||||
|
|
||||||
## 2. 关键取舍(为什么这么选)
|
## 2. 关键取舍(为什么这么选)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
"ID","Title","Description","Acceptance","Test_Method","Tools","Dev_Status","Review1_Status","Regression_Status","Files","Dependencies","Notes"
|
||||||
|
"A1","R79 执行合同建档与范围冻结","创建并校验 R79 合同,范围仅覆盖治理收口、外部环境 runbook 对齐、发布门禁与公网 smoke 现状核查;不新增业务功能,不做 Prisma 迁移,不把任何真实密钥写入仓库。","issues/2026-05-04_13-11-16-r79-governance-live-readiness.csv 列完整并通过校验;A2-A5 依赖顺序清晰;Notes 写明本轮只做治理与部署准备。","命令:`python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-04_13-11-16-r79-governance-live-readiness.csv`。业务:确认本轮执行合同覆盖“文档事实源 -> 外部试运行准备 -> 发布门禁”链路,而非新增业务开发。","manual","DONE","DONE","DONE","issues/2026-05-04_13-11-16-r79-governance-live-readiness.csv","[]","回滚路径:删除本 CSV,不影响运行时。约束:本轮不修改真实腾讯/企微密钥,不改业务数据。2026-05-04:CSV 已写入并通过 validate_issues_csv.py 校验。"
|
||||||
|
"A2","现状事实源刷新","刷新架构、实施计划、功能矩阵/覆盖矩阵中的过期叙述,使文档能反映当前已完成的 trialrun、OCR、支付尾链与外部阻塞项。","docs 与 artifacts 中的日期、范围、事实源引用、当前结论与 2026-04-28 至 2026-05-04 的实际状态一致;不再保留明显过期的 `Phase 1 / P0` 主叙事。","命令:`python3 scripts/validate-feature-matrix.py`、`rg -n 'Phase 1|P0|2026-02-09|2026-03-13' docs artifacts/r75/coverage-matrix.csv`。业务:人工检查“本地 happy path 已闭环、外部环境仍待专项验证”的对外叙述是否一致。","manual","DONE","DONE","DONE","docs/architecture.md|docs/implementation_plan.md|docs/feature-matrix.md|artifacts/r75/coverage-matrix.csv","[""A1""]","只做事实源刷新,不顺手扩写需求规格。若发现更大范围文档债,记录到后续合同。2026-05-04:已刷新 architecture / implementation_plan / feature-matrix / coverage-matrix 顶层事实,`python3 scripts/validate-feature-matrix.py` 通过。"
|
||||||
|
"A3","历史执行合同权威映射收口","梳理早期 issues CSV 与后续 superseding CSV 的替代关系,补 README 或索引说明,避免继续把旧 TODO 误读为当前待办。","issues/README.md 或等效索引明确说明历史合同的 authoritative mapping;至少覆盖 P5/P5-v2/P5-v3 以及 R70-R78 与 coverage matrix 的引用关系;不批量回改历史 CSV 内容。","命令:`rg -n 'p5-blueprint|r70|r78|supersed|authoritative|事实源' issues docs artifacts`。业务:人工检查新人按 README 能判断“看哪份合同才代表当前状态”。","manual","DONE","DONE","DONE","issues/README.md|issues/2026-02-09_11-17-07-p5-blueprint.csv|issues/2026-02-09_12-34-42-p5-blueprint-v2.csv|issues/2026-02-09_13-39-02-p5-blueprint-v3.csv|issues/2026-04-26_r70-manual-trialrun.csv|issues/2026-04-29_10-14-27-r78-reimbursement-payment-tail.csv","[""A2""]","原则:保留历史记录,只补权威映射与阅读入口,不大面积改旧合同状态。2026-05-04:已在 issues/README.md 增加权威读取顺序和历史合同处理原则。"
|
||||||
|
"A4","外部环境与部署手册收口","基于真实服务器 `118.89.77.218`、`oa.hyinda.com`、`caddy`、`deploy/root` 与 `docker-compose` 现状,修正试运行 runbook、checklist 与人工配合说明。","runbook/checklist/manual checklist 中的代理层、登录用户、部署目录、探活命令、手工配合步骤与远端真实现状一致;明确哪些动作可由 Codex 代做、哪些必须人工在企微后台操作。","命令:`curl -k -I https://oa.hyinda.com/ready`、`ssh [email protected] 'docker ps'`、`ssh [email protected] 'sed -n 1,200p /etc/caddy/Caddyfile'`。业务:人工复核文档已正确表达“Caddy 反代 -> 3000 容器服务 -> HTTPS/企微/独立 smoke 账号”的部署链路。","manual|ssh","DONE","DONE","DONE","deploy/trialrun/runbook.md|deploy/trialrun/checklist.md|artifacts/r70/manual-trialrun-checklist.md","[""A2""]","已知远端现状:`deploy`/`root` 可免密,`shunli` 不可;`oa.hyinda.com` 已反代到 `127.0.0.1:3000`;远端目录 `/opt/hyb-oa-trialrun` 不是 git 工作树;远端仅有 `docker-compose`。2026-05-04:已把 runbook / checklist / manual trialrun checklist 改为 Caddy + deploy/root + rsync 部署口径,并同步更新 setup-server.sh。"
|
||||||
|
"A5","发布门禁与公网 smoke 收口","在不改真实业务数据的前提下,核对并收口 release gate / smoke 现状,记录当前阻塞项和后续最小人工动作。","发布门禁入口、live smoke 前置、远端只读 smoke 结果与当前部署事实一致;至少记录 1) 远端 `smoke-trialrun-runtime` 失败点;2) `smoke-external-deps` 通过前提;3) live smoke 仍缺的账号/企微配置。","命令:`cd server && ./scripts/regression-all.sh`(本地需要时);远端:`ssh [email protected] 'cd /opt/hyb-oa-trialrun && docker-compose -f deploy/trialrun/docker-compose.yml --env-file deploy/trialrun/.env exec -T server node src/scripts/smoke-trialrun-runtime.js'`、`... smoke-external-deps.js`。业务:确认“发布前门禁 -> 远端探活 -> 公网只读 smoke”的责任边界清楚,并能给出最小人工清单。","manual|ssh|playwright","DONE","DONE","DONE","scripts/check-minimal.sh|scripts/coverage_gate.js|scripts/qa/run-release-gate.sh|scripts/qa/run-web-gates.sh|artifacts/r70/manual-trialrun-report.md","[""A4""]","2026-05-04 已做只读核查:`smoke-external-deps` 通过,但前提是 `WECOM_*` 未启用且 `OCR_PROVIDER=mock`;`smoke-trialrun-runtime` 失败于 `announcements_v1 => enabled=false reason=flag_force_off envEnabled=true`。后续若要真正通过公网 gate,仍需独立 smoke 账号和企微后台配置。2026-05-04:已将公网巡检结果回填到 manual-trialrun-report,并完成 deploy/deploy-gate 文档口径收口。"
|
||||||
|
+11
@@ -43,3 +43,14 @@
|
|||||||
- 字段含英文逗号时,必须用双引号包裹。
|
- 字段含英文逗号时,必须用双引号包裹。
|
||||||
- 字段内多值可用 `|`。
|
- 字段内多值可用 `|`。
|
||||||
- UTF-8 编码。
|
- UTF-8 编码。
|
||||||
|
|
||||||
|
## 权威读取顺序
|
||||||
|
- **当前执行合同**:优先查看时间最新且已批准的 `issues/*.csv`;当前治理收口入口为 [2026-05-04_13-11-16-r79-governance-live-readiness.csv](/home/shunli/Projects/hyb-oa/issues/2026-05-04_13-11-16-r79-governance-live-readiness.csv:1)。
|
||||||
|
- **历史蓝图链**:P5 相关只把 [2026-02-09_13-39-02-p5-blueprint-v3.csv](/home/shunli/Projects/hyb-oa/issues/2026-02-09_13-39-02-p5-blueprint-v3.csv:1) 视为权威完成态;[2026-02-09_11-17-07-p5-blueprint.csv](/home/shunli/Projects/hyb-oa/issues/2026-02-09_11-17-07-p5-blueprint.csv:1) 和 [2026-02-09_12-34-42-p5-blueprint-v2.csv](/home/shunli/Projects/hyb-oa/issues/2026-02-09_12-34-42-p5-blueprint-v2.csv:1) 保留为历史快照,不再单独作为当前待办来源。
|
||||||
|
- **试运行链**:本地/外部试运行相关优先串读 `R70 -> R71 -> R73 -> R74 -> R75 -> R76 -> R77 -> R78 -> R79`,不要只看单一 CSV 判断系统状态。
|
||||||
|
- **跨文档事实源**:业务能力现状优先结合 [feature-matrix.md](/home/shunli/Projects/hyb-oa/docs/feature-matrix.md:1)、[coverage-matrix.csv](/home/shunli/Projects/hyb-oa/artifacts/r75/coverage-matrix.csv:1) 和 [manual-trialrun-report.md](/home/shunli/Projects/hyb-oa/artifacts/r70/manual-trialrun-report.md:1) 阅读。
|
||||||
|
|
||||||
|
## 历史合同处理原则
|
||||||
|
- 不批量回改旧 CSV 的 `TODO/DOING/DONE` 来伪造一致性。
|
||||||
|
- 若后续合同替代前一版合同,在新合同或索引文档里补“superseded / authoritative”说明。
|
||||||
|
- 需要做全局状态判断时,以最新合同、覆盖矩阵和试运行报告交叉验证,不以单个旧 CSV 为准。
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户