#!/usr/bin/env bash
# ============================================================
# pre-tool-guard.sh
# Claude Code PreToolUse hook — 硬边界安全守卫(确定性拦截)
#
# 拦截范围(exit 2 = 阻断,stderr 反馈给 Claude):
#   1. 对 reference/ 的任何写操作(只读铁律,文件工具 + Bash 双路拦截)
#   2. rm -rf 作用于项目根 / reference/ / 家目录 / 根目录 / 通配全删
#   3. git push --force / -f 与 git push/commit --no-verify
#   4. 明显会泄露密钥的 .env 读取/外传命令(.env.example 除外)
#
# 定位: 本脚本只做确定性安全拦截,不做流程编排。
# 注册: 见 .claude/settings.json → hooks.PreToolUse
# ============================================================
set -euo pipefail

INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')

block() {
    echo -e "🚫 已被 pre-tool-guard 硬边界拦截：$1" >&2
    exit 2
}

# ── A. 文件写入类工具: reference/ 只读 ──
case "$TOOL_NAME" in
    Write|Edit|MultiEdit|NotebookEdit)
        FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.notebook_path // .tool_input.path // ""')
        case "$FILE_PATH" in
            */reference/*|reference/*)
                block "reference/ 是只读参考区（CLAUDE.md 铁律），禁止写入: $FILE_PATH"
                ;;
        esac
        exit 0
        ;;
    Bash) : ;;   # 继续走下方 Bash 命令检查
    *) exit 0 ;;
esac

COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
[[ -z "$COMMAND" ]] && exit 0

# ── B. Bash: 对 reference/ 的写操作 ──
if echo "$COMMAND" | grep -qE '(^|/| )reference/'; then
    # 写指示词: 删除/移动/覆盖/重定向/就地修改/权限变更
    if echo "$COMMAND" | grep -qE '(^|[;&|]\s*|\s)(rm|mv|chmod|chown|truncate|shred|unlink|rmdir)\s[^;&|]*reference/' \
       || echo "$COMMAND" | grep -qE '(cp|rsync|install|ln|tee|touch|mkdir)\s[^;&|]*\s[^;&|]*reference/' \
       || echo "$COMMAND" | grep -qE '>>?\s*[^ ;&|]*reference/' \
       || echo "$COMMAND" | grep -qE 'sed\s+(-[a-zA-Z]*\s+)*-i[^;&|]*reference/' \
       || echo "$COMMAND" | grep -qE 'git\s+[^;&|]*\b(checkout|restore|clean|reset|stash|apply|am)\b[^;&|]*reference/'; then
        block "reference/ 是只读参考区（CLAUDE.md 铁律），禁止任何写/删/改操作。命令: $COMMAND"
    fi
fi

# ── C. 危险 rm -rf ──
if echo "$COMMAND" | grep -qE '(^|[;&|]\s*|\s)rm\s+(-[a-zA-Z]*[rR][a-zA-Z]*f[a-zA-Z]*|-[a-zA-Z]*f[a-zA-Z]*[rR][a-zA-Z]*|-[rR]\s+-f|-f\s+-[rR])\b'; then
    # 提取 rm 之后的目标(粗粒度即可,宁可错杀)
    if echo "$COMMAND" | grep -qE 'rm\s+(-[a-zA-Z]+\s+)*("?\$HOME"?|~|/|\.|\.\.|\*|"?\$\(pwd\)"?)(\s|$|/\*|"$)' \
       || echo "$COMMAND" | grep -qE 'rm\s+(-[a-zA-Z]+\s+)*[^ ]*reference/?(\s|$|\*)' \
       || echo "$COMMAND" | grep -qE 'rm\s+(-[a-zA-Z]+\s+)*[^ ]*PolyGateway/?(\s|$)'; then
        block "危险的 rm -rf（项目根 / reference / 家目录 / 通配全删）。请精确指定要删除的具体文件。命令: $COMMAND"
    fi
fi

# ── D. git 危险操作 ──
if echo "$COMMAND" | grep -qE 'git\s+push[^;&|]*(--force\b|--force-with-lease\b|\s-f\b)'; then
    block "禁止 git push --force（含 --force-with-lease）。如确需覆写远端历史，请人类手动执行。命令: $COMMAND"
fi
if echo "$COMMAND" | grep -qE 'git\s+(commit|push|merge)[^;&|]*--no-verify\b'; then
    block "禁止 --no-verify 绕过提交检查（质量门是硬边界）。命令: $COMMAND"
fi

# ── E. .env 密钥泄露 ──
# 允许 .env.example / .env.template;拦截对真实 .env 的直接读取与外传
ENV_RE='(^|[ /"'"'"'=@,:])\.env(\.[a-z]+)?'
if echo "$COMMAND" | grep -qE "$ENV_RE" \
   && ! echo "$COMMAND" | grep -qE '\.env\.(example|template|sample)\b'; then
    if echo "$COMMAND" | grep -qE '(^|[;&|]\s*|\s)(cat|less|more|head|tail|bat|strings|base64|xxd|od|nl)\s[^;&|]*\.env' \
       || echo "$COMMAND" | grep -qE '(^|[;&|]\s*|\s)(curl|wget|nc|scp|rsync|ftp)\s[^;&|]*\.env' \
       || echo "$COMMAND" | grep -qE '(^|[;&|]\s*|\s)(cp|mv)\s[^;&|]*\.env[^;&|]*\s[^;&|]*(reference|/tmp|/Users/Shared)' \
       || echo "$COMMAND" | grep -qE 'git\s+add\s[^;&|]*\.env'; then
        block "疑似泄露/外传 .env 密钥的命令（读取密钥请通过 pydantic-settings 在代码内完成；确需查看请人类手动执行）。命令: $COMMAND"
    fi
fi

exit 0
