param(
    [string]$ServiceName = "SyncVisionServer",

    [switch]$Probe,

    [string]$Server = "",

    [string]$Token = "",

    [string]$TokenFile = "",

    [ValidateSet("disabled", "optional", "required")]
    [string]$TransportEncryption = "disabled",

    [string]$TransportSecret = "",

    [string]$TransportSecretFile = "",

    [int]$TimeoutMs = 3000,

    [ValidateSet("", "Local", "Public", "Unknown")]
    [string]$ExpectProbeScope = "",

    [switch]$TestMode
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

function Resolve-SyncVisionStatusTrustedWindowsTool {
    param(
        [Parameter(Mandatory = $true)][string]$RelativePath,
        [Parameter(Mandatory = $true)][string]$Context
    )

    if ($RelativePath -cne "System32\sc.exe") {
        throw "$Context requested an unreviewed Windows tool path: $RelativePath"
    }
    $windowsRoot = [IO.Directory]::GetParent([Environment]::SystemDirectory).FullName.TrimEnd('\', '/')
    $path = [IO.Path]::GetFullPath((Join-Path $windowsRoot $RelativePath))
    $trustedSids = @(
        "S-1-5-18",
        "S-1-5-32-544",
        "S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464"
    )
    $mutationRights = [Security.AccessControl.FileSystemRights]::WriteData -bor
        [Security.AccessControl.FileSystemRights]::AppendData -bor
        [Security.AccessControl.FileSystemRights]::WriteExtendedAttributes -bor
        [Security.AccessControl.FileSystemRights]::WriteAttributes -bor
        [Security.AccessControl.FileSystemRights]::DeleteSubdirectoriesAndFiles -bor
        [Security.AccessControl.FileSystemRights]::Delete -bor
        [Security.AccessControl.FileSystemRights]::ChangePermissions -bor
        [Security.AccessControl.FileSystemRights]::TakeOwnership
    $destructiveRights = [Security.AccessControl.FileSystemRights]::DeleteSubdirectoriesAndFiles -bor
        [Security.AccessControl.FileSystemRights]::Delete -bor
        [Security.AccessControl.FileSystemRights]::ChangePermissions -bor
        [Security.AccessControl.FileSystemRights]::TakeOwnership
    $current = Get-Item -LiteralPath (Resolve-Path -LiteralPath $path).Path -Force
    while ($null -ne $current) {
        if (($current.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
            throw "$Context contains a reparse-point path component: $($current.FullName)"
        }
        $acl = Get-Acl -LiteralPath $current.FullName
        $owner = $acl.GetOwner([Security.Principal.SecurityIdentifier]).Value
        if ($trustedSids -notcontains $owner) {
            throw "$Context has an untrusted owner SID $owner at $($current.FullName)."
        }
        $normalized = $current.FullName.TrimEnd('\', '/')
        $reject = if ($normalized.StartsWith($windowsRoot + [IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase) -or
            [string]::Equals($normalized, $windowsRoot, [StringComparison]::OrdinalIgnoreCase)) { $mutationRights } else { $destructiveRights }
        foreach ($rule in $acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier])) {
            $applies = ($rule.PropagationFlags -band [Security.AccessControl.PropagationFlags]::InheritOnly) -eq 0
            if ($applies -and
                $rule.AccessControlType -eq [Security.AccessControl.AccessControlType]::Allow -and
                $trustedSids -notcontains $rule.IdentityReference.Value -and
                ($rule.FileSystemRights -band $reject) -ne 0) {
                throw "$Context grants an untrusted SID mutation rights at $($current.FullName)."
            }
        }
        $current = if ($current -is [IO.DirectoryInfo]) { $current.Parent } else { $current.Directory }
    }
    $item = Get-Item -LiteralPath $path -Force
    $signature = Get-AuthenticodeSignature -LiteralPath $item.FullName
    if ($signature.Status -ne [Management.Automation.SignatureStatus]::Valid -or
        $null -eq $signature.SignerCertificate -or
        $signature.SignerCertificate.Subject -notmatch '(^|, )O=Microsoft Corporation(,|$)') {
        throw "$Context does not have a valid Microsoft Authenticode identity."
    }
    return [pscustomobject]@{
        Path = $item.FullName
        Hash = (Get-FileHash -LiteralPath $item.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
        Version = [string]$item.VersionInfo.FileVersion
        SignerThumbprint = $signature.SignerCertificate.Thumbprint.ToUpperInvariant()
        SignerSubject = $signature.SignerCertificate.Subject
    }
}

function Get-SyncVisionServicePathsFromBinPath {
    param(
        [Parameter(Mandatory = $true)]
        [string]$BinPath
    )

    $installPath = $null
    $configPath = $null

    if ($BinPath -match '^\s*"([^"]+SyncVisionServer\.exe)"') {
        $installPath = Split-Path -Parent $matches[1]
    }
    elseif ($BinPath -match '^\s*(\S+SyncVisionServer\.exe)') {
        $installPath = Split-Path -Parent $matches[1]
    }

    if ($BinPath -match '--config\s+"([^"]+)"') {
        $configPath = $matches[1]
    }
    elseif ($BinPath -match '--config\s+(\S+)') {
        $configPath = $matches[1]
    }

    [pscustomobject]@{
        InstallPath = $installPath
        ConfigPath = $configPath
    }
}

function Get-SyncVisionServiceBinPath {
    param(
        [Parameter(Mandatory = $true)]
        [string]$ServiceName
    )

    $sc = Resolve-SyncVisionStatusTrustedWindowsTool -RelativePath "System32\sc.exe" -Context "Windows Service Controller"
    $output = & $sc.Path qc $ServiceName 2>$null
    if ($LASTEXITCODE -ne 0) {
        return $null
    }

    foreach ($line in $output) {
        if ($line -match 'BINARY_PATH_NAME\s+:\s+(.+)$') {
            return $matches[1].Trim()
        }
    }

    return $null
}

function Format-SyncVisionStatusBinPathForDisplay {
    param(
        [Parameter(Mandatory = $true)]
        [string]$BinPath
    )

    $display = [regex]::Replace($BinPath, '(^|\s)--token\s+"[^"]*"', '$1--token <redacted>')
    $display = [regex]::Replace($display, '(^|\s)--token\s+\S+', '$1--token <redacted>')
    $display = [regex]::Replace($display, '(^|\s)--token=(?:"[^"]*"|\S+)', '$1--token=<redacted>')
    $display = [regex]::Replace($display, '(^|\s)--transport-secret\s+"[^"]*"', '$1--transport-secret <redacted>')
    $display = [regex]::Replace($display, '(^|\s)--transport-secret\s+\S+', '$1--transport-secret <redacted>')
    $display = [regex]::Replace($display, '(^|\s)--transport-secret=(?:"[^"]*"|\S+)', '$1--transport-secret=<redacted>')
    return $display
}

function ConvertFrom-SyncVisionServerConfigText {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Text
    )

    $config = @{}
    foreach ($rawLine in ($Text -split "`r?`n")) {
        $line = ($rawLine -replace '#.*$', '').Trim()
        if (-not $line) {
            continue
        }

        $separator = $line.IndexOf("=")
        if ($separator -le 0) {
            throw "Invalid SyncVision server config line: $rawLine"
        }

        $key = $line.Substring(0, $separator).Trim()
        $value = $line.Substring($separator + 1).Trim()
        $config[$key] = $value
    }

    return $config
}

function Resolve-SyncVisionStatusEndpoint {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Endpoint
    )

    $separator = $Endpoint.LastIndexOf(":")
    if ($separator -le 0 -or $separator -eq $Endpoint.Length - 1) {
        return $Endpoint
    }

    $hostPart = $Endpoint.Substring(0, $separator)
    $portPart = $Endpoint.Substring($separator + 1)
    if ($hostPart -eq "0.0.0.0" -or $hostPart -eq "::" -or $hostPart -eq "*") {
        return "127.0.0.1:$portPart"
    }

    return $Endpoint
}

function Get-SyncVisionStatusEndpointHost {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Endpoint
    )

    $trimmed = $Endpoint.Trim()
    if ($trimmed.StartsWith("[")) {
        $closingBracket = $trimmed.IndexOf("]")
        if ($closingBracket -gt 0) {
            return $trimmed.Substring(1, $closingBracket - 1)
        }
    }

    $separator = $trimmed.LastIndexOf(":")
    if ($separator -le 0) {
        return $trimmed.Trim("[", "]")
    }

    return $trimmed.Substring(0, $separator).Trim().Trim("[", "]")
}

function Test-SyncVisionStatusPrivateOrLocalAddress {
    param(
        [Parameter(Mandatory = $true)]
        [System.Net.IPAddress]$Address
    )

    if ($Address.Equals([System.Net.IPAddress]::Any) -or
        $Address.Equals([System.Net.IPAddress]::IPv6Any) -or
        $Address.Equals([System.Net.IPAddress]::Broadcast) -or
        $Address.Equals([System.Net.IPAddress]::None) -or
        [System.Net.IPAddress]::IsLoopback($Address)) {
        return $true
    }

    $bytes = $Address.GetAddressBytes()
    if ($Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork) {
        return (
            $bytes[0] -eq 0 -or
            $bytes[0] -eq 10 -or
            $bytes[0] -eq 127 -or
            ($bytes[0] -eq 169 -and $bytes[1] -eq 254) -or
            ($bytes[0] -eq 172 -and $bytes[1] -ge 16 -and $bytes[1] -le 31) -or
            ($bytes[0] -eq 192 -and $bytes[1] -eq 168) -or
            ($bytes[0] -eq 100 -and $bytes[1] -ge 64 -and $bytes[1] -le 127)
        )
    }

    if ($Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetworkV6) {
        return (
            $Address.IsIPv6LinkLocal -or
            $Address.IsIPv6SiteLocal -or
            $Address.IsIPv6Multicast -or
            (($bytes[0] -band 0xfe) -eq 0xfc)
        )
    }

    return $false
}

function Resolve-SyncVisionStatusHostAddresses {
    param(
        [Parameter(Mandatory = $true)]
        [string]$HostName
    )

    $normalized = $HostName.Trim()
    if ([string]::IsNullOrWhiteSpace($normalized) -or $normalized -eq "*") {
        return @([System.Net.IPAddress]::Any)
    }

    $ipAddress = [System.Net.IPAddress]::None
    if ([System.Net.IPAddress]::TryParse($normalized, [ref]$ipAddress)) {
        return @($ipAddress)
    }

    try {
        return @([System.Net.Dns]::GetHostAddresses($normalized))
    }
    catch {
        return @()
    }
}

function Get-SyncVisionStatusHostScope {
    param(
        [Parameter(Mandatory = $true)]
        [string]$HostName
    )

    $addresses = @(Resolve-SyncVisionStatusHostAddresses -HostName $HostName)
    if ($addresses.Count -eq 0) {
        return "Unknown"
    }

    foreach ($address in $addresses) {
        if (Test-SyncVisionStatusPrivateOrLocalAddress -Address $address) {
            return "Local"
        }
    }

    return "Public"
}

function Get-SyncVisionStatusProbeScope {
    param(
        [AllowEmptyString()]
        [string]$ConfiguredEndpoint = "",

        [Parameter(Mandatory = $true)]
        [string]$ProbeEndpoint,

        [bool]$ExplicitServer = $false
    )

    $scopeEndpoint = if ($ExplicitServer -or [string]::IsNullOrWhiteSpace($ConfiguredEndpoint)) {
        $ProbeEndpoint
    }
    else {
        $ConfiguredEndpoint
    }

    $scopeHost = Get-SyncVisionStatusEndpointHost -Endpoint $scopeEndpoint
    return Get-SyncVisionStatusHostScope -HostName $scopeHost
}

function Format-SyncVisionStatusProbeScope {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Scope,

        [AllowEmptyString()]
        [string]$ConfiguredEndpoint = "",

        [Parameter(Mandatory = $true)]
        [string]$ProbeEndpoint
    )

    if ($Scope -eq "Public") {
        return @(
            "ProbeEndpoint: $ProbeEndpoint",
            "ConfiguredListen: $(if ([string]::IsNullOrWhiteSpace($ConfiguredEndpoint)) { '<explicit>' } else { $ConfiguredEndpoint })",
            "ProbeScope: PublicAddress",
            "Reachability: reachable from this probe machine/network only; not a global internet reachability guarantee."
        ) -join [Environment]::NewLine
    }

    if ($Scope -eq "Unknown") {
        return @(
            "ProbeEndpoint: $ProbeEndpoint",
            "ConfiguredListen: $(if ([string]::IsNullOrWhiteSpace($ConfiguredEndpoint)) { '<explicit>' } else { $ConfiguredEndpoint })",
            "ProbeScope: UnknownAddress",
            "Reachability: endpoint hostname did not resolve to an address; public/private reachability is not proven."
        ) -join [Environment]::NewLine
    }

    return @(
        "ProbeEndpoint: $ProbeEndpoint",
        "ConfiguredListen: $ConfiguredEndpoint",
        "ProbeScope: LocalAddress",
        "ProbeOrigin: local status script using a loopback, wildcard-resolved, private, or link-local endpoint.",
        "Reachability: local/private path only; public DNS/NAT/firewall/cloud security group not tested and does not prove external public reachability."
    ) -join [Environment]::NewLine
}

