9.7 KiB
9.7 KiB
生产部署验证与迁移门禁
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_REASONoverride;离线灾备或远端故障的未发布提交必须走独立、另行批准的恢复流程。 - 生产目标必须通过独立 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_ORIGINEXPECTED_PRODUCTION_DB_NAMEEXPECTED_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.sh13 项体检、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。