#!/usr/bin/env bash # kv-write-guard.sh 的迴歸測試(inkstone/ISEP#122 搬進 ISEP 時補上—— # 原檔 2026-08-25 立於 InkStoneCo 專案版,搬過來之前沒有自動化測試)。 set -u HOOK="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/kv-write-guard.sh}" PASS=0; FAIL=0; N=0 # run → 送一個 Write 事件的 payload run() { python3 -c ' import json,sys tool, fp, content = sys.argv[1], sys.argv[2], sys.argv[3] print(json.dumps({"tool_name": tool, "tool_input": {"file_path": fp, "content": content}})) ' "$1" "$2" "$3" | bash "$HOOK" 2>&1 echo "EXIT:$?" } check() { # check <說明> <輸出+EXIT行> <該擋(2)|該放行(0)> <該出現|!不該出現>... desc="$1"; out="$2"; want="$3"; shift 3 code="$(printf '%s\n' "$out" | grep -oE 'EXIT:[0-9]+' | tail -1 | cut -d: -f2)" N=$((N+1)); ok=1; why="" if [ "$code" != "$want" ]; then ok=0; why="要 exit $want,實際 $code"; fi for w in "$@"; do case "$w" in "!"*) if printf '%s' "$out" | grep -qF -- "${w#!}"; then ok=0; why="$why 不該出現卻出現:${w#!}"; fi ;; *) if ! printf '%s' "$out" | grep -qF -- "$w"; then ok=0; why="$why 少了:$w"; fi ;; esac done if [ "$ok" = 1 ]; then printf ' ✅ %s\n' "$desc"; PASS=$((PASS+1)) else printf ' ❌ %s ——%s\n' "$desc" "$why"; printf '%s\n' "$out" | sed 's/^/ /'; FAIL=$((FAIL+1)); fi } echo "── 該擋:往 KV binding 寫入 ──────────────────────────────────" out=$(run "Write" "src/app-system.ts" $'export async function save() {\n await MY_KV.put("k", "v");\n}') check "① 全大寫 binding.put( → 擋" "$out" 2 "長效資料不准寫進 KV" "MY_KV" out=$(run "Edit" "src/app-system.ts" $'const x = 1;\nSESSION_KV.delete(id);') check "② .delete( 一樣擋" "$out" 2 "長效資料不准寫進 KV" echo "── 不該擋(誤攔比漏擋嚴重)───────────────────────────────────" out=$(run "Write" "src/app-system.ts" 'const v = await MY_KV.get("k");') check "③ 只是讀(.get)→ 放行" "$out" 0 "!長效資料不准寫進 KV" out=$(run "Write" "src/app-system.ts" 'MY_KV.put("k", v); // kv-ok: session nonce,有 TTL') check "④ 加了 kv-ok 豁免留痕的那行 → 放行" "$out" 0 "!長效資料不准寫進 KV" out=$(run "Write" "README.md" 'MY_KV.put("k", "v")') check "⑤ 非程式碼檔(.md)→ 放行" "$out" 0 "!長效資料不准寫進 KV" out=$(run "Write" "src/kv-write-guard.test.ts" 'MY_KV.put("k", "v")') check "⑥ 閘自己的測試檔 → 放行" "$out" 0 "!長效資料不准寫進 KV" out=$(run "Write" "src/app-system.ts" 'const config = { retries: 3 };') check "⑦ 完全不提 KV 的一般程式碼 → 放行" "$out" 0 "!長效資料不准寫進 KV" out=$(run "Write" "src/app-system.ts" 'this.myKv.put("k", "v"); // 小寫 binding,不是本閘要的形狀') check "⑧ 小寫變數名(不是「全大寫識別字」形狀)→ 放行" "$out" 0 "!長效資料不准寫進 KV" echo "" echo "── 結果:$PASS 通過 / $FAIL 失敗(共 $N)──" [ "$FAIL" -eq 0 ]