function Assert-SyncVisionExpectedProbeScope {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Actual,

        [AllowEmptyString()]
        [string]$Expected = ""
    )

    if ([string]::IsNullOrWhiteSpace($Expected)) {
        return
    }

    if ($Actual -ne $Expected) {
        throw "Status probe scope was '$Actual', expected '$Expected'."
    }
}

function Format-SyncVisionStatusConfigSummary {
    param(
        [Parameter(Mandatory = $true)]
        [hashtable]$Config
    )

    $lines = New-Object System.Collections.Generic.List[string]
    foreach ($key in ($Config.Keys | Sort-Object)) {
        $value = if ($key -eq "token" -or $key -eq "transport_secret") { "<redacted>" } else { $Config[$key] }
        $lines.Add("$key=$value")
    }

    return ($lines -join [Environment]::NewLine)
}

function Resolve-SyncVisionStatusToken {
    param(
        [Parameter(Mandatory = $true)]
        [hashtable]$Config,

        [AllowEmptyString()]
        [string]$ConfigPath = ""
    )

    if ($Config.ContainsKey("token_file") -and -not [string]::IsNullOrWhiteSpace($Config["token_file"])) {
        $tokenFile = $Config["token_file"]
        if (-not [IO.Path]::IsPathRooted($tokenFile) -and -not [string]::IsNullOrWhiteSpace($ConfigPath)) {
            $configDir = Split-Path -Parent $ConfigPath
            $tokenFile = Join-Path $configDir $tokenFile
        }

        if (-not (Test-Path -LiteralPath $tokenFile -PathType Leaf)) {
            throw "Status probe token file was not found: $tokenFile"
        }

        $tokenText = ([IO.File]::ReadAllText($tokenFile)).Trim()
        if ([string]::IsNullOrWhiteSpace($tokenText)) {
            throw "Status probe token file cannot be empty: $tokenFile"
        }

        return $tokenText
    }

    if ($Config.ContainsKey("token") -and -not [string]::IsNullOrWhiteSpace($Config["token"])) {
        return $Config["token"]
    }

    return ""
}

