# governance-file-shield.ps1 -- 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

$ErrorActionPreference = 'Stop'

$rawInput = [Console]::In.ReadToEnd()

if ([string]::IsNullOrWhiteSpace($rawInput)) { exit 0 }

try { $input_obj = $rawInput | ConvertFrom-Json } catch { exit 0 }

$toolName = if ($input_obj.tool_name) { $input_obj.tool_name } else { '' }
$toolInput = $input_obj.tool_input

# Only gate write tools
switch ($toolName) {
    { $_ -in 'Edit', 'Write', 'NotebookEdit' } { break }
    'Bash' {
        $command = if ($toolInput.command) { $toolInput.command } else { '' }
        if (-not $command) { exit 0 }
        # Check for dangerous patterns targeting governance files
        $protectedPatterns = 'SOUL\.md|governance\.md|GOVERNANCE_RULES\.md|ROUTING_RULES\.md|agent-web-permissions\.md|web-interaction-security\.md'
        if ($command -match "(rm|mv|cp|sed|awk|tee|>|>>)\s.*($protectedPatterns)") {
            [Console]::Error.WriteLine("BLOCKED: Bash command attempts to modify protected governance file.")
            exit 2
        }
        exit 0
    }
    default { exit 0 }
}

# Extract file path
$filePath = if ($toolInput.file_path) { $toolInput.file_path }
             elseif ($toolInput.path) { $toolInput.path }
             else { '' }

if (-not $filePath) { exit 0 }

$fileName = [System.IO.Path]::GetFileName($filePath)

# Protected file patterns (case-insensitive)
$protectedFiles = @(
    'SOUL.md'
    'governance.md'
    'GOVERNANCE_RULES.md'
    'ROUTING_RULES.md'
    'agent-web-permissions.md'
    'web-interaction-security.md'
)

foreach ($protected in $protectedFiles) {
    if ($fileName -ieq $protected) {
        [Console]::Error.WriteLine("BLOCKED: '$fileName' is a protected governance file. Only human operators may modify it.")
        exit 2
    }
}

# Check against custom protected files list
$protectedList = $null
foreach ($candidate in @(
    '.claude/governance/protected-files.conf',
    '.claude/rules/protected-files.conf',
    'GOVERNANCE/protected-files.conf'
)) {
    if (Test-Path $candidate) {
        $protectedList = $candidate
        break
    }
}

if ($protectedList) {
    foreach ($line in Get-Content $protectedList) {
        $pattern = $line.Trim()
        if ($pattern -match '^#' -or -not $pattern) { continue }
        if ($filePath -like "*$pattern*") {
            [Console]::Error.WriteLine("BLOCKED: '$filePath' matches protected pattern '$pattern'.")
            exit 2
        }
    }
}

exit 0
