Payload/scripts/kaden/advisory/AdvisoryTurnCorrelation.ps1
|
# Dot-sourced into AdvisoryWorkflow.psm1 - journal-derived turn correlation. function Get-AdvisoryAbsentTurnCorrelation { return [pscustomobject]@{ turn_correlation = 'absent' turn_context = [pscustomobject]@{ turn_state = 'absent'; turn_id = $null; slice = $null; is_active = $false } } } function Get-AdvisoryWorkflowJournalTurnRowSet { param([Parameter(Mandatory = $true)][string]$FeatureRoot) $events = @() if (Get-Command Get-HarnessJournalEvents -ErrorAction SilentlyContinue) { $events = @(Get-HarnessJournalEvents -FeatureRoot $FeatureRoot) } elseif (Test-Path -LiteralPath (Join-Path $FeatureRoot 'journal\events.jsonl')) { foreach ($line in @(Get-Content -LiteralPath (Join-Path $FeatureRoot 'journal\events.jsonl'))) { if ([string]::IsNullOrWhiteSpace($line)) { continue } $events += ($line | ConvertFrom-Json) } } $turnStarts = @() $turnStops = @() foreach ($evt in $events) { $kind = [string](Get-AdvisoryWorkflowProperty -Record $evt -Name 'kind') $activity = Get-AdvisoryWorkflowProperty -Record $evt -Name 'activity' $activityType = [string](Get-AdvisoryWorkflowProperty -Record $activity -Name 'type') $activityName = [string](Get-AdvisoryWorkflowProperty -Record $activity -Name 'name') $refs = Get-AdvisoryWorkflowProperty -Record $evt -Name 'refs' $turnId = [string](Get-AdvisoryWorkflowProperty -Record $refs -Name 'turn_id') if ([string]::IsNullOrWhiteSpace($turnId)) { $turnId = [string](Get-AdvisoryWorkflowProperty -Record $activity -Name 'id') } $slice = [string](Get-AdvisoryWorkflowProperty -Record $evt -Name 'slice') $isTurn = ($activityType -eq 'turn') -or ($activityName -eq 'start') -or ($activityName -eq 'stop') if (-not $isTurn) { continue } $row = [pscustomobject]@{ seq = [int](Get-AdvisoryWorkflowProperty -Record $evt -Name 'seq') kind = $kind turn_id = $turnId slice = $slice name = $activityName summary = [string](Get-AdvisoryWorkflowProperty -Record $evt -Name 'summary') } if ($kind -eq 'ActivityStarted' -and ($activityName -eq 'start' -or $activityType -eq 'turn')) { $turnStarts += $row } if ($kind -eq 'ActivityStopped' -and ($activityName -eq 'stop' -or $activityType -eq 'turn')) { $turnStops += $row } } return [pscustomobject]@{ starts = @($turnStarts); stops = @($turnStops) } } function Resolve-AdvisoryStoppedOrStaleTurn { param($LatestStop) $summary = [string](Get-AdvisoryWorkflowProperty -Record $LatestStop -Name 'summary') $state = if ($summary -match '(?i)stale|abandon') { 'stale' } else { 'stopped' } return [pscustomobject]@{ turn_correlation = $state turn_context = [pscustomobject]@{ turn_state = $state turn_id = [string]$LatestStop.turn_id slice = [string]$LatestStop.slice is_active = $false } } } function Resolve-AdvisoryWorkflowTurnCorrelation { param([Parameter(Mandatory = $true)][string]$FeatureRoot) $rows = Get-AdvisoryWorkflowJournalTurnRowSet -FeatureRoot $FeatureRoot if ($rows.starts.Count -eq 0 -and $rows.stops.Count -eq 0) { return Get-AdvisoryAbsentTurnCorrelation } $latestStart = $null $latestStop = $null $sortedStarts = @($rows.starts | Sort-Object seq) $sortedStops = @($rows.stops | Sort-Object seq) if ($sortedStarts.Count -gt 0) { $latestStart = $sortedStarts[-1] } if ($sortedStops.Count -gt 0) { $latestStop = $sortedStops[-1] } $open = $false if ($null -ne $latestStart) { $open = ($null -eq $latestStop) -or ([int]$latestStop.seq -lt [int]$latestStart.seq) } if ($open) { return [pscustomobject]@{ turn_correlation = 'open' turn_context = [pscustomobject]@{ turn_state = 'open' turn_id = [string]$latestStart.turn_id slice = [string]$latestStart.slice is_active = $true } } } if ($null -ne $latestStop) { return Resolve-AdvisoryStoppedOrStaleTurn -LatestStop $latestStop } return Get-AdvisoryAbsentTurnCorrelation } function Test-AdvisoryWorkflowTurnContextAgreement { param( $Derived, $Caller ) if ($null -eq $Caller) { return $true } $callerTurnId = [string](Get-AdvisoryWorkflowProperty -Record $Caller -Name 'turn_id') $callerState = [string](Get-AdvisoryWorkflowProperty -Record $Caller -Name 'turn_state') $callerSlice = [string](Get-AdvisoryWorkflowProperty -Record $Caller -Name 'slice') $derivedContext = Get-AdvisoryWorkflowProperty -Record $Derived -Name 'turn_context' $derivedTurnId = [string](Get-AdvisoryWorkflowProperty -Record $derivedContext -Name 'turn_id') $derivedState = [string](Get-AdvisoryWorkflowProperty -Record $Derived -Name 'turn_correlation') $derivedSlice = [string](Get-AdvisoryWorkflowProperty -Record $derivedContext -Name 'slice') if ((-not [string]::IsNullOrWhiteSpace($callerTurnId)) -and ($callerTurnId -ne $derivedTurnId)) { return $false } if ((-not [string]::IsNullOrWhiteSpace($callerState)) -and ($callerState -ne $derivedState) -and ($callerState -ne [string](Get-AdvisoryWorkflowProperty -Record $derivedContext -Name 'turn_state'))) { return $false } if ((-not [string]::IsNullOrWhiteSpace($callerSlice)) -and ($callerSlice -ne $derivedSlice)) { return $false } return $true } function Resolve-AdvisoryWorkflowTurnGate { <# .SYNOPSIS Derive turn correlation and reject a disagreeing caller envelope. #> param( [Parameter(Mandatory = $true)]$Request, [Parameter(Mandatory = $true)][string]$ActionName, [Parameter(Mandatory = $true)][string]$ActionId ) $featureRoot = [string]$Request.FeatureRoot $derived = Resolve-AdvisoryWorkflowTurnCorrelation -FeatureRoot $featureRoot $caller = ConvertFrom-AdvisoryWorkflowJson -Text ([string](Get-AdvisoryWorkflowProperty -Record $Request -Name 'TurnContextJson')) if (-not (Test-AdvisoryWorkflowTurnContextAgreement -Derived $derived -Caller $caller)) { return [pscustomobject]@{ rejected = $true result = (New-AdvisoryWorkflowFailure -Status 'rejected' -Code 'TURN_CONTEXT_DISAGREEMENT' -Action $ActionName -ActionId $ActionId ` -Message 'Caller turn context disagrees with the journal-derived turn correlation.') turn_context = $null turn_correlation = $null derived = $derived } } return [pscustomobject]@{ rejected = $false result = $null turn_context = (Get-AdvisoryWorkflowProperty -Record $derived -Name 'turn_context') turn_correlation = [string](Get-AdvisoryWorkflowProperty -Record $derived -Name 'turn_correlation') derived = $derived } } |