mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 22:34:02 +01:00
929 -> 217 lines across five pw_*.sh libraries. This file IS /usr/bin/pacman here (the symlink points at the deployed copy), so the design constraint was not readability but that no failure mode may leave the machine unable to install packages. Fail OPEN, unlike the other splits in this campaign. A missing lib warns on stderr and execs real pacman unwrapped. Failing closed would mean a missing lib leaves no way to install anything, including the missing lib. This is the same choice the existing pacman_lock_lib.sh block already makes, and it is verified rather than asserted: with pw_guard.sh removed from a scratch-dir copy, the wrapper warns, execs, and returns real `-Qi bash` output at rc=0. The libs load at the very top, before the fast path, because the fast path calls needs_unlock() to decide whether to exec straight through, and that function now lives in pw_guard.sh. They are deployed flat beside the wrapper — the shape pacman_lock_lib.sh and heavy_job_lock.sh already use in /usr/local/bin — as required copies, and are added to the integrity manifest. Tamper detection was round-tripped in a fake root: 8 manifest entries verify clean, and appending one line to pw_challenge.sh is detected and the transaction denied. Verified by execution, not just textually: real `-Qi bash` and `-Q` through the split wrapper are byte-identical to the pre-split baseline, same 2824 packages. verify_shell_split.sh reports all 14 top-level functions moved verbatim. The deployed copy is deliberately NOT updated by this commit and still hashes 548fc2b5... exactly as before the work started; live pacman is unaffected. A live `pacman -S` remains unverified — the Bash tool deadlocks on db.lck and a failed experiment costs the package manager. Cap is now down to one file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F3PzGc75gBcdxP3PkHXGcV
66 lines
5.9 KiB
JSON
66 lines
5.9 KiB
JSON
{
|
|
"intent": "Bring pacman_wrapper.sh (929 lines) under the 250-line cap. This file IS /usr/bin/pacman on this machine — /usr/bin/pacman is a symlink to the deployed copy — so the overriding constraint is that no failure mode may leave the box without a working package manager.",
|
|
"scope": [
|
|
"pacman_wrapper.sh: 929 -> 217 lines",
|
|
"New libs, FLAT beside the wrapper: pw_policy.sh (188), pw_challenge.sh (177), pw_cleanup.sh (153), pw_guard.sh (145), pw_ui.sh (90)",
|
|
"install_pacman_wrapper.sh + lib/install_files.sh: deploy the five libs",
|
|
"lib/integrity.sh: checksum them in the policy manifest",
|
|
"Non-goal: redeploying to /usr/local/bin, and any live `pacman -S` transaction"
|
|
],
|
|
"changes": [
|
|
"All 31 functions moved into five libs by responsibility. This needed a fix to extract_shell_functions.py first (committed separately): 17 of the 31 use bash's `function name() {` spelling, which the extractor did not recognise and would have silently left behind.",
|
|
"Libs are deployed FLAT beside the wrapper, matching pacman_lock_lib.sh and heavy_job_lock.sh, which already live and are sourced that way in /usr/local/bin. No lib/ subdirectory is created there.",
|
|
"The source block sits at the TOP of the file, before the fast path, because the fast path calls needs_unlock() to decide whether to exec real pacman and that function now lives in pw_guard.sh.",
|
|
"FAIL OPEN, unlike every other split in this campaign. A missing lib prints a warning to stderr and execs real pacman unwrapped. Failing closed here would mean a missing lib leaves no way to install anything — including the missing lib. This mirrors the choice the pre-existing pacman_lock_lib.sh block already makes.",
|
|
"The five libs are registered in install_files.sh as REQUIRED copies and added to the integrity manifest. They are sourced before verify_policy_integrity runs (the fast path forces that ordering), so the manifest entry is what makes tampering detectable — the check still refuses the transaction afterwards.",
|
|
"BOLD and MAKEPKG_CAPPED_BIN are exported: they are read by pw_ui.sh and pw_cleanup.sh, which shellcheck cannot see across the source boundary without -x."
|
|
],
|
|
"verification": [
|
|
{
|
|
"command": "PACMAN_BIN=/usr/bin/pacman.orig bash pacman_wrapper.sh -Qi bash / -Q",
|
|
"result": "pass",
|
|
"evidence": "REAL pacman queries through the split wrapper, byte-identical to the pre-split baseline: -Qi bash matches exactly, and -Q lists the same 2824 packages. This is execution, not textual proof — better than the --help-only baseline the prompt expected for this file."
|
|
},
|
|
{
|
|
"command": "fail-open simulation: flat layout in a scratch dir with pw_guard.sh removed",
|
|
"result": "pass",
|
|
"evidence": "THE critical safety property. With needs_unlock's lib missing, the wrapper prints 'pacman wrapper libraries missing; running pacman unwrapped.' to stderr, execs real pacman, returns rc=0 and real -Qi output. A missing lib cannot brick package management."
|
|
},
|
|
{
|
|
"command": "integrity round-trip in a fake root",
|
|
"result": "pass",
|
|
"evidence": "Built the manifest exactly as the patched installer does: 8 entries (2 policy lists + lock lib + 5 new libs). Untampered libs verify clean. Appending one line to pw_challenge.sh is DETECTED and the wrapper denies operation. The new libs are genuinely covered, not a hole in the check."
|
|
},
|
|
{
|
|
"command": "bash meta/scripts/verify_shell_split.sh HEAD <old> <old> <5 libs>",
|
|
"result": "pass",
|
|
"evidence": "'IDENTICAL: all 14 top-level functions moved verbatim' — no body changed."
|
|
},
|
|
{
|
|
"command": "python3 line-multiset check",
|
|
"result": "pass",
|
|
"evidence": "Two apparent losses, both explained: BOLD and MAKEPKG_CAPPED_BIN now carry an `export` prefix. Both confirmed present in the entry script; no code line was lost."
|
|
},
|
|
{
|
|
"command": "sha256sum /usr/local/bin/pacman_wrapper vs the backup taken before any edit",
|
|
"result": "pass",
|
|
"evidence": "548fc2b53ee4cea6... on both. The deployed copy is untouched by this commit, which is why live pacman is unaffected. `pacman -Qi bash` through the real /usr/bin/pacman symlink still works, and the symlink is intact."
|
|
},
|
|
{
|
|
"command": "shellcheck (no -x), shfmt idempotence, hyphenated-key canary, check_file_length --all",
|
|
"result": "pass",
|
|
"evidence": "shellcheck rc=0 with no new suppression; shfmt a no-op on all eight touched files; canary clean. The over-cap list is down to a single file."
|
|
}
|
|
],
|
|
"risks": [
|
|
"NOT VERIFIED against a live `pacman -S` transaction. The Bash tool deadlocks on db.lck for interactive pacman, and a failed experiment here costs the package manager. The evidence is instead: identical real read-only queries, a proven fail-open path, and a proven integrity round-trip. Running `sudo install_pacman_wrapper.sh` followed by a real install remains the one check only the user can perform.",
|
|
"The deployed copy still lacks the pw_*.sh libs until install_pacman_wrapper.sh is re-run. That ordering is safe in both directions: the deployed monolith is unchanged and self-contained, and if the new entry script were deployed without libs it would fail open to plain pacman rather than break.",
|
|
"The libs are sourced before verify_policy_integrity, so a tampered lib executes before the manifest is checked. Unavoidable given the fast path needs needs_unlock, and the same was already true of the wrapper file itself; the transaction is still refused."
|
|
],
|
|
"rollback": [
|
|
"git revert the commit; pacman_wrapper.sh returns to one 929-line file and the pw_*.sh libs disappear.",
|
|
"No live rollback needed — the deployed copy was never written.",
|
|
"If the split HAD been deployed: `sudo cp /tmp/.../restore/pacman_wrapper.deployed.bak /usr/local/bin/pacman_wrapper` restores the byte-identical monolith, and /usr/bin/pacman.orig (a real 157 KB ELF, verified running Pacman v7.1.0) is the escape hatch if even that fails."
|
|
]
|
|
}
|