记录付款发布与部署恢复合同(08-01-reimbursement-notification-progress-clarity)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-08-02 10:56:56 +08:00
父节点 5d274af8d4
当前提交 ea985de975
共修改 2 个文件,包含 24 行新增和 1 行删除
@@ -1302,6 +1302,9 @@ bash scripts/qa/run-automatic-backup-contract.sh
- Never derive `REMOTE_DIR` from Compose `com.docker.compose.project.working_dir`; it may name the Compose-file directory rather than the repository root.
- The existing-deployment wrapper reads only `REMOTE_DIR`, `REMOTE_ENV_FILE`, `COMPOSE_FILE`, `COMPOSE_PROJECT_NAME`, `POSTGRES_DATA_DIR` and `STORAGE_HOST_DIR`; it does not echo their values.
- Before `mkdir` or rsync, existing mode requires repository markers, `PG_VERSION`, storage directory and a regular non-symlink env file when `SYNC_ENV=0`.
- If the frozen unit points to a missing or non-repository root, recover the canonical source tree from an exact published Git commit into a new dedicated root. Do not choose among stale source directories by timestamp, and do not use `--delete` or carry an environment file into the new root during this bootstrap.
- When the frozen `REMOTE_ENV_FILE` is missing, locate candidates from the running Compose configuration and compare each candidate's service/database values with the running containers by per-key digest. Output only key names and PASS/FAIL; never print values or digests. A candidate must pass every container-observable key, including the field-encryption and database identity keys, before root copies it (not moves it) to the canonical root with deployment-user ownership and mode `0600`. If no candidate fully passes, stop and use the environment recovery classification; never use `SYNC_ENV=1` to guess.
- After a successful application switch, re-run the automatic-backup and WARCH3 installers with the newly active full `BUILD_SHA` and matching 12-character frontend prefix. Validate all managed service working directories/env paths/build identities and enabled timers, then run one complete backup plus the freshness watchdog; application `/ready` alone does not prove the backup contract followed the release.
- `apk add` and both lockfile `npm ci` steps precede `BUILD_SHA` / `VITE_BUILD_SHA`. Build identity may invalidate application output, never stable dependency installation.
- Seed and smoke output reports readiness, counts and booleans; it does not print full login identifiers, contact values, WeCom identifiers, redirect URI or generated credentials.
@@ -1309,15 +1312,20 @@ bash scripts/qa/run-automatic-backup-contract.sh
- Config directory passed as `REMOTE_DIR` -> preflight fails before rsync.
- Remote env missing or symlinked with `SYNC_ENV=0` -> preflight fails before rsync.
- Multiple environment candidates or any per-key mismatch -> stop before copying, syncing or rebuilding containers; do not select the newest-looking file.
- Environment copy digest, owner or mode mismatch -> stop before formal deploy and keep the original candidate unchanged.
- Existing PGDATA missing `PG_VERSION` or storage missing -> preflight fails before rsync.
- Canonical systemd unit missing an allowlisted value -> wrapper fails without calling `deploy.sh`.
- Post-deploy installer still embeds the previous build SHA, any managed timer is inactive, or the real backup/watchdog fails runtime identity or off-host freshness -> deployment recovery remains incomplete even when `/ready` is green.
- Lockfile unchanged but a new SHA reruns dependency installation -> Dockerfile contract test fails.
### 5. Good/Base/Bad Cases
- Good: wrapper reads the frozen unit contract, preflight passes, Git archive syncs and unchanged dependency layers are cached.
- Good: a broken-root recovery creates a clean published-commit source tree, proves one environment candidate against running containers without exposing values, copies it with mode `0600`, deploys with `SYNC_ENV=0`, then updates the backup contracts and completes a real off-host backup.
- Base: first initialization uses reviewed explicit parameters and `DEPLOY_DATA_MODE=initialize`; it does not pretend an existing unit is available.
- Bad: inspect a running container's `working_dir`, append another `deploy/trialrun`, then discover the mistake only after rsync.
- Bad: choose one of several stale `.env` files by path or modification time, use `SYNC_ENV=1`, or stop after `/ready` while the backup unit still expects the previous build.
### 6. Tests Required
@@ -1325,6 +1333,7 @@ bash scripts/qa/run-automatic-backup-contract.sh
- `node deploy/trialrun/validate-env-contract.js`.
- `cd server && npm test -- tests/unit/scripts/deployment-safety-contract.test.js`.
- Synthetic fixtures must prove wrong root, missing/symlink env and invalid data fail; static ordering must prove preflight precedes rsync and dependency stages precede build args.
- A controlled recovery must additionally record: exact published source commit, per-key PASS set/date without values, byte-copy/owner/mode PASS, new-SHA service/timer contract PASS, a successful complete backup, and a successful off-host freshness check. Old candidates remain untouched until a separately approved cleanup.
### 7. Wrong vs Correct
@@ -1341,6 +1350,11 @@ REMOTE_DIR="$(docker inspect <server> --format '<working_dir-label>')" \
```bash
DEPLOY_SERVER=<approved-ssh-target> \
bash deploy/trialrun/deploy-existing.sh
# If contract recovery was required, update the backup units with the active
# full SHA after the switch, then prove both creation and freshness.
systemctl start hyb-oa-automatic-backup-daily.service
systemctl start hyb-oa-automatic-backup-watchdog.service
```
## Scenario: Environment Recovery Classification And Secret Custody