function Resolve-SyncVisionStatusConfigRelativePath {
    param(
        [AllowEmptyString()]
        [string]$Path = "",

        [AllowEmptyString()]
        [string]$ConfigPath = ""
    )

    if ([string]::IsNullOrWhiteSpace($Path)) {
        return ""
    }
    if ([IO.Path]::IsPathRooted($Path) -or [string]::IsNullOrWhiteSpace($ConfigPath)) {
        return $Path
    }

    $configDir = Split-Path -Parent $ConfigPath
    if ([string]::IsNullOrWhiteSpace($configDir)) {
        return $Path
    }

    return Join-Path $configDir $Path
}

function Read-SyncVisionRequiredSecretFile {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Path,

        [Parameter(Mandatory = $true)]
        [string]$Name
    )

    if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
        throw "$Name was not found: $Path"
    }

    $secretText = ([IO.File]::ReadAllText($Path)).Trim()
    if ([string]::IsNullOrWhiteSpace($secretText)) {
        throw "$Name cannot be empty: $Path"
    }

    return $secretText
}

function Resolve-SyncVisionStatusTransportSecret {
    param(
        [AllowEmptyString()]
        [string]$TransportSecret = "",

        [AllowEmptyString()]
        [string]$TransportSecretFile = "",

        [hashtable]$Config = @{},

        [AllowEmptyString()]
        [string]$ConfigPath = ""
    )

    if (-not [string]::IsNullOrWhiteSpace($TransportSecret) -and
        -not [string]::IsNullOrWhiteSpace($TransportSecretFile)) {
        throw "Pass either -TransportSecret or -TransportSecretFile, not both."
    }
    if (-not [string]::IsNullOrWhiteSpace($TransportSecretFile)) {
        return Read-SyncVisionRequiredSecretFile -Path $TransportSecretFile -Name "TransportSecretFile"
    }
    if (-not [string]::IsNullOrWhiteSpace($TransportSecret)) {
        return $TransportSecret
    }

    if ($Config -and
        $Config.ContainsKey("transport_secret") -and
        $Config.ContainsKey("transport_secret_file") -and
        -not [string]::IsNullOrWhiteSpace($Config["transport_secret"]) -and
        -not [string]::IsNullOrWhiteSpace($Config["transport_secret_file"])) {
        throw "Config cannot combine transport_secret and transport_secret_file."
    }
    if ($Config -and $Config.ContainsKey("transport_secret_file") -and
        -not [string]::IsNullOrWhiteSpace($Config["transport_secret_file"])) {
        $secretFile = Resolve-SyncVisionStatusConfigRelativePath -Path $Config["transport_secret_file"] -ConfigPath $ConfigPath
        return Read-SyncVisionRequiredSecretFile -Path $secretFile -Name "transport_secret_file"
    }
    if ($Config -and $Config.ContainsKey("transport_secret") -and
        -not [string]::IsNullOrWhiteSpace($Config["transport_secret"])) {
        return $Config["transport_secret"]
    }

    return ""
}

