13 KiB
13 KiB
生产部署执行与验收
Goal
在已完成生产目标与迁移门禁实现的基础上,于明确批准的生产窗口内执行一次可审计的既有部署,验证合同 terminated 三列迁移已经安全落地,并完成部署后只读 readiness 检查。任何门禁失败都必须停止,不得以退出码、部分输出或后续部署结果替代人工核对。
本任务不主动制造真实 terminated 记录,也不执行其他业务写入;它只在生产侧执行获批的迁移/发布动作,并保留足以产出审查的脱敏证据。
Background and Confirmed Facts
- 生产部署入口是
deploy/trialrun/deploy-existing.sh。它读取受控 systemd deployment contract,固定SYNC_ENV=0、DEPLOY_DATA_MODE=existing,并在deploy.sh前调用生产 target/pre-migration gate,部署后再做 post-status gate。 - 当前没有独立预发环境:历史命名为
hyb-oa-trialrun的既有部署就是承载公网 OA 的唯一运行环境。trialrun是遗留命名,不代表另一套非生产实例;这次 schema 迁移无法先在同构预发环境演练。 - Git 历史中的
REMOTE_DIR="${REMOTE_DIR:-...}"是未证明曾生效的 fallback,不是生产目录事实源。只有历史 SSH target 与 Compose project 继续作为独立基线;REMOTE_DIR必须在远端.env和运行容器 origin 双取样一致后,从该生产主机的受控 systemd contract 冻结为当前进程精确基线。 - 生产 target gate 必须确认 HTTPS 公网 origin、
NODE_ENV=production、COOKIE_SECURE=true、数据库身份和既有部署合同。不得再以名称中含trialrun作为拒绝依据;改为精确匹配已确认的部署身份组,并继续拒绝回环、本地回归库、staging、shadow、测试占位符等真实非生产目标。 - pre-status 的原始 stdout/stderr 只能留在受控执行现场;任务目录和报告只保存脱敏副本、稳定状态码、迁移 ID、计数和证据引用。
- 候选发布必须是干净、已提交并已进入上游的 commit。规划阶段曾发现
origin/main落后并已通过受控提交解决;严格 wrapper 仍拒绝未发布提交 override,任何规划修订都必须重新提交、推送并复核 provenance。 - 当前候选迁移为
20260807193000_contract_registry_termination_workspace。部署前须从候选 commit 生成 manifest,并以生产_prisma_migrations与prisma migrate status原始输出共同核对 pending、failed、rolled-back、unfinished 和 diverged 状态。 contract_registry.status = 'terminated'的第一条已提交记录会关闭回滚窗口。窗口按事件定义,不按发布时间或时间窗口定义;本任务不执行终止写入。- 既有生产部署、真实合同写入、企业微信、付款、审批和其他业务数据操作均需受控;本任务明确只授权本节列出的发布迁移和只读验证。
Scope
- 在候选发布进入上游且工作区干净后,先从已审查的历史 Git 事实和受控远端合同完成只读身份引导,再执行生产 target gate、既有 13 项部署体检、pre-migration status 与
terminated行数查询。 - 在所有 pre-gate 通过且变更冻结成立后,使用唯一获批入口执行既有部署;允许的 schema 写入仅为候选 commit 已声明的 Prisma migration。
- 部署后执行 post-migration status、
/ready、候选 build SHA、基础/external/runtime smoke、公开 bundle 扫描和权限负向/详情只读检查,并生成脱敏证据包。 - 按失败阶段记录
PAUSED、FAIL或DEPLOYED_BUT_CONTRACT_REFRESH_FAILED,完成只读 review、收口和归档。
Requirements
R1 发布来源与生产目标
- 候选 commit 必须干净、已提交、已进入配置的上游远端;严格 wrapper 不接受
DEPLOY_ALLOW_UNPUBLISHED_COMMIT或DEPLOY_UNPUBLISHED_REASON。 - 公网 origin 从当前 OPS7 运维交接 Runbook 的现行公网检查基准取得;部署 SSH 目标从已审查历史提交
34181e3恢复,Compose project 从首次显式冻结该值的历史提交5e2d03893826恢复。历史REMOTE_DIRfallback 不参与生产身份判断。 DEPLOY_REFRESH_SERVER通过本机受控 SSH 配置的 exact forced-commandprobe唯一识别;零个或多个候选均立即停止,不按别名、顺序或连接速度猜测。- 使用 structurally valid 的 systemd contract 定位远端
.env和运行容器,只读比较两个APP_ORIGIN取样;两者均与 OPS7 基准一致后,才确认该主机承载生产 origin,并把 contract 的REMOTE_DIR冻结为当前进程预期值。origin 不一致立即停止,不得采信 contract 目录。 - 生产数据库名只允许在部署目标、Compose project、受控 systemd contract 和公网 origin 已确认后,通过一次获批的远端
.env只读读取取得;值仅保留在远端并转换为 target gate 所需的比较输入,不回显、不落盘。 - target gate 必须精确验证
DEPLOY_SERVER、origin 验证后冻结的REMOTE_DIR、COMPOSE_PROJECT_NAME、公网 origin 与读取后的POSTGRES_DB身份组,并继续核对运行时DATABASE_URLhost/database、当前数据库、NODE_ENV和 cookie 安全配置;任一身份不确定均 fail-closed。 EXPECTED_PENDING_MIGRATIONS可先以空集合运行只读 pre-status 发现实际 pending;只要实际集合非空或不等于批准 allowlist,就必须停止并逐条复核 SQL,不能自动进入部署。
R2 pre-status 与回滚窗口先行
- 在任何
migrate deploy、seed、应用切换或业务写入前,人工阅读 target gate 和prisma migrate status原始输出,并核对脱敏副本。 - pending 集合必须与批准 allowlist 精确一致;未知 migration、failed/rolled-back/unfinished/diverged、不可解释 status 或数据库目标漂移均立即停止。
- 同一只读阶段查询
terminated行数:0 记rollbackWindow=OPEN,大于 0 记CLOSED。必须在权限负向路径与任何未来真实终止写入前完成。
R3 受控发布
- 只使用
DEPLOY_SERVER=<受控目标> DEPLOY_REFRESH_SERVER=<受控刷新目标> bash deploy/trialrun/deploy-existing.sh。 - 保持
SYNC_ENV=0、DEPLOY_DATA_MODE=existing,不得覆盖生产.env,不得选择其他部署脚本或 SSH 身份。 - 只有 R1/R2 全部 PASS 且能证明 preflight 到 deploy 期间目标与配置冻结,才允许进入 schema/app 写入阶段。
R4 发布后只读验收
- post-status 必须显示候选迁移全部 applied / schema up to date;不能只看命令退出码。
/ready、完整 build SHA、公开短 SHA、基础 smoke、external/runtime smoke、公开 bundle 扫描和权限负向路径必须与候选 commit 一致。- 登录态、企业微信真机、真实 OCR 或其他缺少专用凭据/样本的检查只能记
PAUSED/SKIP,不得伪装成 PASS。
R5 失败与回滚边界
- target/preflight/status 失败:不部署、不写库,保留现场并返回
PAUSED。 - migrate deploy/init 中途失败:保留现场,禁止 reset、resolve、drop、手工 DDL 或重复部署,等待明确决策。
OPEN窗口下应用健康失败可按既有合同回退兼容应用但不 drop 三列;CLOSED窗口下只允许 roll-forward 或兼容 hotfix。- refresh 失败标记
DEPLOYED_BUT_CONTRACT_REFRESH_FAILED,不重复发布应用。
Acceptance Criteria
- AC1:候选 commit 已提交、工作区 clean、已进入上游;来源校验和既有 13 项体检均 PASS。若候选未发布,任务在此处 PAUSED,不使用 override。
- AC2:只读身份引导证明历史部署目标、Compose project、受控 systemd contract 与公网 origin 属于同一唯一运行环境;远端
.env与运行容器 origin 双取样均匹配后,contractREMOTE_DIR已冻结为进程内精确基线,数据库名只在该前提下读取。target gate 的原始输出在受控现场可供人工阅读,脱敏副本只证明 PASS/FAIL 和原因,未泄露任何身份值。 - AC3:任何 schema 写入前完成 pre-status;原始 status 输出与脱敏副本可对账,异常集合为空,pending 与 allowlist 精确一致,
terminated行数和rollbackWindow=OPEN|CLOSED判定已记录。 - AC4:仅在 AC1–AC3 全部 PASS 后调用
deploy-existing.sh;未执行 reset、db push、resolve、手工 DDL、seed 之外的业务写入或真实terminated写入。 - AC5:部署后 status 显示全部候选迁移 applied/schema up to date,
/ready、build SHA、smoke、external/runtime smoke、bundle scan 结果与候选 commit 一致。 - AC6:权限负向路径和合同详情只读检查排在任何真实终止写入之前;缺少凭据项明确标记
PAUSED/SKIP。 - AC7:结果证据包含候选 commit、target gate、pre/post status 引用、窗口状态、各检查真实数字/输出摘要、失败分流和业务写入计数;不含凭据、原始环境或合同正文。
- AC8:Trellis task validate、process contract、docs audit、governance、sensitive scan 和 diff check 通过;生产、公网或真机未全通过时,最终答复不得告知“可以测试”。
Out of Scope
- 不执行真实
terminated写入、合同编辑/归档/恢复、报销/付款/审批/银行/ERP/企业微信写入。 - 不执行
prisma migrate dev、migrate reset、db push、migrate resolve、手工 DDL、删除/修改_prisma_migrations或自动 drop 新列。 - 不修改合同业务代码、权限模型、状态机、生产
.env或应用配置;如发现缺陷,登记后另建 task。 - 不以本地、staging、shadow、回归库或临时 runner 代替预期生产目标;不得仅凭环境名称包含或不包含
trialrun判定身份,必须使用精确身份组。 - 不把从历史 Git 或远端
.env读取到的身份值写回仓库、任务文档、普通日志或对话。
Accepted Risk and Deferred Items
- 首条已提交
terminated记录出现后,旧应用回退窗口永久关闭;本任务只读取并记录窗口状态,不主动关闭它。 - 当前没有同构预发环境;13 项体检、target/pre-status、回滚窗口和
/ready是唯一运行环境上的主要安全网。窗口 OPEN 时的兼容回退是本轮唯一一次可用的旧版本回退机会。 - 生产公网 smoke、企业微信真机、登录态或真实 OCR 可能因专用凭据/样本缺失而
PAUSED/SKIP,不等同于部署通过。 - preflight 与 deploy 之间无法建立配置/数据库变更冻结时,必须在写入前暂停;post-status 不能事后补救错误目标写入风险。
- 任何非迁移产品失败不得在本任务内顺手修复,应登记为独立后续任务。
Operational Inputs (not committed)
EXPECTED_PRODUCTION_ORIGIN(从现行 OPS7 公网基准在进程内取得)PRODUCTION_IDENTITY_ONLY=1(只完成 origin 双取样与 contract 目录基线冻结,随后在数据库读取和 pre-status 前退出)EXPECTED_PRODUCTION_DB_NAME_SHA256(仅在精确身份引导通过后,于远端从.env读取数据库名并转换为不含明文的比较基线;数据库名明文本身不离开远端,也不进入日志或证据文件)EXPECTED_PENDING_MIGRATIONS- 受控
DEPLOY_SERVER(从已审查历史入口恢复)、DEPLOY_REFRESH_SERVER(exact probe 唯一识别)、systemd contract 与 live smoke 凭据(如获批提供)
Open Questions
- 无。唯一公网环境拓扑、精确身份匹配和数据库名只读引导方式均已由用户确认;修订规划仍需复核批准后才实施 tooling 改动或连接生产。
Test Plan
规划/本地
node deploy/trialrun/validate-env-contract.js- 新增执行 task 后运行
python3 ./.trellis/scripts/task.py validate 08-08-production-deployment-execution node scripts/qa/check-process-contract.mjs --baseline --jsonnode scripts/qa/audit-docs.mjs --check-registrynode scripts/qa/check-trellis-governance.mjs --jsonnode scripts/qa/check-sensitive-content.mjsgit diff --check
生产执行窗口
- 先验证历史身份恢复与 exact refresh probe;只读核对远端 systemd contract 和公网 origin,再在不回显值的同一进程中读取数据库名。
- 保存 target gate、13 项体检、candidate provenance、pre-status 原始输出(受控现场)及脱敏副本。
- 核对 migration manifest、
_prisma_migrations、pending allowlist、异常集合和terminated行数;任一失败即停止。 - 仅在前置证据全部 PASS 后运行
deploy-existing.sh。 - 部署后保存 post-status 原始输出及脱敏副本,运行
/ready、build/SHA、基础/external/runtime smoke、bundle scan 和权限负向检查。 - 失败按阶段分流;不重复部署、不 reset、不 resolve、不 drop。
Evidence Rules
- 原始 target/status stdout/stderr 只留在受控执行现场;任务 artifacts 只保存脱敏副本、短 ID、计数、状态码和引用。
- 不记录生产 origin、数据库名、SSH target、用户名、路径、连接串、凭据、业务正文或原始 payload。
- 报告目录重用时仅清理已知 evidence 文件,不能保留旧 PASS。