Cai
2026-08-14 85bbcb99dbd54f3fba3420832736670e9da60cc3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
 
function Invoke-AnaSemiL0StaticValidationV001 {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)][string]$ProjectRoot,
        [Parameter(Mandatory = $true)][string]$RunnerAssemblyPath,
        [Parameter(Mandatory = $true)][string]$ExpectedVectorsPath,
        [Parameter(Mandatory = $true)][string]$OutputPath
    )
 
    function Get-HexSha256Bytes([byte[]]$Bytes) {
        $sha = [Security.Cryptography.SHA256]::Create()
        try { return ([BitConverter]::ToString($sha.ComputeHash($Bytes)).Replace('-', '').ToLowerInvariant()) }
        finally { $sha.Dispose() }
    }
    function Get-HexSha256File([string]$Path) {
        $stream = [IO.File]::Open($Path, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::None)
        try {
            $sha = [Security.Cryptography.SHA256]::Create()
            try { return ([BitConverter]::ToString($sha.ComputeHash($stream)).Replace('-', '').ToLowerInvariant()) }
            finally { $sha.Dispose() }
        }
        finally { $stream.Dispose() }
    }
    function Escape-JsonString([string]$Value) {
        $builder = New-Object Text.StringBuilder
        [void]$builder.Append('"')
        foreach ($ch in $Value.ToCharArray()) {
            $code = [int][char]$ch
            switch ($code) {
                8 { [void]$builder.Append('\b'); continue }
                9 { [void]$builder.Append('\t'); continue }
                10 { [void]$builder.Append('\n'); continue }
                12 { [void]$builder.Append('\f'); continue }
                13 { [void]$builder.Append('\r'); continue }
                34 { [void]$builder.Append('\"'); continue }
                92 { [void]$builder.Append('\\'); continue }
            }
            if ($code -lt 32) { [void]$builder.Append(('\u{0:x4}' -f $code)) }
            else { [void]$builder.Append($ch) }
        }
        [void]$builder.Append('"')
        return $builder.ToString()
    }
    function ConvertTo-JcsValue($Value) {
        if ($null -eq $Value) { return 'null' }
        if ($Value -is [string]) { return (Escape-JsonString $Value) }
        if ($Value -is [bool]) { if ($Value) { return 'true' }; return 'false' }
        if ($Value -is [byte] -or $Value -is [sbyte] -or $Value -is [int16] -or $Value -is [uint16] -or
            $Value -is [int32] -or $Value -is [uint32] -or $Value -is [int64] -or $Value -is [uint64]) {
            return ([Convert]::ToString($Value, [Globalization.CultureInfo]::InvariantCulture))
        }
        if ($Value -is [Collections.IDictionary]) {
            $keys = @($Value.Keys | ForEach-Object { [string]$_ })
            [Array]::Sort($keys, [StringComparer]::Ordinal)
            $pairs = New-Object Collections.Generic.List[string]
            foreach ($key in $keys) { $pairs.Add((Escape-JsonString $key) + ':' + (ConvertTo-JcsValue $Value[$key])) }
            return '{' + [string]::Join(',', $pairs.ToArray()) + '}'
        }
        if ($Value -is [Collections.IEnumerable]) {
            $items = New-Object Collections.Generic.List[string]
            foreach ($item in $Value) { $items.Add((ConvertTo-JcsValue $item)) }
            return '[' + [string]::Join(',', $items.ToArray()) + ']'
        }
        $dictionary = [ordered]@{}
        foreach ($property in $Value.PSObject.Properties) { $dictionary[$property.Name] = $property.Value }
        return (ConvertTo-JcsValue $dictionary)
    }
    function Write-JcsCreateNew([string]$Path, $Value) {
        $text = ConvertTo-JcsValue $Value
        $bytes = (New-Object Text.UTF8Encoding($false)).GetBytes($text)
        $stream = New-Object IO.FileStream($Path, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
        try { $stream.Write($bytes, 0, $bytes.Length); $stream.Flush($true) }
        finally { $stream.Dispose() }
    }
    function Assert-TextCanonical([string]$Path, [bool]$RequireFinalLf) {
        $bytes = [IO.File]::ReadAllBytes($Path)
        if ($bytes.Length -ge 3 -and $bytes[0] -eq 239 -and $bytes[1] -eq 187 -and $bytes[2] -eq 191) { throw 'BOM' }
        if (@($bytes | Where-Object { $_ -eq 13 }).Count -ne 0) { throw 'CR' }
        if ($RequireFinalLf) {
            if ($bytes.Length -eq 0 -or $bytes[-1] -ne 10 -or ($bytes.Length -gt 1 -and $bytes[-2] -eq 10)) { throw 'LF' }
        }
        elseif ($bytes.Length -gt 0 -and $bytes[-1] -eq 10) { throw 'JSON_TRAILING_LF' }
        [void](New-Object Text.UTF8Encoding($false, $true)).GetString($bytes)
    }
    function New-Check([string]$Id, [string]$Expected, [string]$Actual, [string]$Result, $StopCode) {
        return [ordered]@{ check_id = $Id; expected = $Expected; actual = $Actual; result = $Result; stop_code = $StopCode }
    }
 
    $runId = 'RUN-DEV-ANA-SEMI-ROOT-PREFLIGHT-V007-IMPLEMENTATION-20260724-001'
    $checks = New-Object Collections.Generic.List[object]
    $spec = @(
        [pscustomobject]@{ Id = 'SOURCE_CANONICAL'; Stop = 'STOP_L0_SOURCE_CANONICAL_DRIFT'; Action = {
            $sourcePaths = @(
                'dev/ana-dev/AnaSemi.NativeProcessRunnerV006.cs',
                'dev/ana-dev/Invoke-AnaSemiWrapperSelftestV006.ps1',
                'dev/ana-dev/synthetic-child.ps1',
                'dev/ana-dev/test/Test-AnaSemiNativeProcessRunnerV006.Static.ps1',
                'dev/ana-dev/test/Test-InvokeAnaSemiWrapperSelftestV006.Static.ps1',
                'dev/ana-dev/test/V007ExpectedVectors.json',
                'dev/ana-dev/test/Invoke-AnaSemiImplementationValidationV001.ps1'
            )
            for ($index = 0; $index -lt $sourcePaths.Count; $index++) {
                Assert-TextCanonical -Path (Join-Path $ProjectRoot $sourcePaths[$index]) -RequireFinalLf ($index -ne 5)
            }
        }},
        [pscustomobject]@{ Id = 'CSC_EXIT'; Stop = 'STOP_L0_CSC_OR_PUBLISH_DRIFT'; Action = {
            if (-not (Test-Path -LiteralPath $RunnerAssemblyPath -PathType Leaf)) { throw 'ASSEMBLY_ABSENT' }
            $assemblyName = [Reflection.AssemblyName]::GetAssemblyName($RunnerAssemblyPath)
            if ($assemblyName.Name -cne 'AnaSemi.NativeProcessRunnerV006' -or $assemblyName.Version.ToString() -cne '1.0.0.0') { throw 'IDENTITY' }
        }},
        [pscustomobject]@{ Id = 'PUBLIC_API'; Stop = 'STOP_ASSEMBLY_PUBLIC_API_DRIFT'; Action = {
            $assembly = @([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -ceq 'AnaSemi.NativeProcessRunnerV006' })
            if ($assembly.Count -ne 1) { throw 'ASSEMBLY_COUNT' }
            $expectedTypes = @('AnaSemi.NativeProcessContractExceptionV006','AnaSemi.NativeProcessResultV006','AnaSemi.NativeProcessRunnerV006','AnaSemi.ProcessResultEnvelopeValidatorV006','AnaSemi.ProcessResultSidecarCsvV006','AnaSemi.WindowsCommandLineV006')
            $actualTypes = @($assembly[0].GetExportedTypes() | ForEach-Object { $_.FullName })
            [Array]::Sort($expectedTypes, [StringComparer]::Ordinal); [Array]::Sort($actualTypes, [StringComparer]::Ordinal)
            if ([string]::Join([char]0, $expectedTypes) -cne [string]::Join([char]0, $actualTypes)) { throw 'TYPE_SET' }
            $requiredMethods = @(
                'AnaSemi.WindowsCommandLineV006|QuoteAndJoin|System.String|System.String[]',
                'AnaSemi.WindowsCommandLineV006|Fingerprint|System.String|System.String[]',
                'AnaSemi.NativeProcessRunnerV006|Run|AnaSemi.NativeProcessResultV006|System.String,System.String[],System.String,System.String,System.Int32,System.Int32,System.String',
                'AnaSemi.ProcessResultEnvelopeValidatorV006|ValidateSingle|AnaSemi.NativeProcessResultV006|System.Object[]',
                'AnaSemi.ProcessResultSidecarCsvV006|WriteCreateNew|System.Void|AnaSemi.NativeProcessResultV006,System.String'
            )
            foreach ($signature in $requiredMethods) {
                $parts = $signature.Split('|')
                $type = $assembly[0].GetType($parts[0], $true, $false)
                $matches = @($type.GetMethods([Reflection.BindingFlags]'Public,Static,DeclaredOnly') | Where-Object {
                    $_.Name -ceq $parts[1] -and $_.ReturnType.FullName -ceq $parts[2] -and
                    [string]::Join(',', @($_.GetParameters() | ForEach-Object { $_.ParameterType.FullName })) -ceq $parts[3]
                })
                if ($matches.Count -ne 1) { throw ('METHOD:' + $signature) }
            }
        }},
        [pscustomobject]@{ Id = 'PROPERTY_22'; Stop = 'STOP_L0_PROPERTY_CONTRACT_DRIFT'; Action = {
            $type = @([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -ceq 'AnaSemi.NativeProcessRunnerV006' })[0].GetType('AnaSemi.NativeProcessResultV006', $true, $false)
            $properties = @($type.GetProperties([Reflection.BindingFlags]'Public,Instance') | Sort-Object MetadataToken)
            $names = @($properties | ForEach-Object { $_.Name })
            $expected = @('schema_id','process_kind','process_started','process_id','argv_count','argv_fingerprint','command_line_sha256','roundtrip_argv_fingerprint','started_at','finished_at','exit_code','timed_out','copy_state','child_liveness','stdout_path','stdout_bytes','stdout_sha256','stderr_path','stderr_bytes','stderr_sha256','result_contract_version','wrapper_status')
            if ($properties.Count -ne 22 -or [string]::Join([char]0, $names) -cne [string]::Join([char]0, $expected)) { throw 'PROPERTY_SET' }
            $preimage = 'ANA-SEMI-PROPERTY-SET-V005' + [char]0 + [string]::Join([char]0, $names)
            if ((Get-HexSha256Bytes ([Text.Encoding]::UTF8.GetBytes($preimage))) -cne '92c089153161a08a2327667befda342f4949ae6e2657eca51ad462a763614a2f') { throw 'PROPERTY_HASH' }
        }},
        [pscustomobject]@{ Id = 'POWERSHELL_AST'; Stop = 'STOP_L0_POWERSHELL_AST_DRIFT'; Action = {
            foreach ($relative in @('dev/ana-dev/Invoke-AnaSemiWrapperSelftestV006.ps1','dev/ana-dev/synthetic-child.ps1','dev/ana-dev/test/Test-AnaSemiNativeProcessRunnerV006.Static.ps1','dev/ana-dev/test/Test-InvokeAnaSemiWrapperSelftestV006.Static.ps1','dev/ana-dev/test/Invoke-AnaSemiImplementationValidationV001.ps1')) {
                $tokens = $null; $errors = $null
                [void][Management.Automation.Language.Parser]::ParseFile((Join-Path $ProjectRoot $relative), [ref]$tokens, [ref]$errors)
                if (@($errors).Count -ne 0) { throw ('PARSE:' + $relative) }
            }
        }},
        [pscustomobject]@{ Id = 'PROHIBITED_API'; Stop = 'STOP_L0_PROHIBITED_API'; Action = {
            foreach ($relative in @('dev/ana-dev/AnaSemi.NativeProcessRunnerV006.cs','dev/ana-dev/Invoke-AnaSemiWrapperSelftestV006.ps1','dev/ana-dev/synthetic-child.ps1')) {
                $text = [IO.File]::ReadAllText((Join-Path $ProjectRoot $relative), [Text.Encoding]::UTF8)
                foreach ($needle in @('Invoke-WebRequest','System.Net.Http','MySql','mysql_config_editor','MYSQL_PWD','Start-Process','cmd.exe','git clean','git reset','Add-Type')) {
                    if ($text.IndexOf($needle, [StringComparison]::OrdinalIgnoreCase) -ge 0) { throw ('PROHIBITED:' + $needle) }
                }
            }
        }},
        [pscustomobject]@{ Id = 'TOP_LEVEL_SIDE_EFFECT'; Stop = 'STOP_L0_TOP_LEVEL_SIDE_EFFECT'; Action = {
            $harness = [IO.File]::ReadAllText((Join-Path $ProjectRoot 'dev/ana-dev/Invoke-AnaSemiWrapperSelftestV006.ps1'), [Text.Encoding]::UTF8)
            $l0 = [IO.File]::ReadAllText((Join-Path $ProjectRoot 'dev/ana-dev/test/Test-AnaSemiNativeProcessRunnerV006.Static.ps1'), [Text.Encoding]::UTF8)
            $l1 = [IO.File]::ReadAllText((Join-Path $ProjectRoot 'dev/ana-dev/test/Test-InvokeAnaSemiWrapperSelftestV006.Static.ps1'), [Text.Encoding]::UTF8)
            if (($harness -split 'function Invoke-AnaSemiWrapperSelftestV006').Count -ne 2) { throw 'HARNESS_ENTRY' }
            if (($l0 -split 'function Invoke-AnaSemiL0StaticValidationV001').Count -ne 2) { throw 'L0_ENTRY' }
            if (($l1 -split 'function Invoke-AnaSemiL1ContractValidationV001').Count -ne 2) { throw 'L1_ENTRY' }
        }},
        [pscustomobject]@{ Id = 'EXPECTED_VECTOR_BINDING'; Stop = 'STOP_L0_EXPECTED_VECTOR_BINDING'; Action = {
            $vectors = [IO.File]::ReadAllText($ExpectedVectorsPath, [Text.Encoding]::UTF8) | ConvertFrom-Json
            if ($vectors.schema_id -cne 'ANA-SEMI-V007-EXPECTED-VECTORS-JCS-V001' -or
                $vectors.professional_design.id -cne 'DESIGN-ANA-SEMI-ROOT-IDENTITY-GRANT-PREFLIGHT-V007' -or
                [uint64]$vectors.professional_design.bytes -ne 279657 -or
                $vectors.professional_design.sha256 -cne '5906c63008a2366ebf9b3519df85b9e421e8f706fb916d1749c12af43f99a801' -or
                [uint16]$vectors.property_contract.property_count -ne 22 -or
                $vectors.property_contract.property_set_sha256 -cne '92c089153161a08a2327667befda342f4949ae6e2657eca51ad462a763614a2f' -or
                @($vectors.scenario_contract.rows).Count -ne 9 -or @($vectors.manifest_contract.rows).Count -ne 30) { throw 'VECTOR_BINDING' }
        }}
    )
 
    $firstFailure = $null
    foreach ($item in $spec) {
        if ($null -ne $firstFailure) {
            $checks.Add((New-Check $item.Id 'PASS' 'NOT_RUN_UPSTREAM_STOP' 'NOT_RUN' 'STOP_UPSTREAM_NOT_RUN'))
            continue
        }
        try {
            [void](& $item.Action)
            $checks.Add((New-Check $item.Id 'PASS' 'PASS' 'PASS' $null))
        }
        catch {
            $firstFailure = $item.Stop
            $checks.Add((New-Check $item.Id 'PASS' ('FAIL:' + $_.Exception.Message) 'FAIL' $firstFailure))
        }
    }
 
    $sourceHashes = [ordered]@{}
    for ($index = 1; $index -le 7; $index++) {
        $relative = @('dev/ana-dev/AnaSemi.NativeProcessRunnerV006.cs','dev/ana-dev/Invoke-AnaSemiWrapperSelftestV006.ps1','dev/ana-dev/synthetic-child.ps1','dev/ana-dev/test/Test-AnaSemiNativeProcessRunnerV006.Static.ps1','dev/ana-dev/test/Test-InvokeAnaSemiWrapperSelftestV006.Static.ps1','dev/ana-dev/test/V007ExpectedVectors.json','dev/ana-dev/test/Invoke-AnaSemiImplementationValidationV001.ps1')[$index - 1]
        $sourceHashes[('I{0:d2}' -f $index)] = Get-HexSha256File (Join-Path $ProjectRoot $relative)
    }
    $stagingPath = Join-Path (Split-Path (Split-Path $OutputPath -Parent) -Parent) 'staging/AnaSemi.NativeProcessRunnerV006.dll'
    $stagingInfo = Get-Item -LiteralPath $stagingPath
    $publishedInfo = Get-Item -LiteralPath $RunnerAssemblyPath
    $publishedHash = Get-HexSha256File $RunnerAssemblyPath
    $stagingHash = Get-HexSha256File $stagingPath
    $assembly = @([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -ceq 'AnaSemi.NativeProcessRunnerV006' })[0]
    $apiParts = @('ANA-SEMI-PUBLIC-API-V003',$assembly.FullName,'AnaSemi.NativeProcessResultV006','AnaSemi.NativeProcessContractExceptionV006','AnaSemi.WindowsCommandLineV006.QuoteAndJoin(System.String[])','AnaSemi.WindowsCommandLineV006.Fingerprint(System.String[])','AnaSemi.NativeProcessRunnerV006.Run(System.String,System.String[],System.String,System.String,System.Int32,System.Int32,System.String)','AnaSemi.ProcessResultEnvelopeValidatorV006.ValidateSingle(System.Object[])','AnaSemi.ProcessResultSidecarCsvV006.WriteCreateNew(AnaSemi.NativeProcessResultV006,System.String)')
    $apiParts += @('schema_id:System.String','process_kind:System.String','process_started:System.Boolean','process_id:System.Nullable`1[System.UInt32]','argv_count:System.UInt16','argv_fingerprint:System.String','command_line_sha256:System.String','roundtrip_argv_fingerprint:System.String','started_at:System.Nullable`1[System.DateTimeOffset]','finished_at:System.DateTimeOffset','exit_code:System.Nullable`1[System.Int32]','timed_out:System.Boolean','copy_state:System.String','child_liveness:System.String','stdout_path:System.String','stdout_bytes:System.UInt64','stdout_sha256:System.String','stderr_path:System.String','stderr_bytes:System.UInt64','stderr_sha256:System.String','result_contract_version:System.String','wrapper_status:System.String')
    $publicApiHash = Get-HexSha256Bytes ([Text.Encoding]::UTF8.GetBytes([string]::Join([char]0, $apiParts)))
    $passCount = @($checks | Where-Object { $_.result -ceq 'PASS' }).Count
    $failCount = @($checks | Where-Object { $_.result -ceq 'FAIL' }).Count
    $notRunCount = @($checks | Where-Object { $_.result -ceq 'NOT_RUN' }).Count
    $result = [ordered]@{
        assembly = [ordered]@{ full_name = $assembly.FullName; public_api_sha256 = $publicApiHash; published_bytes = [uint64]$publishedInfo.Length; published_path = $RunnerAssemblyPath; published_sha256 = $publishedHash; staging_bytes = [uint64]$stagingInfo.Length; staging_path = $stagingPath; staging_sha256 = $stagingHash }
        check_count = [uint16]8
        checks = $checks.ToArray()
        credential_count = [uint16]0
        database_count = [uint16]0
        external_process_count = [uint16]1
        fail_count = [uint16]$failCount
        network_count = [uint16]0
        not_run_count = [uint16]$notRunCount
        pass_count = [uint16]$passCount
        run_id = $runId
        schema_id = 'ANA-SEMI-IMPLEMENTATION-L0-JCS-V002'
        source_hashes = $sourceHashes
        status = if ($failCount -eq 0) { 'PASS' } else { 'FAIL' }
        terminal_stop_code = $firstFailure
        toolchain = [ordered]@{
            csc = [ordered]@{ bytes = [uint64]2569696; path = 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe'; sha256 = 'aae1db57f898ca8bda18590c56f86ced6d0ead80c22033b76fdfe9119706f116'; version = '4.8.9232.0 built by: NET481REL1LAST_C' }
            powershell = [ordered]@{ bytes = [uint64]455680; path = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'; sha256 = '9785001b0dcf755eddb8af294a373c0b87b2498660f724e76c4d53f9c217c7a3'; version = '10.0.19041.1 (WinBuild.160101.0800)' }
        }
    }
    Write-JcsCreateNew -Path $OutputPath -Value $result
    if ($null -ne $firstFailure) { throw $firstFailure }
}