文件
hyb-oa/.trellis/tasks/archive/2026-08/08-08-production-deployment-validation/prd.md
T

9.7 KiB
原始文件 Blame 文件历史

生产部署验证与迁移门禁

Goal

在不写入真实业务数据的前提下,将包含合同 terminated 三列迁移的当前发布提交安全部署到预期生产环境,并用可追溯、脱敏的证据证明生产迁移状态、运行版本、只读权限边界和回滚窗口边界。

Background and Confirmed Facts

  • 当前既有生产发布入口是 deploy/trialrun/deploy-existing.sh;它会先调用 check-existing-deployment.sh 的 13 项聚合体检,再调用 deploy.sh,默认 SYNC_ENV=0。
  • 当前 deploy.sh 在远端先执行 prisma migrate deploy(4.4),之后才执行 prisma migrate status(4.6)。这只能证明写入后的状态,不能作为本轮要求的部署前迁移门禁。
  • 当前发布提交包含合同迁移 20260807193000_contract_registry_termination_workspace:三个可空列、ON DELETE RESTRICT 外键和索引;本轮不应执行任何真实 terminated 业务写入。
  • 既有部署合同从受控 systemd unit 读取六个 allowlist 参数,13 项聚合体检覆盖部署身份、仓库、环境文件、数据目录、运行实例、挂载、build 和 refresh 身份;不得从 Compose 标签猜路径或选择 SSH 身份。
  • 合同设计规定:生产出现第一条已提交 terminated 记录的瞬间关闭应用回滚窗口;此后不得回退到不识别该状态的旧应用,也不自动 drop 三列,只能 roll-forward。
  • 本任务当前尚未执行生产部署、生产 migration、真实合同写入、企业微信写入或付款/审批操作。

Scope

  • 为既有生产部署入口增加/启用生产目标识别与迁移 preflight,使 migrate status 成为任何 schema 写入前的硬门禁。
  • 在获批窗口内部署包含合同 terminated 三列迁移的明确候选 commit,并完成迁移、运行版本、只读权限和公网 readiness 验证。
  • 记录首条 terminated 记录前后的回滚窗口判据、脱敏证据和失败分流;不主动制造任何真实终止记录。

Requirements

R1 任务来源与部署身份

  • 发布候选必须是干净、已提交且已进入上游的明确 commit;来源校验和 13 项既有部署体检通过后才可继续。
  • 本任务的 deploy-existing.sh 拒绝 DEPLOY_ALLOW_UNPUBLISHED_COMMIT/DEPLOY_UNPUBLISHED_REASON override;离线灾备或远端故障的未发布提交必须走独立、另行批准的恢复流程。
  • 生产目标必须通过独立 target gate:执行时显式提供 EXPECTED_PRODUCTION_ORIGIN 与 EXPECTED_PRODUCTION_DB_NAME(仅进程环境,不写入仓库、日志或报告),与远端 .env 的 APP_ORIGIN、数据库身份逐项比对。
  • target gate 必须确认 NODE_ENV=production、COOKIE_SECURE=true、公网 origin 为 HTTPS 且与预期值一致;拒绝回环地址、本地数据库(含 hyb_oa_regression)、占位符或 staging/trialrun 身份标识。不要把本地任务中“必须是回环地址”的 R2 复用于生产。
  • 目标、账号、路径、数据库名和环境值不得回显;只记录 PASS/FAIL 及脱敏原因。

R2 部署前迁移只读门禁

  • 在任何 migrate deploy、seed、应用切换或真实业务写入之前,针对已确认身份的预期生产数据库执行只读 migration status 检查;原始 stdout/stderr 只留在受控执行现场,任务 artifacts 仅保存脱敏副本供人工核对。
  • 预检必须明确区分 applied、pending、failed、rolled back、diverged;失败/回滚/分叉或无法人工解释的输出立即 PAUSED。
  • 候选迁移目录与生产 _prisma_migrations 的已应用集合必须可对账;pending 集合只能是执行时显式批准的 allowlist(本轮预期最多为合同迁移),出现未知 pending 必须停止。
  • 禁止 prisma migrate dev、migrate reset、db push、migrate resolve、手工 DDL、修改 _prisma_migrations 或以退出码代替原始输出核对。

R3 受控发布

  • 仅使用既有 deploy-existing.sh,保持 SYNC_ENV=0、DEPLOY_DATA_MODE=existing 和既有 PGDATA/附件目录;不得覆盖生产 .env。
  • 预检通过后才允许部署脚本执行已批准的 migrate deploy、构建、服务切换、运行时 smoke 和备份合同 refresh。
  • 本任务不创建、编辑、终止、归档或恢复真实合同,不写报销、付款、审批、银行、ERP 或企业微信数据。

R4 发布后迁移与运行验证

  • 部署后再次保存并人工核对 migrate status 的脱敏证据副本,必须显示所有候选迁移已 applied/数据库 schema up to date;原始 stdout/stderr 仍只留在受控执行现场,不能只看命令退出码。
  • /ready、运行时完整 build SHA、公开短 SHA、基础 smoke、external deps、runtime smoke 和公开 bundle 扫描必须与发布 commit 一致。
  • 所有权限负向路径、详情只读检查和迁移状态复核必须排在任何真实 terminated 写入之前;本任务不执行真实终止写入。缺少专用凭据时记录 PAUSED/SKIP,不伪装成通过。

