# destructive-command-guard.ps1 -- PreToolUse hook
# Blocks dangerous Bash commands unless explicitly authorized.
# 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 { '' }

# Only gate Bash tool
if ($toolName -ne 'Bash') { exit 0 }

$command = if ($input_obj.tool_input.command) { $input_obj.tool_input.command } else { '' }

if (-not $command) { exit 0 }

# Check maintenance mode override
if ($env:CXNI_MAINTENANCE_MODE -eq 'true') { exit 0 }

# Destructive patterns that require explicit authorization
$destructivePatterns = @(
    @{ Pattern = 'rm\s+(-[rRf]+\s+|--recursive|--force).*[/~]|rm\s+-rf\b'; Description = 'Recursive force delete' }
    @{ Pattern = 'git\s+push\s+.*--force\b|git\s+push\s+-f\b'; Description = 'Force push (can overwrite remote history)' }
    @{ Pattern = 'git\s+reset\s+--hard\b'; Description = 'Hard reset (discards all uncommitted changes)' }
    @{ Pattern = 'git\s+clean\s+-[fdx]+\b'; Description = 'Git clean (removes untracked files permanently)' }
    @{ Pattern = 'git\s+checkout\s+--\s+\.\b|git\s+restore\s+\.\b'; Description = 'Restore all files (discards all changes)' }
    @{ Pattern = 'DROP\s+(TABLE|DATABASE|INDEX|SCHEMA)\b'; Description = 'SQL DROP statement' }
    @{ Pattern = 'TRUNCATE\s+TABLE\b'; Description = 'SQL TRUNCATE statement' }
    @{ Pattern = 'DELETE\s+FROM\s+\w+\s*(;|\s*$|WHERE\s+1\s*=\s*1)'; Description = 'SQL DELETE without specific WHERE' }
    @{ Pattern = 'npm\s+publish\b'; Description = 'npm publish (releases package to registry)' }
    @{ Pattern = 'docker\s+system\s+prune\b'; Description = 'Docker system prune' }
    @{ Pattern = 'kill\s+-9\s+(-1|0)\b|killall\b'; Description = 'Kill all processes' }
    @{ Pattern = 'chmod\s+-R\s+777\b'; Description = 'Recursive world-writable permissions' }
    @{ Pattern = 'mkfs\b|fdisk\b|dd\s+if='; Description = 'Filesystem/disk operations' }
    @{ Pattern = '>\s*/dev/sd|>\s*/etc/'; Description = 'Write to system paths' }
    @{ Pattern = 'curl.*\|\s*(bash|sh)\b|wget.*\|\s*(bash|sh)\b'; Description = 'Pipe remote script to shell' }
    @{ Pattern = 'eval\s+.*\$(curl|wget)'; Description = 'Eval remote content' }
    @{ Pattern = 'base64\s+(-d|--decode).*\|\s*(bash|sh|eval)\b'; Description = 'Decode and execute base64 payload' }
    @{ Pattern = 'echo\s+.*\|\s*base64\s+(-d|--decode)\s*\|\s*(bash|sh)\b'; Description = 'Pipe decoded base64 to shell' }
    @{ Pattern = 'eval\s+.*base64'; Description = 'Eval base64-decoded content' }
    @{ Pattern = 'python[23]?\s+-c\s+.*exec\(.*base64'; Description = 'Python exec with base64 decode' }
    @{ Pattern = 'node\s+-e\s+.*Buffer\.from\(.*base64'; Description = 'Node eval with base64 decode' }
    # Windows-specific destructive patterns
    @{ Pattern = 'Remove-Item\s+.*-Recurse.*-Force'; Description = 'PowerShell recursive force delete' }
    @{ Pattern = 'Format-Volume\b|Clear-Disk\b'; Description = 'Disk formatting operations' }
    @{ Pattern = 'Stop-Process\s+.*-Force'; Description = 'Force kill processes' }
    @{ Pattern = 'Invoke-Expression.*Invoke-WebRequest'; Description = 'Download and execute remote code' }
    @{ Pattern = 'iex\s*\(.*iwr\b'; Description = 'PowerShell download-execute shorthand' }
)

foreach ($entry in $destructivePatterns) {
    if ($command -match $entry.Pattern) {
        [Console]::Error.WriteLine("BLOCKED: Destructive command detected -- $($entry.Description)")
        [Console]::Error.WriteLine("Command: $command")
        [Console]::Error.WriteLine("This command requires explicit human authorization.")
        exit 2
    }
}

exit 0