function Resolve-SyncVisionStatusProbeToken {
    param(
        [AllowEmptyString()]
        [string]$Token = "",

        [AllowEmptyString()]
        [string]$TokenFile = "",

        [AllowEmptyString()]
        [string]$ConfigToken = ""
    )

    if (-not [string]::IsNullOrWhiteSpace($TokenFile)) {
        if (-not [string]::IsNullOrWhiteSpace($Token)) {
            throw "Pass either -Token or -TokenFile, not both."
        }

        return Resolve-SyncVisionStatusToken -Config @{ token_file = $TokenFile }
    }

    if (-not [string]::IsNullOrWhiteSpace($Token)) {
        return $Token
    }

    return $ConfigToken
}

function ConvertTo-SyncVisionBytes {
    param(
        [AllowEmptyString()]
        [string]$Text = ""
    )

    return [Text.Encoding]::UTF8.GetBytes($Text)
}

function ConvertTo-SyncVisionHex {
    param(
        [Parameter(Mandatory = $true)]
        [byte[]]$Bytes
    )

    $builder = [Text.StringBuilder]::new($Bytes.Length * 2)
    foreach ($byte in $Bytes) {
        [void]$builder.AppendFormat("{0:x2}", $byte)
    }

    return $builder.ToString()
}

function New-SyncVisionRandomBytes {
    param(
        [Parameter(Mandatory = $true)]
        [int]$Length
    )

    if ($Length -lt 0) {
        throw "Random byte length cannot be negative."
    }

    $bytes = New-Object byte[] $Length
    if ($Length -eq 0) {
        return $bytes
    }

    $rng = [Security.Cryptography.RandomNumberGenerator]::Create()
    try {
        $rng.GetBytes($bytes)
    }
    finally {
        $rng.Dispose()
    }

    return $bytes
}

function Get-SyncVisionHmacSha256 {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Secret,

        [Parameter(Mandatory = $true)]
        [string]$Message
    )

    if ([string]::IsNullOrEmpty($Secret)) {
        throw "authentication secret cannot be empty."
    }

    $keyBytes = ConvertTo-SyncVisionBytes -Text $Secret
    $messageBytes = ConvertTo-SyncVisionBytes -Text $Message
    $hmac = [Security.Cryptography.HMACSHA256]::new($keyBytes)
    try {
        return $hmac.ComputeHash($messageBytes)
    }
    finally {
        $hmac.Dispose()
    }
}

function Get-SyncVisionHmacSha256Hex {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Secret,

        [Parameter(Mandatory = $true)]
        [string]$Message
    )

    return ConvertTo-SyncVisionHex -Bytes (Get-SyncVisionHmacSha256 -Secret $Secret -Message $Message)
}

function New-SyncVisionStatusRequestPayload {
    param(
        [AllowEmptyString()]
        [string]$Token = ""
    )

    if ([string]::IsNullOrEmpty($Token)) {
        return "token=`n"
    }

    $nonce = ConvertTo-SyncVisionHex -Bytes (New-SyncVisionRandomBytes -Length 16)
    $authTimestampMs = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
    $authMessage = "syncvision.status.v2`nauth_nonce=$nonce`nauth_timestamp_ms=$authTimestampMs`n"
    $proof = Get-SyncVisionHmacSha256Hex -Secret $Token -Message $authMessage
    return "auth_nonce=$nonce`nauth_timestamp_ms=$authTimestampMs`ntoken_proof=$proof`n"
}

