fix: 隔离既有发布的数据库容器生命周期(09-05-existing-deploy-db-lifecycle-isolation)
这个提交包含在:
@@ -19,6 +19,96 @@ operations require explicit approval and evidence.
|
||||
- Do not execute real payments, import bank statements, connect payment
|
||||
providers or write ERP without a separate approved Trellis task.
|
||||
|
||||
## Scenario: Existing Application Release Must Not Manage Database Containers
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
- Applies to `deploy-existing.sh` → `deploy.sh` and direct `deploy.sh` execution.
|
||||
- Separate application publication from database container lifecycle management;
|
||||
this does not make migrations or seed operations read-only.
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
- `DEPLOY_DATA_MODE=existing|initialize`; the existing wrapper pins `existing`.
|
||||
- Only `initialize` may explicitly run Compose `up -d db`.
|
||||
- One-shot init: `run --rm --no-deps -T --entrypoint sh init ...`.
|
||||
- Application: explicit `build server`, then `up -d --no-build --no-deps server`;
|
||||
optional worker and explicitly selected MinIO services also isolate dependencies.
|
||||
- Database readiness: `timeout --signal=KILL 120 bash -s -- <compose arguments>`;
|
||||
poll every 2 seconds with no environment override for the 120-second deadline.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- Existing releases may query database state but must not start, stop, restart,
|
||||
recreate, replace or remove db, explicitly or via dependency propagation.
|
||||
A project-wide lifecycle operation is not safe merely because it omits `db`.
|
||||
- Resolve exactly one container through the approved Compose project/service.
|
||||
Inspect its running state and Docker health, replacing the `service_healthy`
|
||||
startup guarantee otherwise lost when dependency startup is disabled.
|
||||
- The deadline encloses both polling and potentially stuck Compose/inspect calls.
|
||||
Missing, stopped, unhealthy, ambiguous or uninspectable db must fail; only
|
||||
`running|starting` waits, and only `running|healthy` proceeds. No automatic
|
||||
initialize fallback, restart, permission repair or health-bypass option.
|
||||
- Initialize starts db explicitly, then passes the same health gate before init.
|
||||
Reuse the gate after init build, after init and after server build, before each
|
||||
application switch; a healthy snapshot before a long build is not sufficient.
|
||||
Prepare worker before switching server: resolve its existing container through
|
||||
Compose, inspect Config.Image and verify that image reference, not just a retained
|
||||
image ID whose tag may be gone. Build explicitly when no container/reference is
|
||||
available, then check health and start with `--no-build --no-deps`. A cached image
|
||||
without a container may incur an extra cached build. This assumes the current
|
||||
build-only worker definition; future image overrides need their own compatibility
|
||||
review, rather than treating a previous container reference as new configuration.
|
||||
Preserve migration/seed command content and order, safe logs, identity/path
|
||||
preflights, rollback window, build markers and backup-contract refresh.
|
||||
- Missing timeout tooling or unsupported isolation options fail closed. Do not
|
||||
retry a command without isolation to accommodate an older Compose executable.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- Missing/invalid mode → nonzero before container operations.
|
||||
- Missing timeout tool → `db_health_timeout_unavailable`, no db start or init.
|
||||
- Missing/non-unique db → `db_container_missing_or_ambiguous`.
|
||||
- Query failure → `db_health_query_failed`; invalid/unhealthy state → `db_not_healthy`.
|
||||
- Deadline → `db_health_timeout`, nonzero; never continue init/application switch.
|
||||
- Init failure → preserve failure status and stop before application switch.
|
||||
|
||||
### 5. Good / Base / Bad Cases
|
||||
|
||||
- Good: existing healthy db → isolated init → isolated application switch;
|
||||
captured effective lifecycle targets never include db.
|
||||
- Base: initialize → explicit db start → bounded healthy check → isolated init.
|
||||
- Bad: remove only the explicit `up db` but leave init `run` or application `up`
|
||||
free to start dependencies; grep for one `--no-deps` cannot prove safety.
|
||||
|
||||
### 6. Tests Required
|
||||
|
||||
- Execute the actual remote shell from current source in a private temporary
|
||||
fixture; capture argv and resolve effective service targets from the real
|
||||
Compose dependency graph. Assert execution reaches init and expected services.
|
||||
- Cover V1/V2, both modes, worker/MinIO profiles and failure cases; mutate explicit
|
||||
db startup and each init/server/worker dependency isolation independently.
|
||||
- Change db health after build/init/server-switch stages and prove the next
|
||||
guarded action never runs; verify image builds cannot follow the last health
|
||||
check implicitly inside application `up`.
|
||||
- Cover a retained worker container/image ID with a missing launch tag; rebuild
|
||||
must happen before the server switch, not fail later at isolated worker startup.
|
||||
- Test the real deadline mechanism with a shortened deadline only in a temporary
|
||||
source copy, including a hung inspect; never shorten the production constant.
|
||||
- Fake binaries and whitelisted PATH/env exist only in test subprocesses. Unknown
|
||||
commands fail, real Docker/SSH/production credentials remain inaccessible.
|
||||
- Run `server/tests/unit/scripts/deployment-db-lifecycle.test.js` in static gates
|
||||
and retain existing `deployment-safety-contract.test.js` coverage.
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
|
||||
- Wrong: database unavailable → application deploy silently runs `up db`.
|
||||
- Correct: database unavailable → stop and request separate fault recovery.
|
||||
- First authorized real release needs an operator, pre/post db container identity
|
||||
comparison and separate application-image/tool recovery references. Keep the
|
||||
old tool source as evidence, not a ready-to-run command sequence that reintroduces
|
||||
unapproved db lifecycle operations or replays migrations/seeds.
|
||||
|
||||
## Scenario: Exact Production Identity Bootstrap Before Migration Status
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
在新工单中引用
屏蔽一个用户