# web-access-gate.ps1 -- PreToolUse hook
# Blocks WebSearch/WebFetch/Playwright for agents without web access authorization.
# 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 { '' }
$agentName = if ($input_obj.agent_name) { $input_obj.agent_name } else { '' }

# Only gate web-related tools
$webTools = @('WebSearch', 'WebFetch', 'mcp__playwright')
$isWebTool = $false
foreach ($wt in $webTools) {
    if ($toolName.StartsWith($wt)) {
        $isWebTool = $true
        break
    }
}

if (-not $isWebTool) { exit 0 }

# Find the permissions manifest
$manifest = $null
foreach ($candidate in @(
    '.claude/rules/agent-web-permissions.md',
    '.claude/governance/web-permissions.md',
    'GOVERNANCE/web-permissions.md'
)) {
    if (Test-Path $candidate) {
        $manifest = $candidate
        break
    }
}

# If no manifest exists, block all web access by default (deny-by-default)
if (-not $manifest) {
    [Console]::Error.WriteLine("BLOCKED: No web permissions manifest found. All web access denied by default.")
    exit 2
}

# If no agent name provided, block
if (-not $agentName) {
    [Console]::Error.WriteLine("BLOCKED: No agent name provided for web access check.")
    exit 2
}

# Parse agent's web access level from manifest
$accessLevel = 'NONE'
$manifestContent = Get-Content $manifest -Raw
if ($manifestContent -match "(?i)$([regex]::Escape($agentName)).*?(NONE|SEARCH_ONLY|READ_ONLY|FULL)") {
    $accessLevel = $Matches[1].ToUpper()
}

# Enforce access levels
switch ($accessLevel) {
    'NONE' {
        [Console]::Error.WriteLine("BLOCKED: Agent '$agentName' has NONE web access level. Tool '$toolName' denied.")
        exit 2
    }
    'SEARCH_ONLY' {
        if ($toolName -ne 'WebSearch') {
            [Console]::Error.WriteLine("BLOCKED: Agent '$agentName' has SEARCH_ONLY access. Tool '$toolName' denied (only WebSearch allowed).")
            exit 2
        }
    }
    'READ_ONLY' {
        if ($toolName.StartsWith('mcp__playwright')) {
            [Console]::Error.WriteLine("BLOCKED: Agent '$agentName' has READ_ONLY access. Playwright tools denied.")
            exit 2
        }
    }
    'FULL' {
        # All web tools allowed
    }
    default {
        [Console]::Error.WriteLine("BLOCKED: Unknown access level '$accessLevel' for agent '$agentName'.")
        exit 2
    }
}

exit 0