function Add-SyncVisionAesGcmType {
    if ("SyncVision.CngAesGcm" -as [type]) {
        return
    }

    Add-Type -Language CSharp -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;

namespace SyncVision
{
    public static class CngAesGcm
    {
        private const int BCRYPT_CHAIN_MODE_GCM_INFO_VERSION = 1;
        private static readonly int STATUS_AUTH_TAG_MISMATCH = unchecked((int)0xC000A002);
        private static readonly byte[] ChainModeGcm = Encoding.Unicode.GetBytes("ChainingModeGCM\0");

        [StructLayout(LayoutKind.Sequential)]
        private struct BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
        {
            public int cbSize;
            public int dwInfoVersion;
            public IntPtr pbNonce;
            public int cbNonce;
            public IntPtr pbAuthData;
            public int cbAuthData;
            public IntPtr pbTag;
            public int cbTag;
            public IntPtr pbMacContext;
            public int cbMacContext;
            public int cbAAD;
            public long cbData;
            public int dwFlags;
        }

        [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
        private static extern int BCryptOpenAlgorithmProvider(out IntPtr phAlgorithm, string pszAlgId, string pszImplementation, int dwFlags);

        [DllImport("bcrypt.dll")]
        private static extern int BCryptCloseAlgorithmProvider(IntPtr hAlgorithm, int dwFlags);

        [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
        private static extern int BCryptSetProperty(IntPtr hObject, string pszProperty, byte[] pbInput, int cbInput, int dwFlags);

        [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
        private static extern int BCryptGetProperty(IntPtr hObject, string pszProperty, out int pbOutput, int cbOutput, out int pcbResult, int dwFlags);

        [DllImport("bcrypt.dll")]
        private static extern int BCryptGenerateSymmetricKey(
            IntPtr hAlgorithm,
            out IntPtr phKey,
            byte[] pbKeyObject,
            int cbKeyObject,
            byte[] pbSecret,
            int cbSecret,
            int dwFlags);

        [DllImport("bcrypt.dll")]
        private static extern int BCryptDestroyKey(IntPtr hKey);

        [DllImport("bcrypt.dll")]
        private static extern int BCryptEncrypt(
            IntPtr hKey,
            byte[] pbInput,
            int cbInput,
            ref BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO pPaddingInfo,
            IntPtr pbIV,
            int cbIV,
            byte[] pbOutput,
            int cbOutput,
            out int pcbResult,
            int dwFlags);

        [DllImport("bcrypt.dll")]
        private static extern int BCryptDecrypt(
            IntPtr hKey,
            byte[] pbInput,
            int cbInput,
            ref BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO pPaddingInfo,
            IntPtr pbIV,
            int cbIV,
            byte[] pbOutput,
            int cbOutput,
            out int pcbResult,
            int dwFlags);

        public static byte[] Encrypt(byte[] key, byte[] nonce, byte[] authenticatedData, byte[] plaintext)
        {
            ValidateInputs(key, nonce, authenticatedData, plaintext, null);
            byte[] tag = new byte[16];
            byte[] ciphertext = new byte[plaintext.Length];
            using (Pinned pinNonce = new Pinned(nonce))
            using (Pinned pinAuth = new Pinned(authenticatedData))
            using (Pinned pinTag = new Pinned(tag))
            {
                WithAesGcmKey(key, (hKey) =>
                {
                    BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO info = AuthInfo(pinNonce, nonce.Length, pinAuth, authenticatedData.Length, pinTag, tag.Length);
                    int bytesWritten;
                    Check(BCryptEncrypt(hKey, plaintext, plaintext.Length, ref info, IntPtr.Zero, 0, ciphertext, ciphertext.Length, out bytesWritten, 0), "BCryptEncrypt AES-GCM");
                    if (bytesWritten != ciphertext.Length)
                    {
                        Array.Resize(ref ciphertext, bytesWritten);
                    }
                });
            }

            byte[] combined = new byte[tag.Length + ciphertext.Length];
            Buffer.BlockCopy(tag, 0, combined, 0, tag.Length);
            Buffer.BlockCopy(ciphertext, 0, combined, tag.Length, ciphertext.Length);
            return combined;
        }

        public static byte[] Decrypt(byte[] key, byte[] nonce, byte[] authenticatedData, byte[] tag, byte[] ciphertext)
        {
            ValidateInputs(key, nonce, authenticatedData, ciphertext, tag);
            byte[] plaintext = new byte[ciphertext.Length];
            using (Pinned pinNonce = new Pinned(nonce))
            using (Pinned pinAuth = new Pinned(authenticatedData))
            using (Pinned pinTag = new Pinned(tag))
            {
                WithAesGcmKey(key, (hKey) =>
                {
                    BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO info = AuthInfo(pinNonce, nonce.Length, pinAuth, authenticatedData.Length, pinTag, tag.Length);
                    int bytesWritten;
                    int status = BCryptDecrypt(hKey, ciphertext, ciphertext.Length, ref info, IntPtr.Zero, 0, plaintext, plaintext.Length, out bytesWritten, 0);
                    if (status == STATUS_AUTH_TAG_MISMATCH)
                    {
                        throw new CryptographicException("encrypted payload authentication failed.");
                    }
                    Check(status, "BCryptDecrypt AES-GCM");
                    if (bytesWritten != plaintext.Length)
                    {
                        Array.Resize(ref plaintext, bytesWritten);
                    }
                });
            }

            return plaintext;
        }

        private static BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO AuthInfo(Pinned nonce, int nonceLength, Pinned auth, int authLength, Pinned tag, int tagLength)
        {
            return new BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO
            {
                cbSize = Marshal.SizeOf(typeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO)),
                dwInfoVersion = BCRYPT_CHAIN_MODE_GCM_INFO_VERSION,
                pbNonce = nonce.Pointer,
                cbNonce = nonceLength,
                pbAuthData = auth.Pointer,
                cbAuthData = authLength,
                pbTag = tag.Pointer,
                cbTag = tagLength,
                pbMacContext = IntPtr.Zero,
                cbMacContext = 0,
                cbAAD = 0,
                cbData = 0,
                dwFlags = 0
            };
        }

        private static void WithAesGcmKey(byte[] key, Action<IntPtr> action)
        {
            IntPtr algorithm = IntPtr.Zero;
            IntPtr keyHandle = IntPtr.Zero;
            byte[] keyObject = null;
            try
            {
                Check(BCryptOpenAlgorithmProvider(out algorithm, "AES", null, 0), "BCryptOpenAlgorithmProvider AES");
                Check(BCryptSetProperty(algorithm, "ChainingMode", ChainModeGcm, ChainModeGcm.Length, 0), "BCryptSetProperty BCRYPT_CHAIN_MODE_GCM");
                int objectLength;
                int bytesWritten;
                Check(BCryptGetProperty(algorithm, "ObjectLength", out objectLength, 4, out bytesWritten, 0), "BCryptGetProperty BCRYPT_OBJECT_LENGTH");
                keyObject = new byte[objectLength];
                Check(BCryptGenerateSymmetricKey(algorithm, out keyHandle, keyObject, keyObject.Length, key, key.Length, 0), "BCryptGenerateSymmetricKey AES");
                action(keyHandle);
            }
            finally
            {
                if (keyHandle != IntPtr.Zero)
                {
                    BCryptDestroyKey(keyHandle);
                }
                if (algorithm != IntPtr.Zero)
                {
                    BCryptCloseAlgorithmProvider(algorithm, 0);
                }
            }
        }

        private static void ValidateInputs(byte[] key, byte[] nonce, byte[] authenticatedData, byte[] input, byte[] tag)
        {
            if (key == null || key.Length != 32)
            {
                throw new ArgumentException("AES-256-GCM key must be 32 bytes.");
            }
            if (nonce == null || nonce.Length != 12)
            {
                throw new ArgumentException("AES-GCM nonce must be 12 bytes.");
            }
            if (authenticatedData == null)
            {
                throw new ArgumentNullException("authenticatedData");
            }
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (tag != null && tag.Length != 16)
            {
                throw new ArgumentException("AES-GCM tag must be 16 bytes.");
            }
        }

        private static void Check(int status, string action)
        {
            if (status < 0)
            {
                throw new CryptographicException(action + " failed with NTSTATUS " + status.ToString());
            }
        }

        private sealed class Pinned : IDisposable
        {
            private GCHandle handle;
            private bool pinned;

            public Pinned(byte[] bytes)
            {
                if (bytes != null && bytes.Length > 0)
                {
                    handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                    pinned = true;
                    Pointer = handle.AddrOfPinnedObject();
                }
                else
                {
                    Pointer = IntPtr.Zero;
                }
            }

            public IntPtr Pointer { get; private set; }

            public void Dispose()
            {
                if (pinned)
                {
                    handle.Free();
                    pinned = false;
                }
            }
        }
    }
}
'@
}

function Get-SyncVisionTransportKey {
    param(
        [Parameter(Mandatory = $true)]
        [string]$TransportSecret,

        [Parameter(Mandatory = $true)]
        [string]$Context
    )

    if ([string]::IsNullOrEmpty($TransportSecret)) {
        throw "TransportSecret cannot be empty when transport encryption is enabled."
    }
    if ([string]::IsNullOrEmpty($Context)) {
        throw "Transport encryption context cannot be empty."
    }

    return Get-SyncVisionHmacSha256 `
        -Secret $TransportSecret `
        -Message "syncvision.transport-key.v1`ncontext=$Context`n"
}

function Join-SyncVisionByteArrays {
    param(
        [Parameter(Mandatory = $true)]
        [byte[][]]$Arrays
    )

    $length = 0
    foreach ($array in $Arrays) {
        if ($array) {
            $length += $array.Length
        }
    }

    $result = New-Object byte[] $length
    $offset = 0
    foreach ($array in $Arrays) {
        if (-not $array -or $array.Length -eq 0) {
            continue
        }
        [Array]::Copy($array, 0, $result, $offset, $array.Length)
        $offset += $array.Length
    }

    return $result
}

function New-SyncVisionEncryptedFramePayload {
    param(
        [UInt16]$Type,

        [Parameter(Mandatory = $true)]
        [byte[]]$Payload,

        [Parameter(Mandatory = $true)]
        [string]$TransportSecret,

        [Parameter(Mandatory = $true)]
        [string]$Context
    )

    if ([string]::IsNullOrEmpty($TransportSecret)) {
        throw "TransportSecret cannot be empty when transport encryption is enabled."
    }
    if ([string]::IsNullOrEmpty($Context)) {
        throw "Transport encryption context cannot be empty."
    }
    if ($Type -eq 14) {
        throw "EncryptedEnvelope cannot be nested inside another encrypted envelope."
    }

    Add-SyncVisionAesGcmType

    $payloadLengthBytes = [BitConverter]::GetBytes([UInt32]$Payload.Length)
    $header = New-Object byte[] 16
    [Text.Encoding]::ASCII.GetBytes("SVE1").CopyTo($header, 0)
    [BitConverter]::GetBytes([UInt16]1).CopyTo($header, 4)
    [BitConverter]::GetBytes([UInt16]$Type).CopyTo($header, 6)
    [BitConverter]::GetBytes([UInt16]12).CopyTo($header, 8)
    [BitConverter]::GetBytes([UInt16]16).CopyTo($header, 10)
    $payloadLengthBytes.CopyTo($header, 12)

    $nonce = New-SyncVisionRandomBytes -Length 12
    $aad = Join-SyncVisionByteArrays -Arrays @(
        (ConvertTo-SyncVisionBytes -Text "syncvision.encrypted-frame.v1`n$Context`n"),
        $header
    )
    $key = Get-SyncVisionTransportKey -TransportSecret $TransportSecret -Context $Context
    $encrypted = [SyncVision.CngAesGcm]::Encrypt($key, $nonce, $aad, $Payload)

    return Join-SyncVisionByteArrays -Arrays @($header, $nonce, $encrypted)
}

function ConvertFrom-SyncVisionFrameBytes {
    param(
        [Parameter(Mandatory = $true)]
        [byte[]]$Bytes,

        [int]$MaxPayloadBytes = 1048576
    )

    if ($Bytes.Length -lt 12) {
        throw "SyncVision frame is shorter than the fixed header."
    }

    $magic = [Text.Encoding]::ASCII.GetString($Bytes, 0, 4)
    if ($magic -ne "SVP1") {
        throw "Unexpected SyncVision frame magic: $magic"
    }

    $version = [BitConverter]::ToUInt16($Bytes, 4)
    if ($version -ne 1) {
        throw "Unsupported SyncVision protocol version: $version"
    }

    $type = [BitConverter]::ToUInt16($Bytes, 6)
    $length = [BitConverter]::ToUInt32($Bytes, 8)
    if ($length -gt [UInt32]$MaxPayloadBytes) {
        throw "SyncVision frame payload length $length exceeds the maximum allowed $MaxPayloadBytes bytes."
    }
    if ($Bytes.Length -ne (12 + [int]$length)) {
        throw "SyncVision frame payload size does not match header."
    }

    $payload = New-Object byte[] ([int]$length)
    if ($payload.Length -gt 0) {
        [Array]::Copy($Bytes, 12, $payload, 0, $payload.Length)
    }

    return [pscustomobject]@{
        Type = $type
        PayloadBytes = $payload
        Payload = [Text.Encoding]::UTF8.GetString($payload)
    }
}

function Unprotect-SyncVisionEncryptedFramePayload {
    param(
        [Parameter(Mandatory = $true)]
        [byte[]]$EncryptedPayload,

        [Parameter(Mandatory = $true)]
        [string]$TransportSecret,

        [Parameter(Mandatory = $true)]
        [string]$Context
    )

    if ($EncryptedPayload.Length -lt 16) {
        throw "Invalid encrypted SyncVision payload."
    }
    if ([Text.Encoding]::ASCII.GetString($EncryptedPayload, 0, 4) -ne "SVE1") {
        throw "Invalid encrypted SyncVision payload."
    }

    $version = [BitConverter]::ToUInt16($EncryptedPayload, 4)
    $type = [BitConverter]::ToUInt16($EncryptedPayload, 6)
    $nonceSize = [BitConverter]::ToUInt16($EncryptedPayload, 8)
    $tagSize = [BitConverter]::ToUInt16($EncryptedPayload, 10)
    $ciphertextSize = [BitConverter]::ToUInt32($EncryptedPayload, 12)
    if ($version -ne 1 -or $nonceSize -ne 12 -or $tagSize -ne 16 -or $type -eq 14) {
        throw "Invalid encrypted SyncVision payload."
    }

    $expectedSize = 16 + [int]$nonceSize + [int]$tagSize + [int]$ciphertextSize
    if ($EncryptedPayload.Length -ne $expectedSize) {
        throw "Invalid encrypted SyncVision payload."
    }

    Add-SyncVisionAesGcmType

    $header = New-Object byte[] 16
    [Array]::Copy($EncryptedPayload, 0, $header, 0, $header.Length)
    $offset = 16
    $nonce = New-Object byte[] ([int]$nonceSize)
    [Array]::Copy($EncryptedPayload, $offset, $nonce, 0, $nonce.Length)
    $offset += $nonce.Length
    $tag = New-Object byte[] ([int]$tagSize)
    [Array]::Copy($EncryptedPayload, $offset, $tag, 0, $tag.Length)
    $offset += $tag.Length
    $ciphertext = New-Object byte[] ([int]$ciphertextSize)
    if ($ciphertext.Length -gt 0) {
        [Array]::Copy($EncryptedPayload, $offset, $ciphertext, 0, $ciphertext.Length)
    }

    $aad = Join-SyncVisionByteArrays -Arrays @(
        (ConvertTo-SyncVisionBytes -Text "syncvision.encrypted-frame.v1`n$Context`n"),
        $header
    )
    $key = Get-SyncVisionTransportKey -TransportSecret $TransportSecret -Context $Context
    $plaintext = [SyncVision.CngAesGcm]::Decrypt($key, $nonce, $aad, $tag, $ciphertext)

    return [pscustomobject]@{
        Type = $type
        PayloadBytes = $plaintext
        Payload = [Text.Encoding]::UTF8.GetString($plaintext)
    }
}

function New-SyncVisionTransportFrame {
    param(
        [UInt16]$Type,

        [Parameter(Mandatory = $true)]
        [byte[]]$Payload,

        [ValidateSet("disabled", "optional", "required")]
        [string]$TransportEncryption = "disabled",

        [AllowEmptyString()]
        [string]$TransportSecret = "",

        [Parameter(Mandatory = $true)]
        [string]$Context
    )

    if ($TransportEncryption -eq "disabled") {
        return New-SyncVisionFrame -Type $Type -Payload $Payload
    }

    $encryptedPayload = New-SyncVisionEncryptedFramePayload `
        -Type $Type `
        -Payload $Payload `
        -TransportSecret $TransportSecret `
        -Context $Context
    return New-SyncVisionFrame -Type 14 -Payload $encryptedPayload
}

function Unwrap-SyncVisionTransportFrame {
    param(
        [Parameter(Mandatory = $true)]
        $Frame,

        [ValidateSet("disabled", "optional", "required")]
        [string]$TransportEncryption = "disabled",

        [AllowEmptyString()]
        [string]$TransportSecret = "",

        [Parameter(Mandatory = $true)]
        [string]$Context
    )

    if ($Frame.Type -eq 14) {
        if ($TransportEncryption -eq "disabled") {
            throw "SyncVision transport encryption is disabled but received encrypted frame."
        }

        return Unprotect-SyncVisionEncryptedFramePayload `
            -EncryptedPayload $Frame.PayloadBytes `
            -TransportSecret $TransportSecret `
            -Context $Context
    }

    if ($TransportEncryption -eq "required") {
        throw "SyncVision transport encryption required but received plaintext frame."
    }

    return $Frame
}

function New-SyncVisionFrame {
    param(
        [UInt16]$Type,
        [byte[]]$Payload
    )

    $bytes = New-Object byte[] (12 + $Payload.Length)
    $bytes[0] = [byte][char]'S'
    $bytes[1] = [byte][char]'V'
    $bytes[2] = [byte][char]'P'
    $bytes[3] = [byte][char]'1'
    [BitConverter]::GetBytes([UInt16]1).CopyTo($bytes, 4)
    [BitConverter]::GetBytes($Type).CopyTo($bytes, 6)
    [BitConverter]::GetBytes([UInt32]$Payload.Length).CopyTo($bytes, 8)
    if ($Payload.Length -gt 0) {
        $Payload.CopyTo($bytes, 12)
    }

    return $bytes
}

function Read-SyncVisionExact {
    param(
        [Parameter(Mandatory = $true)]
        [System.Net.Sockets.NetworkStream]$Stream,

        [Parameter(Mandatory = $true)]
        [int]$Length
    )

    $buffer = New-Object byte[] $Length
    $offset = 0
    while ($offset -lt $Length) {
        $read = $Stream.Read($buffer, $offset, $Length - $offset)
        if ($read -le 0) {
            throw "Socket closed while reading $Length bytes."
        }
        $offset += $read
    }

    return $buffer
}

function Read-SyncVisionFrame {
    param(
        [Parameter(Mandatory = $true)]
        [System.Net.Sockets.TcpClient]$Client,

        [int]$MaxPayloadBytes = 1048576
    )

    $stream = $Client.GetStream()
    $header = Read-SyncVisionExact -Stream $stream -Length 12
    $magic = [Text.Encoding]::ASCII.GetString($header, 0, 4)
    if ($magic -ne "SVP1") {
        throw "Unexpected SyncVision frame magic: $magic"
    }

    $length = [BitConverter]::ToUInt32($header, 8)
    if ($length -gt [UInt32]$MaxPayloadBytes) {
        throw "SyncVision frame payload length $length exceeds the maximum allowed $MaxPayloadBytes bytes."
    }
    $payload = Read-SyncVisionExact -Stream $stream -Length ([int]$length)
    $bytes = Join-SyncVisionByteArrays -Arrays @($header, $payload)
    return ConvertFrom-SyncVisionFrameBytes -Bytes $bytes -MaxPayloadBytes $MaxPayloadBytes
}

function Read-SyncVisionStatus {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Endpoint,

        [Parameter(Mandatory = $true)]
        [string]$Token,

        [int]$TimeoutMs = 3000,

        [ValidateSet("disabled", "optional", "required")]
        [string]$TransportEncryption = "disabled",

        [AllowEmptyString()]
        [string]$TransportSecret = "",

        [AllowEmptyString()]
        [string]$TransportSecretFile = ""
    )

    $parsed = $Endpoint.LastIndexOf(":")
    if ($parsed -le 0 -or $parsed -eq $Endpoint.Length - 1) {
        throw "Status endpoint must use host:port."
    }

    $hostPart = $Endpoint.Substring(0, $parsed)
    $portPart = [int]$Endpoint.Substring($parsed + 1)
    $client = [System.Net.Sockets.TcpClient]::new()
    try {
        $connectTask = $client.ConnectAsync($hostPart, $portPart)
        if (-not $connectTask.Wait($TimeoutMs)) {
            throw "Timed out connecting to SyncVision server at $Endpoint."
        }

        $client.ReceiveTimeout = $TimeoutMs
        $client.SendTimeout = $TimeoutMs
        $resolvedTransportSecret = Resolve-SyncVisionStatusTransportSecret `
            -TransportSecret $TransportSecret `
            -TransportSecretFile $TransportSecretFile
        $payload = ConvertTo-SyncVisionBytes -Text (New-SyncVisionStatusRequestPayload -Token $Token)
        $frame = New-SyncVisionTransportFrame `
            -Type 11 `
            -Payload $payload `
            -TransportEncryption $TransportEncryption `
            -TransportSecret $resolvedTransportSecret `
            -Context "syncvision.transport.v1:client-to-server"
        $stream = $client.GetStream()
        $stream.Write($frame, 0, $frame.Length)
        $stream.Flush()

        $wireFrame = Read-SyncVisionFrame -Client $client
        return Unwrap-SyncVisionTransportFrame `
            -Frame $wireFrame `
            -TransportEncryption $TransportEncryption `
            -TransportSecret $resolvedTransportSecret `
            -Context "syncvision.transport.v1:server-to-client"
    }
    finally {
        $client.Close()
    }
}

if ($TestMode) {
    return
}

$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if (-not $service) {
    if (-not ($Probe -and $Server -and ($Token -or $TokenFile))) {
        Write-Host "Service '$ServiceName' was not found."
        exit 1
    }
}
else {
    Write-Host "Service: $ServiceName"
    Write-Host "Status: $($service.Status)"
    Write-Host "DisplayName: $($service.DisplayName)"
}

$binPath = Get-SyncVisionServiceBinPath -ServiceName $ServiceName
$paths = $null
if ($binPath) {
    Write-Host "binPath: $(Format-SyncVisionStatusBinPathForDisplay -BinPath $binPath)"
    $paths = Get-SyncVisionServicePathsFromBinPath -BinPath $binPath
    if ($paths.InstallPath) {
        Write-Host "InstallDir: $($paths.InstallPath)"
    }
    if ($paths.ConfigPath) {
        Write-Host "Config: $($paths.ConfigPath)"
    }
}

$configMap = $null
$configProbeEndpoint = ""
$configToken = ""
$configTransportEncryption = "disabled"
if ($paths -and $paths.ConfigPath -and (Test-Path -LiteralPath $paths.ConfigPath)) {
    $configMap = ConvertFrom-SyncVisionServerConfigText -Text ([IO.File]::ReadAllText($paths.ConfigPath))
    Write-Host "ConfigSummary:"
    Write-Host (Format-SyncVisionStatusConfigSummary -Config $configMap)
    if ($configMap.ContainsKey("listen")) {
        $configProbeEndpoint = Resolve-SyncVisionStatusEndpoint -Endpoint $configMap["listen"]
    }
    $configToken = Resolve-SyncVisionStatusToken -Config $configMap -ConfigPath $paths.ConfigPath
    if ($configMap.ContainsKey("transport_encryption") -and -not [string]::IsNullOrWhiteSpace($configMap["transport_encryption"])) {
        $configTransportEncryption = $configMap["transport_encryption"]
    }
}

if ($Probe) {
    $probeEndpoint = if ($Server) { $Server } else { $configProbeEndpoint }
    $probeToken = Resolve-SyncVisionStatusProbeToken -Token $Token -TokenFile $TokenFile -ConfigToken $configToken
    $probeTransportEncryption = if ($PSBoundParameters.ContainsKey("TransportEncryption")) { $TransportEncryption } else { $configTransportEncryption }
    $explicitTransportSecret = if ($PSBoundParameters.ContainsKey("TransportSecret")) { $TransportSecret } else { "" }
    $explicitTransportSecretFile = if ($PSBoundParameters.ContainsKey("TransportSecretFile")) { $TransportSecretFile } else { "" }
    $probeTransportConfig = if ($configMap) { $configMap } else { @{} }
    $probeTransportConfigPath = if ($paths -and $paths.ConfigPath) { $paths.ConfigPath } else { "" }
    $probeTransportSecret = Resolve-SyncVisionStatusTransportSecret `
        -TransportSecret $explicitTransportSecret `
        -TransportSecretFile $explicitTransportSecretFile `
        -Config $probeTransportConfig `
        -ConfigPath $probeTransportConfigPath
    if (-not $probeEndpoint) {
        throw "Status probe requires -Server or a service config containing listen."
    }
    if (-not $probeToken) {
        throw "Status probe requires -Token, -TokenFile, or a service config containing token_file/token."
    }

    $configuredEndpoint = if ($configMap -and $configMap.ContainsKey("listen")) { $configMap["listen"] } else { "" }
    $probeScope = Get-SyncVisionStatusProbeScope `
        -ConfiguredEndpoint $configuredEndpoint `
        -ProbeEndpoint $probeEndpoint `
        -ExplicitServer:((-not [string]::IsNullOrWhiteSpace($Server)))
    Assert-SyncVisionExpectedProbeScope -Actual $probeScope -Expected $ExpectProbeScope
    Write-Host (Format-SyncVisionStatusProbeScope `
            -Scope $probeScope `
            -ConfiguredEndpoint $configuredEndpoint `
            -ProbeEndpoint $probeEndpoint)

    $statusFrame = Read-SyncVisionStatus `
        -Endpoint $probeEndpoint `
        -Token $probeToken `
        -TimeoutMs $TimeoutMs `
        -TransportEncryption $probeTransportEncryption `
        -TransportSecret $probeTransportSecret
    if ($statusFrame.Type -eq 12) {
        Write-Host "LiveStatus:"
        Write-Host $statusFrame.Payload
    }
    elseif ($statusFrame.Type -eq 6) {
        throw "SyncVision server rejected status probe: $($statusFrame.Payload)"
    }
    else {
        throw "SyncVision server returned unexpected status frame type $($statusFrame.Type)."
    }
}
