Payload/scripts/kaden/harness/harness-pretooluse-guard.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS Cursor and Copilot (Windows) preToolUse / beforeShellExecution guard. .DESCRIPTION Denies bare harness scripts without pwsh -File scripts/kaden/harness-invoke.ps1, and denies production edits under src/, public/, or tests/ while RED is pending/in_progress without a CODE_FIRST_BUILD skip. Windows-only: PowerShell adapter. Copilot cloud/Linux is out of scope for this slice. Install via scripts/kaden/harness/setup-harness-hooks.ps1. #> [CmdletBinding()] param( [string]$InputJson = '', [string]$RepoRoot = '', [string]$FeatureRoot = '', # Fixture/Pester only: skip deny telemetry. Allowed solely when FeatureRoot is under TEMP. [switch]$SkipJournal ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $modulePath = Join-Path $PSScriptRoot 'lib\HarnessContract.psm1' Import-Module $modulePath -Force Import-Module (Join-Path $PSScriptRoot 'lib\HarnessJournal.psm1') -Force if ($SkipJournal -and -not (Test-HarnessPretooluseSkipJournalAllowed -FeatureRoot $FeatureRoot)) { throw 'SkipJournal is only allowed when -FeatureRoot is an existing path under TEMP (fixture/Pester isolation). Live hooks must not pass -SkipJournal.' } $stdin = if ([string]::IsNullOrWhiteSpace($InputJson)) { [Console]::In.ReadToEnd() } else { $InputJson } if ([string]::IsNullOrWhiteSpace($stdin)) { Write-Output '{"permission":"allow"}' exit 0 } if ([string]::IsNullOrWhiteSpace($RepoRoot)) { $RepoRoot = Get-HarnessRepoRoot -StartPath $PSScriptRoot } $payload = $stdin | ConvertFrom-Json $parsed = ConvertFrom-HarnessToolUseEnvelope -Payload $payload $policy = Test-HarnessToolUsePolicy -RepoRoot $RepoRoot -FeatureRoot $FeatureRoot ` -ToolFamily $parsed.ToolFamily -Command $parsed.Command -Path $parsed.Path $decision = [string]$policy.Decision if ($decision -eq 'deny' -and -not $SkipJournal) { try { $open = Get-HarnessOpenOwnershipTurn -RepoRoot $RepoRoot -FeatureRoot $FeatureRoot if ($open) { $actor = New-HarnessJournalActor -Agent 'harness-pretooluse-guard.ps1' -ParentAgent $null ` -Tool 'harness-script' -Provider 'other' -Slug 'unknown' -Role 'primary' $activity = New-HarnessJournalActivity -Id (New-HarnessJournalActivityId) -Type 'sensor' -Name 'pretooluse-guard' -Role 'instant' $denyPath = if ($parsed.Path) { $parsed.Path } else { $parsed.Command } Add-HarnessJournalEvent -FeatureRoot $open.FeatureRoot -Feature $open.Feature -Slice $open.Slice ` -Kind 'SensorRunRecorded' -Activity $activity -Actor $actor -Outcome 'DENY' ` -Summary "preToolUse denied: $denyPath" ` -Payload ([pscustomobject]@{ name = 'pretooluse-guard' verdict = 'DENY' path = $denyPath reason = [string]$policy.Reason }) ` -Refs ([pscustomobject]@{ amends_event_id = $null pair_event_id = $null artifact = $null command = '.\scripts\kaden\harness\harness-pretooluse-guard.ps1' }) | Out-Null } } catch { Write-Verbose "pretooluse-guard journal append failed: $($_.Exception.Message)" } } if ($decision -ne 'deny') { $decision = 'allow' } Write-Output (ConvertTo-HarnessHookPermissionJson -ResponseFamily $parsed.ResponseFamily -Decision $decision -Reason ([string]$policy.Reason)) exit 0 |