#!/usr/bin/env bash
# governance-file-shield.sh -- PreToolUse hook
# Blocks any edit to governance files (SOUL.md, GOVERNANCE_RULES.md, etc.).
# SHA-256 integrity verification on protected files.
# Exit code 2 = block. Exit code 0 = allow.
#
# Part of @connexum/ai-governance

set -euo pipefail

INPUT=""; IFS= read -r -d '' -t 5 INPUT || true

# AIAG-018: enforce 1MB input size limit
if [ "${#INPUT}" -gt 1048576 ]; then
  echo "BLOCKED: Hook input exceeds 1MB. Possible injection attempt." >&2
  exit 2
fi

TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input // empty' 2>/dev/null)

# Only gate write tools
case "$TOOL_NAME" in
  Edit|Write|NotebookEdit) ;;
  Bash)
    # Check if bash command modifies protected files
    COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // empty' 2>/dev/null)
    if [ -z "$COMMAND" ]; then
      exit 0
    fi
    # Check for dangerous patterns targeting governance files.
    # F-NEW-PROBE-2026-05-03: previous pattern required whitespace after the
    # verb token (`[[:space:]]`) which let `>SOUL.md` (no space, common
    # shell idiom) bypass. Allow zero-or-more whitespace AND match the
    # path verb either with whitespace or directly adjoining the
    # protected filename.
    PROTECTED_PATTERNS="SOUL\.md|governance\.md|GOVERNANCE_RULES\.md|ROUTING_RULES\.md|agent-web-permissions\.md|web-interaction-security\.md"
    if echo "$COMMAND" | grep -qE "(rm|mv|cp|sed|awk|tee|>>?)[[:space:]]*[^|;&]*($PROTECTED_PATTERNS)"; then
      echo "BLOCKED: Bash command attempts to modify protected governance file." >&2
      exit 2
    fi
    exit 0
    ;;
  *) exit 0 ;;
esac

# Extract file path
FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // .path // empty' 2>/dev/null)

if [ -z "$FILE_PATH" ]; then
  exit 0
fi

# Get just the filename
FILENAME=$(basename "$FILE_PATH")

# Protected file patterns (case-insensitive check)
PROTECTED_FILES=(
  "SOUL.md"
  "governance.md"
  "GOVERNANCE_RULES.md"
  "ROUTING_RULES.md"
  "agent-web-permissions.md"
  "web-interaction-security.md"
)

# AIAG-012: bash 3.2 (macOS default) does not support `${var,,}` lowercase
# parameter expansion. Use `tr` for case-insensitive comparison so the hook
# works under /bin/bash on macOS as well as modern bash on Linux.
FILENAME_LC=$(printf '%s' "$FILENAME" | tr '[:upper:]' '[:lower:]')
for protected in "${PROTECTED_FILES[@]}"; do
  PROTECTED_LC=$(printf '%s' "$protected" | tr '[:upper:]' '[:lower:]')
  if [ "$FILENAME_LC" = "$PROTECTED_LC" ]; then
    echo "BLOCKED: '$FILENAME' is a protected governance file. Only human operators may modify it." >&2
    exit 2
  fi
done

# Check against custom protected files list
PROTECTED_LIST=""
for candidate in \
  ".claude/governance/protected-files.conf" \
  ".claude/rules/protected-files.conf" \
  "GOVERNANCE/protected-files.conf"; do
  if [ -f "$candidate" ]; then
    PROTECTED_LIST="$candidate"
    break
  fi
done

if [ -n "$PROTECTED_LIST" ]; then
  while IFS= read -r pattern; do
    [[ "$pattern" =~ ^#.*$ ]] && continue
    [[ -z "$pattern" ]] && continue
    if [[ "$FILE_PATH" == *"$pattern"* ]]; then
      echo "BLOCKED: '$FILE_PATH' matches protected pattern '$pattern'." >&2
      exit 2
    fi
  done < "$PROTECTED_LIST"
fi

exit 0