R5 回滚窗口与结果证据

  • 部署前只读查询 terminated 行数量并记录窗口状态:数量为 0 记为 OPEN,大于 0 记为 CLOSED;窗口按首条已提交记录的产生时刻关闭,不按时间计算。
  • 在窗口 OPEN 时,应用健康失败可按既有发布合同回退到兼容版本,但不 drop 新列;窗口一旦 CLOSED,任何失败只允许 roll-forward 或兼容 hotfix,不回退到旧状态机。
  • 结果记录发布 commit、target gate、pre/post migration 原始证据引用、/ready/smoke、权限负向路径、窗口状态、可解释 SKIP/PAUSED 和是否发生真实写入;不记录凭据、原始环境或业务正文。

Acceptance Criteria

  • AC1:候选 commit 干净、已进入上游,来源校验与 13 项部署体检通过。
  • AC2:生产 target gate 证明目标是预期生产 origin/数据库,明确排除本地、回环和 staging/trialrun 身份,且没有泄露环境值。
  • AC3:任何 schema 写入前完成 pre-migration status;受控现场原始输出与 artifacts 脱敏副本均可核对,failed/rolled-back/diverged 为 0,_prisma_migrations 的 pending 集合与批准 allowlist 完全一致,status 文案中出现的 pending ID 不得超出候选 manifest。
  • AC4:deploy-existing.sh 仅在 AC1–AC3 通过后执行,保持 SYNC_ENV=0/existing 数据合同,未执行 reset、db push、resolve、手工 DDL 或真实业务写入。
  • AC5:部署后 migration status 脱敏证据副本显示全部候选迁移 applied/schema up to date;/ready、build SHA、运行时 smoke、external deps 和公开 bundle 与候选 commit 一致。
  • AC6:权限负向路径和只读合同详情检查在任何真实终止写入前完成;本任务无真实 terminated 写入,缺凭据项明确记录 PAUSED/SKIP。
  • AC7:以首条已提交 terminated 记录定义回滚窗口 OPEN/CLOSED,并记录兼容回滚或 roll-forward 判据;不自动 drop 三列。
  • AC8:任务证据、Trellis/process/docs/sensitive/diff 门禁通过;只有部署、公网和必要真机检查全部获批并通过后,才可告知用户可以测试。

Out of Scope

  • 真实 terminated 写入、合同业务编辑/归档/恢复、报销/付款/审批/银行/ERP/企业微信写入。
  • 生产数据库 reset、db push、resolve、手工 DDL、删除或修改 _prisma_migrations。
  • 修改合同业务代码、权限模型、状态机或生产环境变量;如部署 preflight 需要工具加固,只改部署/QA 脚本与其测试。
  • 以本地或试运行数据库代替预期生产目标;以临时 runner、删除断言或未授权凭据冒充公网通过。

Accepted Risk and Deferred Items

  • 登录态 smoke、企业微信真机和真实 OCR 样本可能因专用凭据/样本缺失而 PAUSED/SKIP;这不等同于生产部署或业务功能通过。
  • 首条 terminated 写入后的旧版本回退风险由产品与合同 task 已接受;本任务只验证窗口判据,不主动关闭窗口。
  • preflight 到 deploy.sh 的受控窗口内,远端 .env、Compose project 和数据库连接目标必须保持不变;并发改动无法由 post-status 追溯性补救。若无法取得该变更冻结,任务应在写入前 PAUSED,不得把 post gate 当作事后纠错。

Operational Inputs (not committed)

  • EXPECTED_PRODUCTION_ORIGIN
  • EXPECTED_PRODUCTION_DB_NAME
  • EXPECTED_PENDING_MIGRATIONS(本轮候选迁移 allowlist)
  • 受控 DEPLOY_SERVER、DEPLOY_REFRESH_SERVER 与 live smoke 凭据(如获批提供)

Open Questions

  • 无;目标识别、迁移门禁顺序、回滚窗口定义和真实写入边界均已确认。

Test Plan

  • 本地静态:node deploy/trialrun/validate-env-contract.js、shell syntax、相关部署安全测试、task validate、process contract、docs registry、Trellis governance、sensitive scan、git diff --check。
  • 部署前:生产 target gate、check-existing-deployment.sh 13 项体检、candidate migration manifest 对账、pre-status 原始输出(仅受控现场)及其脱敏副本和 terminated 计数。
  • 受控发布:DEPLOY_SERVER=<...> DEPLOY_REFRESH_SERVER=<...> bash deploy/trialrun/deploy-existing.sh;仅在前置门禁全 PASS 后执行。
  • 部署后:post-status 原始输出(仅受控现场)及脱敏副本、/ready/build SHA、scripts/qa/run-live-smoke-readiness.sh、external/runtime smoke、公开 bundle 扫描和权限负向路径。
  • 失败分流:target/migration/preflight 失败不触碰远端应用;应用发布后 refresh 失败不重复发布;首条 terminated 出现后只允许 roll-forward。

Evidence Notes

  • 规划阶段未执行生产 SSH、migration、部署、真实数据写入或 live smoke。