修正(08-08-production-deployment-execution): 先验生产公网身份再冻结目录
这个提交包含在:
@@ -29,30 +29,32 @@ operations require explicit approval and evidence.
|
||||
### 2. Signatures
|
||||
|
||||
- Bootstrap entry: `node deploy/trialrun/production-identity-bootstrap.mjs`.
|
||||
- Identity-only stop: `PRODUCTION_IDENTITY_ONLY=1 node deploy/trialrun/production-identity-bootstrap.mjs`.
|
||||
- Read-only stop: `PRODUCTION_READ_ONLY_PREFLIGHT=1 node deploy/trialrun/production-identity-bootstrap.mjs`.
|
||||
- Exact local inputs passed to the existing wrapper: `EXPECTED_DEPLOY_SERVER`, `EXPECTED_REMOTE_DIR`, `EXPECTED_COMPOSE_PROJECT_NAME`, `EXPECTED_PRODUCTION_ORIGIN` and `EXPECTED_PRODUCTION_DB_NAME_SHA256`.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- Recover deployment target, repository root and Compose project from reviewed Git history; when values come from different commits, require their shared identity fields to agree.
|
||||
- Recover deployment target and Compose project from reviewed Git history. A shell `${REMOTE_DIR:-...}` default that operations routinely override is a fallback, not proof of the production repository root.
|
||||
- Select the refresh identity only when exactly one concrete SSH candidate returns the exact forced-command probe token. Do not print candidate aliases.
|
||||
- Compare target, directory and project independently. Missing or empty expected values are errors, not reasons to skip a comparison.
|
||||
- Compare target and project against their independent history. Use a structurally validated systemd contract only to locate the remote env/runtime, verify both origin samples, then freeze its directory as the exact expected value for later preflight. Missing or empty expected values are errors, not reasons to skip a comparison.
|
||||
- A legacy token such as `trialrun` is neutral. Continue to reject loopback/zero addresses, local regression, staging, shadow and placeholder identities.
|
||||
- Read `POSTGRES_DB` only after history, systemd contract and public origin agree. Keep the database name remote; pass only a hash comparison baseline to the preflight.
|
||||
- Identity-only mode must stop after env/runtime origin agreement and contract-directory freeze; it must not read `POSTGRES_DB`, run aggregate checks or enter Prisma status.
|
||||
- Read `POSTGRES_DB` only after history target/project, systemd contract structure and both public-origin samples agree. Keep the database name remote; pass only a hash comparison baseline to the preflight.
|
||||
- Read-only mode must exit after target/pre-status and rollback-window checks and before `deploy.sh`, rsync, migration or application switching.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- Zero refresh probe matches -> `REFRESH_IDENTITY_NOT_FOUND`; stop before target gate.
|
||||
- Multiple exact probe matches -> `REFRESH_IDENTITY_NOT_UNIQUE`; do not select the first candidate.
|
||||
- Historical target/directory/project disagreement -> an explicit `HISTORICAL_*` or `SYSTEMD_*_MISMATCH`; stop before database identity read.
|
||||
- Historical target/project or contract-relative-path disagreement -> an explicit `HISTORICAL_*` or `SYSTEMD_*_MISMATCH`; stop before database identity read.
|
||||
- Any expected exact value missing/empty -> `EXPECTED_*_MISSING`; no SSH preflight fallback.
|
||||
- Env origin or running-container origin differs from the approved origin -> `PROD_TARGET_*_ORIGIN_MISMATCH`; do not read migration status.
|
||||
- Read-only mode reaches `deploy.sh` -> contract failure; tests and env validation must reject the ordering.
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
- Good: a legacy-named deployment passes because all independent identity values match exactly, then read-only mode records status/window and exits before writes.
|
||||
- Good: a legacy-named deployment passes target/project checks, both origin samples match, the contract directory becomes the exact in-process baseline, then identity-only mode exits before DB/status reads.
|
||||
- Base: an explicitly supplied, unambiguous production identity passes the same exact comparisons.
|
||||
- Bad: reject or accept solely because the alias/project contains or omits `trialrun`.
|
||||
- Bad: database name lookup fails and the wrapper continues without comparing database identity.
|
||||
@@ -60,10 +62,10 @@ operations require explicit approval and evidence.
|
||||
### 6. Tests Required
|
||||
|
||||
- Positive fixture for the approved legacy naming pattern.
|
||||
- Separate negative assertions and stable error codes for deploy target, remote directory and Compose project mismatches.
|
||||
- Separate negative assertions and stable error codes for deploy target, Compose project, contract-relative env path and later preflight directory mismatches.
|
||||
- Missing-value tests proving exact comparison cannot be skipped.
|
||||
- Zero/multiple refresh-probe fixtures.
|
||||
- Ordering assertion: identity/DB bootstrap -> target/pre-status/window -> read-only exit -> `deploy.sh` only when read-only mode is off.
|
||||
- Ordering assertion: contract structure -> env/runtime origin -> contract-directory freeze -> identity-only exit; only a later approved run may read DB -> target/pre-status/window -> read-only exit -> `deploy.sh` when read-only mode is off.
|
||||
- Evidence assertions proving target/path/database values are absent from stdout and committed reports.
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
@@ -77,8 +79,9 @@ name does not contain staging -> assume production -> run migrate deploy
|
||||
#### Correct
|
||||
|
||||
```text
|
||||
reviewed history + unique refresh probe + exact systemd contract + exact origin
|
||||
-> remote-only DB identity hash -> target/pre-status/window
|
||||
reviewed target/project + unique refresh probe + contract structure
|
||||
-> env/runtime origin agreement -> freeze contract directory -> identity-only stop
|
||||
-> separately approved remote-only DB identity hash -> target/pre-status/window
|
||||
-> explicit read-only stop or separately approved deploy
|
||||
```
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户