修复(08-23-isolated-backup-restore-drill): 闭环Attempt 5安装器路径缺陷

这个提交包含在:
2026-08-25 22:50:24 +08:00
父节点 7bfaa92bf1
当前提交 f84e6cf4e3
共修改 3 个文件,包含 98 行新增和 3 行删除
@@ -1344,6 +1344,10 @@ validate_copied_batch(private/batch, source_metadata)
- Candidate render:
`bash scripts/qa/run-offhost-shadow-restore-runner-contract.sh render <private-config.json> <new-output>`;
it prints only PASS and the candidate SHA-256, never config values or paths.
- One-shot installer manifest: the candidate `LIB_DIR`, runner entry, dependency
basenames and sudoers entry form one exact private mapping. The installer must
validate that mapping before its first privileged write; a sibling `lib` /
`libexec` path reconstructed independently is not equivalent.
### 3. Contracts
@@ -1410,6 +1414,17 @@ validate_copied_batch(private/batch, source_metadata)
`server/prisma/migrations` at the source commit, validates every directory
name, sorts the names and hashes that exact non-empty set. Files such as
`migration_lock.toml` are not migrations and must never enter the fingerprint.
- A one-shot installer must install every helper into the exact `LIB_DIR`
embedded in the already approved rendered runner, or derive both values from
the same validated private render input and compare them before `sudo
install`. It must use the same exact destinations for preflight, installation,
residue accounting and cleanup; a path that differs only by `lib` versus
`libexec` is an entry-contract failure, not an ARM environment exception.
- A root/sudo helper must not use `$HOME` to locate a caller-owned upload,
installer or diagnostic script: sudo normally changes it to the root home.
Self-cleanup may use `$0` only after validating the fixed basename, regular
file type and absence of a symlink; otherwise a non-root outer wrapper owns
cleanup of the exact caller-side path.
### 4. Validation & Error Matrix
@@ -1447,6 +1462,12 @@ validate_copied_batch(private/batch, source_metadata)
hashing; never reinterpret the extra file as schema drift.
- Candidate differs from the deterministic render or has not passed the tracked
contract -> do not upload or install it.
- Installer dependency destination differs from the rendered runner `LIB_DIR`
-> fail before the first privileged file write; do not install into the
similar sibling directory and rely on runner cleanup to discover it later.
- A sudo helper resolves caller staging through root `$HOME`, or cannot prove
the fixed identity of `$0` -> leave caller-side cleanup to the non-root outer
wrapper and report it explicitly; do not guess or unlink a different home.
### 5. Good/Base/Bad Cases
@@ -1471,6 +1492,12 @@ validate_copied_batch(private/batch, source_metadata)
- Bad: add two successful queries only to the fixture while the rendered runner
still accepts the first socket `pg_isready`, or use a fixed sleep as an ARM
timing workaround.
- Good: the installer mechanically compares its dependency destination with the
rendered runner `LIB_DIR`, installs all three pinned helpers there and checks
that same exact directory during residue accounting.
- Bad: type a site path twice, install helpers below `lib` while the candidate
reads `libexec`, or use sudo `$HOME` to delete a script uploaded by the
calling user.
### 6. Tests Required
@@ -1514,6 +1541,14 @@ validate_copied_batch(private/batch, source_metadata)
- Directly test source/copy identity, dynamic migration fingerprint and the
tracked attachment validator. Run `check-sensitive-content.mjs` explicitly on
all three tracked runner assets and require zero findings.
- Build an installer fixture from a rendered candidate and assert runner entry,
exact `LIB_DIR`, dependency basenames and sudoers destination are one mapping.
Mutate only `libexec` to `lib` and require failure before any simulated
privileged install; verify residue accounting uses the same destinations.
- Exercise a diagnostic helper with sudo/root `HOME`: `$0` plus fixed-basename,
regular-file and non-symlink checks may self-clean, while an unverified path
must remain owned by a non-root outer cleanup. Assert no root-home path is
inferred or emitted.
### 7. Wrong vs Correct
@@ -1532,10 +1567,12 @@ print result=NO_GO
```text
tracked template + exact private config -> deterministic candidate + SHA-256
candidate LIB_DIR == installer dependency destination -> privileged install
contract drives rendered TCP target function -> list -> target -> real restore path
continuous stage transitions -> exact stage sum + one data-only RTO
capture only stage/path/exit/category/duration allowlists
finalize active stage -> emit fixed diagnostics -> finally teardown raw private runtime
sudo helper: validated $0 self-cleanup or exact non-root outer cleanup; never sudo $HOME
non-zero apply remains FAIL
```