job4: install guard fail-closed
install-plugins.sh: mktemp failure building CFG_SNAPSHOT now aborts the install loudly (err + exit 1) instead of warning and continuing UNGUARDED — a failed guard used to mean CLAUDE.md/.claude/settings.json/ settings.json could be silently rewritten by graphify's installer for the rest of that run. Closes §3.4. Added T5 to lib/tests/curated-config-guard.test.sh: extracts the WIDER header block (GUARDED_CONFIGS through the closing `fi` — the fail-closed logic lives in the top-level if/else, outside restore_curated_configs(), so it needs its own awk range) in a subshell with a stubbed `mktemp` forced to fail; asserts exit 1 and a loud "mktemp failed" message. +2 assertions (4→6). Verified: bash -n clean, shellcheck clean (both files), full `make test` exit 0.
This commit is contained in:
+4
-1
@@ -62,7 +62,10 @@ if [ -n "$CFG_SNAPSHOT" ]; then
|
|||||||
done
|
done
|
||||||
trap restore_curated_configs EXIT
|
trap restore_curated_configs EXIT
|
||||||
else
|
else
|
||||||
warn "Config guard disabled (mktemp failed) — CLAUDE.md/settings may drift"
|
err "Config guard could not be created (mktemp failed) — refusing to run" \
|
||||||
|
"unguarded: CLAUDE.md/.claude/settings.json/settings.json could be" \
|
||||||
|
"silently rewritten by the installer. Fix mktemp/TMPDIR and retry."
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Read pinned version from plugins.lock.json
|
# Read pinned version from plugins.lock.json
|
||||||
|
|||||||
@@ -46,7 +46,33 @@ cmp -s "$REPO/.claude/settings.json" "$EXPECT/.claude/settings.json"
|
|||||||
check T2-untouched-local-settings-unchanged "$?" 0
|
check T2-untouched-local-settings-unchanged "$?" 0
|
||||||
cmp -s "$REPO/settings.json" "$EXPECT/settings.json"
|
cmp -s "$REPO/settings.json" "$EXPECT/settings.json"
|
||||||
check T3-untouched-settings-unchanged "$?" 0
|
check T3-untouched-settings-unchanged "$?" 0
|
||||||
[ ! -d "$CFG_SNAPSHOT" ]
|
if [ -d "$CFG_SNAPSHOT" ]; then r4=present; else r4=gone; fi
|
||||||
check T4-snapshot-dir-removed "$?" 0
|
check T4-snapshot-dir-removed "$r4" gone
|
||||||
|
|
||||||
|
# --- T5: mktemp failure -> fail-closed (install-plugins.sh, the header block
|
||||||
|
# that builds CFG_SNAPSHOT) — refuses to run unguarded instead of warning and
|
||||||
|
# continuing. Extracted with a WIDER range than the SUT above: this logic
|
||||||
|
# lives in the top-level if/else, outside restore_curated_configs().
|
||||||
|
SUT2="$(mktemp)"
|
||||||
|
awk '/^GUARDED_CONFIGS=/,/^fi$/' "$INSTALL_SH" > "$SUT2"
|
||||||
|
ERR5="$(mktemp)"
|
||||||
|
(
|
||||||
|
# shellcheck disable=SC2329 # invoked indirectly by the sourced snippet below
|
||||||
|
mktemp() { return 1; } # force the header's CFG_SNAPSHOT creation to fail
|
||||||
|
# shellcheck disable=SC2329
|
||||||
|
err() { echo "ERR: $*" >&2; }
|
||||||
|
# shellcheck disable=SC2329
|
||||||
|
warn() { echo "WARN: $*" >&2; }
|
||||||
|
# shellcheck disable=SC2329
|
||||||
|
info() { :; }
|
||||||
|
REPO="$(command mktemp -d)"
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$SUT2"
|
||||||
|
) >/dev/null 2>"$ERR5"
|
||||||
|
rc5=$?
|
||||||
|
check T5-mktemp-failure-aborts "$rc5" 1
|
||||||
|
if grep -qi 'mktemp failed' "$ERR5"; then r5msg=yes; else r5msg=no; fi
|
||||||
|
check T5-mktemp-failure-loud "$r5msg" yes
|
||||||
|
rm -f "$ERR5" "$SUT2"
|
||||||
|
|
||||||
printf 'PASS=%s FAIL=%s\n' "$pass" "$fail"; [ "$fail" -eq 0 ]
|
printf 'PASS=%s FAIL=%s\n' "$pass" "$fail"; [ "$fail" -eq 0 ]
|
||||||
|
|||||||
Reference in New Issue
Block a user