建立生产密钥恢复合同(08-01-production-secret-recovery-env-externalization)
这个提交包含在:
@@ -1342,3 +1342,65 @@ REMOTE_DIR="$(docker inspect <server> --format '<working_dir-label>')" \
|
||||
DEPLOY_SERVER=<approved-ssh-target> \
|
||||
bash deploy/trialrun/deploy-existing.sh
|
||||
```
|
||||
|
||||
## Scenario: Environment Recovery Classification And Secret Custody
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
- Trigger: adding/removing a trialrun environment key, documenting host-loss recovery, or preparing an environment-file migration.
|
||||
- Purpose: make environment loss recoverable without placing Secret values in Git, ordinary backup, logs or AI context.
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
- Template contract: `deploy/trialrun/.env.example`.
|
||||
- Recovery classification: `deploy/trialrun/env-recovery-classification.json`.
|
||||
- Recovery card: the opening section of `deploy/trialrun/runbook.md`.
|
||||
- Validator: `node deploy/trialrun/validate-env-contract.js`.
|
||||
- Fixed categories: `template_rebuild`, `external_reissue`, `direct_rotate`, `downtime_reset`, `preserve_original`.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- Every `.env.example` key appears in exactly one fixed recovery category; the classification file contains key names only, never values, defaults, hashes, accounts or platform addresses.
|
||||
- `template_rebuild` comes from reviewed templates/runbooks; `external_reissue` comes from the owning platform; `direct_rotate` records the invalidation consequence; `downtime_reset` requires an isolated approved outage.
|
||||
- `POSTGRES_PASSWORD` is a reset case. PostgreSQL stores a verifier in `pg_authid`, not recoverable plaintext. Any temporary authentication relaxation is local-socket only, never a trusted host rule, and the original authentication file must be restored byte-for-byte before reopening the application.
|
||||
- `FIELD_ENCRYPTION_KEY` is `preserve_original` and the highest-risk class. Its current AES-256-GCM payload is `v1:<iv>:<tag>:<ciphertext>` without a key id; replacing a lost key does not recover existing bank, identity or notification-channel ciphertext.
|
||||
- `preserve_original` custody must be available to both the system administrator and a company responsible person through a repository-external shared vault or encrypted sealed copy. Evidence records roles and status only.
|
||||
- Original-key custody is a current recovery constraint, not a permanent rotation design. Key id, keyring, lazy/bulk re-encryption and old-key retirement require a separate approved security task.
|
||||
- Database/attachment backups do not absorb plaintext environment files. Phase 1 recovery-contract work never reads production env or contacts production systems.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- New `.env.example` key missing from classification -> validator fails.
|
||||
- Key appears in two categories -> validator fails and names the duplicated key.
|
||||
- Unknown category, extra key, illegal key name or value-like entry -> validator fails.
|
||||
- `FIELD_ENCRYPTION_KEY` outside `preserve_original` -> validator fails.
|
||||
- `POSTGRES_PASSWORD` outside `downtime_reset` -> validator fails.
|
||||
- Original encryption key unavailable -> stop recovery and report ciphertext impact; never generate a replacement and claim success.
|
||||
- Temporary database trust remains or a DB host port is published -> recovery fails and the external entry remains closed.
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
- Good: a TTL is rebuilt from the template, a WeCom Secret is reissued by its platform owner, JWT is rotated with session invalidation, and the field-encryption key is restored from dual-access custody.
|
||||
- Base: the production key set differs from the example contract; a separately approved read-only check explains key names/counts without reading values before migration.
|
||||
- Bad: put `.env` into the paired data backup, print a secret hash as evidence, assume `pg_authid` reveals the old password, or replace `FIELD_ENCRYPTION_KEY` with a new random value.
|
||||
|
||||
### 6. Tests Required
|
||||
|
||||
- `node deploy/trialrun/validate-env-contract.js`.
|
||||
- Focused unit tests must cover the complete contract plus missing, duplicate, extra, unknown-category, illegal/value-like, field-key and database-password misclassification cases.
|
||||
- Run `node scripts/qa/check-sensitive-content.mjs`, Trellis governance, process contract, docs registry audit and `git diff --check` after classification/runbook changes.
|
||||
- Production key-name comparison, shared-vault custody, env migration, systemd updates, restarts and old-copy deletion remain separately approved Phase 2 evidence.
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
|
||||
#### Wrong
|
||||
|
||||
```json
|
||||
{"direct_rotate":["FIELD_ENCRYPTION_KEY"]}
|
||||
```
|
||||
|
||||
#### Correct
|
||||
|
||||
```json
|
||||
{"preserve_original":["FIELD_ENCRYPTION_KEY"]}
|
||||
```
|
||||
|
||||
在新工单中引用
屏蔽一个用户