Public/Resolve-NSPScanBridgeJob.ps1
|
function Resolve-NSPScanBridgeJob { <# .SYNOPSIS Verifies a held job against SharePoint before archival. .DESCRIPTION Read-back comparison uses actual remote bytes and SHA-256 rather than trusting filename or size. Does not retry the upload or overwrite files. Requires a previously established Process-scoped app-only Graph context. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][string]$ConfigurationPath, [Parameter(Mandatory)][string]$RouteName, [Parameter(Mandatory)][ValidatePattern('^[0-9a-f]{32}$')][string]$JobId ) $config = Import-PowerShellDataFile -LiteralPath $ConfigurationPath -ErrorAction Stop if (-not $config.LockPath) { throw 'LockPath is required.' } $lock = $null try { $lock = [IO.File]::Open([IO.Path]::GetFullPath([string]$config.LockPath), [IO.FileMode]::OpenOrCreate, [IO.FileAccess]::ReadWrite, [IO.FileShare]::None) } catch [IO.IOException] { throw 'ScanBridge worker or reconciler already holds the lock.' } try { $routes = @($config.Routes | Where-Object { $_.Name -eq $RouteName }) if ($routes.Count -ne 1) { throw 'Route must match exactly one configured entry.' } $route = $routes[0] $binding = Get-NSPScanBridgeJobBinding -Route $route -Auth $config.Auth $pdf = Join-Path $route.Spool ($JobId + '.pdf') $receiptPath = [IO.Path]::ChangeExtension($pdf, '.json') if (-not (Test-Path -LiteralPath $pdf -PathType Leaf) -or -not (Test-Path -LiteralPath $receiptPath -PathType Leaf)) { throw 'Held PDF and receipt must both exist.' } $receipt = Read-NSPScanBridgeReceipt -PdfPath $pdf -ReceiptPath $receiptPath -ExpectedBinding $binding if ($receipt.State -notin @('Review','Uploading')) { throw 'Job is not awaiting upload reconciliation.' } if ($receipt.JobId -ne $JobId -or $receipt.Hash -ne (Get-FileHash -LiteralPath $pdf -Algorithm SHA256).Hash) { throw 'Local PDF fails receipt integrity verification.' } Assert-NSPScanBridgeContext -Auth $config.Auth $result = Test-NSPScanBridgeRemoteMatch -PdfPath $pdf -DriveId ([string]$route.DriveId) -FolderItemId ([string]$route.FolderItemId) if ($result.Status -ne 'Verified') { return [pscustomobject]@{ JobId=$JobId; Status=$result.Status; Archived=$false } } if ($PSCmdlet.ShouldProcess($JobId,'Record verified remote copy and archive local PDF')) { Save-NSPScanBridgeReceipt -PdfPath $pdf -State Uploaded -RemoteId $result.RemoteId -VerifiedReconciliation -Binding $binding Complete-NSPScanBridgeArchive -PdfPath $pdf -ArchiveDirectory $route.Archive -ExpectedBinding $binding return [pscustomobject]@{ JobId=$JobId; Status='Verified'; Archived=$true } } } finally { $lock.Dispose() } } |