deadbyte-mcp 0.15.74 → 0.15.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MANIFEST.SHA256 +108 -42
- package/PROVENANCE.json +20 -22
- package/README.txt +23 -18
- package/RELEASE.json +69 -18
- package/SBOM.cdx.json +2 -2
- package/TEST-MATRIX.json +32 -2
- package/bin/deadbyte-desktop-uia-r199-fixed.exe +0 -0
- package/bin/deadbyte-desktop-uia-r199-fixed.obj +0 -0
- package/bin/deadbyte-desktop-uia-r199.exe +0 -0
- package/bin/deadbyte-desktop-uia-r199.obj +0 -0
- package/bin/deadbyte-fs-read-r197-fixed.exe +0 -0
- package/bin/deadbyte-fs-read-r198.exe +0 -0
- package/bin/deadbyte-fs-read-r198.obj +0 -0
- package/bin/deadbyte-root-relative-probe-r197.exe +0 -0
- package/bridge/package.json +1 -1
- package/controller/deadbyte-process-policy.json +4 -4
- package/docs/R184-package-lock.json +2 -8
- package/native/deadbyte-desktop-uia-r199.cpp +345 -0
- package/native/deadbyte-fs-read-r197.cpp +174 -0
- package/native/deadbyte-fs-read-r198.cpp +181 -0
- package/native/deadbyte-root-relative-probe-r197.cpp +97 -0
- package/package.json +5 -2
- package/scripts/build-native-desktop-uia-r199-fixed.ps1 +28 -0
- package/scripts/build-native-desktop-uia-r199.ps1 +28 -0
- package/scripts/build-native-fs-read-r197-fixed.ps1 +28 -0
- package/scripts/build-native-fs-read-r197.ps1 +28 -0
- package/scripts/build-native-fs-read-r198.ps1 +28 -0
- package/scripts/build-native-root-probe-r197.ps1 +28 -0
- package/scripts/gate-windows-r195.ps1 +114 -0
- package/scripts/gate-windows-r206.ps1 +116 -0
- package/scripts/gate-windows-r207.ps1 +104 -0
- package/scripts/init-desktop-policy-r199.ps1 +85 -0
- package/scripts/npm-release-r48.mjs +27 -0
- package/scripts/npm-release-readiness-r195.mjs +72 -0
- package/scripts/npm-release-readiness-r206.mjs +76 -0
- package/scripts/npm-release-readiness-r207.mjs +76 -0
- package/scripts/r193-owner-request-live.mjs +8 -7
- package/scripts/r193-owner-uac-broker.mjs +6 -5
- package/scripts/r205-candidate-selection.mjs +22 -0
- package/src/candidate-selection-evidence-r206.mjs +71 -0
- package/src/candidate-selection-r205.mjs +96 -0
- package/src/desktop-postcondition-r196.mjs +30 -0
- package/src/desktop-runtime-r40.mjs +44 -7
- package/src/desktop-uia-identity-r199.mjs +51 -0
- package/src/desktop-uia-r40.mjs +9 -1
- package/src/machine-fs-handle-read-r196.mjs +43 -0
- package/src/machine-fs-native-read-r197.mjs +73 -0
- package/src/machine-fs-native-read-r198.mjs +76 -0
- package/src/machine-fs-read-worker.mjs +5 -25
- package/src/machine-fs.mjs +31 -16
- package/src/r195-canonical-owner-observation.mjs +15 -0
- package/src/r207-owner-enrollment-io.mjs +30 -0
- package/src/remote-destination-journal-r202.mjs +120 -0
- package/src/remote-device-r44.mjs +89 -14
- package/src/remote-payload-boundary-r201.mjs +71 -0
- package/src/remote-terminal-evidence-r200.mjs +60 -0
- package/src/version.mjs +1 -1
- package/test/desktop-runtime-r40.test.mjs +111 -0
- package/test/desktop-uia-r40.test.mjs +15 -0
- package/test/fixtures/r197-junction-swap-worker.mjs +21 -0
- package/test/fixtures/r203-journal-writer.mjs +6 -0
- package/test/process-policy-refresh.test.mjs +4 -4
- package/test/r130-release-security-contract.test.mjs +8 -8
- package/test/r132-release-identity.test.mjs +7 -7
- package/test/r153-prepublish-identity.test.mjs +1 -1
- package/test/r160-release-contract.test.mjs +3 -3
- package/test/r165-live-cli-skew.test.mjs +1 -1
- package/test/r167-release-contract.test.mjs +11 -11
- package/test/r168-release-contract.test.mjs +4 -4
- package/test/r172-release-contract.test.mjs +6 -6
- package/test/r173-release-contract.test.mjs +16 -16
- package/test/r179-release-contract.test.mjs +12 -12
- package/test/r190-release-contract.test.mjs +10 -10
- package/test/r191-release-contract.test.mjs +12 -12
- package/test/r192-release-identity.test.mjs +9 -9
- package/test/r193-release-identity.test.mjs +24 -22
- package/test/r193-release-readiness.test.mjs +2 -2
- package/test/r193-windows-gate.test.mjs +10 -10
- package/test/r194-release-identity.test.mjs +19 -15
- package/test/r194-release-readiness.test.mjs +3 -3
- package/test/r194-windows-gate.test.mjs +9 -8
- package/test/r195-canonical-owner-observation.test.mjs +32 -0
- package/test/r195-release-readiness.test.mjs +22 -0
- package/test/r196-desktop-postcondition.test.mjs +53 -0
- package/test/r196-handle-bound-read.test.mjs +99 -0
- package/test/r196-remote-outcome.test.mjs +94 -0
- package/test/r197-namespace-race.test.mjs +41 -0
- package/test/r197-native-dispatch-race.test.mjs +49 -0
- package/test/r197-native-file-read.test.mjs +60 -0
- package/test/r197-native-root-open.test.mjs +61 -0
- package/test/r198-root-identity.test.mjs +88 -0
- package/test/r199-native-uia-worker.test.mjs +28 -0
- package/test/r199-uia-identity.test.mjs +43 -0
- package/test/r200-remote-reconcile.test.mjs +106 -0
- package/test/r201-payload-boundary.test.mjs +78 -0
- package/test/r201-payload-fuzz.test.mjs +37 -0
- package/test/r201-tool-boundary-fuzz.test.mjs +120 -0
- package/test/r202-destination-journal.test.mjs +92 -0
- package/test/r203-atomic-journal.test.mjs +86 -0
- package/test/r205-candidate-selection-cli.test.mjs +31 -0
- package/test/r205-candidate-selection.test.mjs +83 -0
- package/test/r206-candidate-evidence.test.mjs +64 -0
- package/test/r206-release-contract.test.mjs +42 -0
- package/test/r206-release-readiness.test.mjs +23 -0
- package/test/r207-owner-enrollment-io.test.mjs +37 -0
- package/test/r207-release-contract.test.mjs +51 -0
- package/test/r207-release-readiness.test.mjs +23 -0
- package/test/r59-tool-surface-compat.test.mjs +1 -1
- package/test/r64-machine-fs-large-read.test.mjs +26 -12
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#requires -Version 5.1
|
|
2
|
+
[CmdletBinding()]
|
|
3
|
+
param([Parameter(Mandatory=$true)][ValidatePattern('^[0-9a-f]{64}$')][string]$SourceSha256)
|
|
4
|
+
Set-StrictMode -Version Latest
|
|
5
|
+
$ErrorActionPreference='Stop'
|
|
6
|
+
$repo=Split-Path -Parent $PSScriptRoot
|
|
7
|
+
$src=Join-Path $repo 'native\deadbyte-root-relative-probe-r197.cpp'
|
|
8
|
+
$actual=(Get-FileHash -LiteralPath $src -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
9
|
+
if($actual -cne $SourceSha256){throw 'R197_NATIVE_SOURCE_HASH_DRIFT'}
|
|
10
|
+
$vswhere='C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
|
|
11
|
+
if(!(Test-Path -LiteralPath $vswhere)){throw 'R197_MSVC_UNAVAILABLE'}
|
|
12
|
+
$install=(& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1)
|
|
13
|
+
if(!$install){throw 'R197_MSVC_TOOLCHAIN_MISSING'}
|
|
14
|
+
$dev=Join-Path $install 'Common7\Tools\VsDevCmd.bat'
|
|
15
|
+
$bin=Join-Path $repo 'bin'
|
|
16
|
+
$exe=Join-Path $bin 'deadbyte-root-relative-probe-r197.exe'
|
|
17
|
+
$obj=Join-Path $bin 'deadbyte-root-relative-probe-r197.obj'
|
|
18
|
+
if(Test-Path -LiteralPath $exe){throw 'R197_NATIVE_OUTPUT_EXISTS'}
|
|
19
|
+
if(Test-Path -LiteralPath $obj){throw 'R197_NATIVE_OBJECT_EXISTS'}
|
|
20
|
+
$common='/nologo /std:c++17 /permissive- /W4 /WX /O2 /MT /EHsc /guard:cf /diagnostics:caret /utf-8 /Brepro /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0A00'
|
|
21
|
+
$compile='cl {0} "{1}" /Fo:"{2}" /Fe:"{3}" /link /Brepro /INCREMENTAL:NO' -f $common,$src,$obj,$exe
|
|
22
|
+
$cmd=Join-Path $env:SystemRoot 'System32\cmd.exe'
|
|
23
|
+
$line='call "{0}" -no_logo -arch=x64 -host_arch=x64 && {1}' -f $dev,$compile
|
|
24
|
+
& $cmd /d /s /c $line
|
|
25
|
+
if($LASTEXITCODE -ne 0){throw ('R197_NATIVE_COMPILATION_FAIL exit='+$LASTEXITCODE)}
|
|
26
|
+
if(!(Test-Path -LiteralPath $exe -PathType Leaf)){throw 'R197_NATIVE_OUTPUT_MISSING'}
|
|
27
|
+
$hash=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
28
|
+
Write-Output ('R197_NATIVE_BUILD_PASS exe_sha256='+$hash)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#requires -Version 5.1
|
|
2
|
+
[CmdletBinding()]
|
|
3
|
+
param(
|
|
4
|
+
[ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight'
|
|
5
|
+
)
|
|
6
|
+
Set-StrictMode -Version Latest
|
|
7
|
+
$ErrorActionPreference='Stop'
|
|
8
|
+
$repo=Split-Path -Parent $PSScriptRoot
|
|
9
|
+
$productionState=Join-Path $env:USERPROFILE '.deadbyte-mcp'
|
|
10
|
+
$parentId='v0.15.74-e84bf4eed16e9443'
|
|
11
|
+
$parentSha='e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47'
|
|
12
|
+
$parentGen='598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7'
|
|
13
|
+
$parentTarball='5da436a3f8068107e74caf6da58ff1e211d4a62f94266853136b601762f36f0c'
|
|
14
|
+
$nativeNode='C:\Program Files\nodejs\node.exe'
|
|
15
|
+
$node=if(Test-Path -LiteralPath $nativeNode -PathType Leaf){$nativeNode}else{(Get-Command node -ErrorAction Stop).Source}
|
|
16
|
+
function Sha([string]$file){
|
|
17
|
+
$sha=[Security.Cryptography.SHA256]::Create()
|
|
18
|
+
try{$stream=[IO.File]::OpenRead($file);try{return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}finally{$stream.Dispose()}}finally{$sha.Dispose()}
|
|
19
|
+
}
|
|
20
|
+
function Need([bool]$condition,[string]$message){if(-not $condition){throw $message}}
|
|
21
|
+
function Run-Node([string]$label,[string[]]$nodeArgs){
|
|
22
|
+
Need ($null -ne $nodeArgs -and $nodeArgs.Count -gt 0) "R195_${label}_NO_NODE_ARGUMENTS"
|
|
23
|
+
Write-Output "R195_STAGE_START=$label"
|
|
24
|
+
$global:LASTEXITCODE=0
|
|
25
|
+
& $node @nodeArgs
|
|
26
|
+
$exit=$global:LASTEXITCODE
|
|
27
|
+
if($exit -ne 0){throw "R195_${label}_FAILED exit=$exit"}
|
|
28
|
+
Write-Output "R195_STAGE_PASS=$label"
|
|
29
|
+
}
|
|
30
|
+
Push-Location $repo
|
|
31
|
+
$previousExpectedDevelopmentRoot=$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT
|
|
32
|
+
try{
|
|
33
|
+
$pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
|
|
34
|
+
$release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
|
|
35
|
+
Need (-not [string]::IsNullOrWhiteSpace([string]$release.r195.development_policy_root)) 'R195_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
|
|
36
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r195.development_policy_root)
|
|
37
|
+
Need ($pkg.version -eq '0.15.75' -and $release.version -eq '0.15.75' -and $release.train -eq 'R195') 'R195_CANDIDATE_VERSION_DRIFT'
|
|
38
|
+
Need ($release.source_predecessor.version -eq '0.15.74' -and $release.source_predecessor.train -eq 'R194') 'R195_SOURCE_PREDECESSOR_VERSION_DRIFT'
|
|
39
|
+
Need ($release.source_predecessor.manifest_sha256 -eq $parentSha -and $release.source_predecessor.tarball_sha256 -eq $parentTarball) 'R195_SOURCE_PREDECESSOR_IDENTITY_DRIFT'
|
|
40
|
+
Need ($release.runtime_predecessor.release_id -eq $parentId -and $release.runtime_predecessor.manifest_sha256 -eq $parentSha -and $release.runtime_predecessor.generation_manifest_sha256 -eq $parentGen) 'R195_RUNTIME_PREDECESSOR_IDENTITY_DRIFT'
|
|
41
|
+
$active=Get-Content -LiteralPath (Join-Path $productionState 'active-release.json') -Raw | ConvertFrom-Json
|
|
42
|
+
Need ($active.version -eq '0.15.74' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R195_ACTIVE_RUNTIME_DRIFT'
|
|
43
|
+
Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R195_ACTIVE_MANIFEST_MISMATCH'
|
|
44
|
+
Write-Output 'R195_PREDECESSOR_PREFLIGHT=PASS'
|
|
45
|
+
if($Stage -eq 'preflight'){return}
|
|
46
|
+
if($Stage -in @('focused','all')){
|
|
47
|
+
$focused=@(
|
|
48
|
+
'test/r70-owner-approval.test.mjs',
|
|
49
|
+
'test/r89-privileged-install-boundary.test.mjs',
|
|
50
|
+
'test/r186-controller-owner-grant.test.mjs',
|
|
51
|
+
'test/r186-owner-consent-preflight.test.mjs',
|
|
52
|
+
'test/r186-owner-enrollment.test.mjs',
|
|
53
|
+
'test/r186-owner-grant-broker.test.mjs',
|
|
54
|
+
'test/r186-owner-local-signing.test.mjs',
|
|
55
|
+
'test/r186-owner-request.test.mjs',
|
|
56
|
+
'test/r186-owner-review-export.test.mjs',
|
|
57
|
+
'test/r188-owner-uac.test.mjs',
|
|
58
|
+
'test/r188-uac-boundary.test.mjs',
|
|
59
|
+
'test/r193-limited-migration-contract.test.mjs',
|
|
60
|
+
'test/r193-live-owner-subject.test.mjs',
|
|
61
|
+
'test/r193-native-process-observer.test.mjs',
|
|
62
|
+
'test/r193-native-token.test.mjs',
|
|
63
|
+
'test/r193-owner-enrollment-entrypoint.test.mjs',
|
|
64
|
+
'test/r193-owner-secret-acl.test.mjs',
|
|
65
|
+
'test/r193-owner-uac-broker.test.mjs',
|
|
66
|
+
'test/r193-owner-uac-entrypoint.test.mjs',
|
|
67
|
+
'test/r193-release-readiness.test.mjs',
|
|
68
|
+
'test/r193-release-identity.test.mjs',
|
|
69
|
+
'test/r194-release-identity.test.mjs',
|
|
70
|
+
'test/r194-release-readiness.test.mjs',
|
|
71
|
+
'test/r193-uac-r70-bridge.test.mjs',
|
|
72
|
+
'test/r194-windows-gate.test.mjs',
|
|
73
|
+
'test/r194-npm-auth-recovery.test.mjs',
|
|
74
|
+
'test/r194-npm-preauth.test.mjs'
|
|
75
|
+
'test/r195-canonical-owner-observation.test.mjs'
|
|
76
|
+
'test/r195-release-readiness.test.mjs'
|
|
77
|
+
)
|
|
78
|
+
Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
|
|
79
|
+
if($Stage -eq 'focused'){return}
|
|
80
|
+
}
|
|
81
|
+
if($Stage -in @('full','all')){
|
|
82
|
+
$previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
|
|
83
|
+
$tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
|
|
84
|
+
$scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
|
|
85
|
+
Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R195_CROSS_VOLUME_DRIVE_UNAVAILABLE'
|
|
86
|
+
$crossVolume=Join-Path $scratchDrive 'DEADBYTE-R195-CrossVolume'
|
|
87
|
+
try{
|
|
88
|
+
[IO.Directory]::CreateDirectory($crossVolume)|Out-Null
|
|
89
|
+
$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
|
|
90
|
+
Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
|
|
91
|
+
}finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
|
|
92
|
+
if($Stage -eq 'full'){return}
|
|
93
|
+
}
|
|
94
|
+
if($Stage -in @('manifest','all')){
|
|
95
|
+
Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
|
|
96
|
+
if($Stage -eq 'manifest'){return}
|
|
97
|
+
}
|
|
98
|
+
if($Stage -in @('doctor','all')){
|
|
99
|
+
$previousStateRoot=$env:DEADBYTE_STATE_ROOT
|
|
100
|
+
$isolated=Join-Path $env:TEMP ('deadbyte-r195-doctor-'+[guid]::NewGuid().ToString('N'))
|
|
101
|
+
try{
|
|
102
|
+
[IO.Directory]::CreateDirectory($isolated)|Out-Null
|
|
103
|
+
$env:DEADBYTE_STATE_ROOT=$isolated
|
|
104
|
+
Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
|
|
105
|
+
}finally{
|
|
106
|
+
$env:DEADBYTE_STATE_ROOT=$previousStateRoot
|
|
107
|
+
Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
Write-Output 'R195_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
|
|
111
|
+
}finally{
|
|
112
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
|
|
113
|
+
Pop-Location
|
|
114
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#requires -Version 5.1
|
|
2
|
+
[CmdletBinding()]
|
|
3
|
+
param(
|
|
4
|
+
[ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight'
|
|
5
|
+
)
|
|
6
|
+
Set-StrictMode -Version Latest
|
|
7
|
+
$ErrorActionPreference='Stop'
|
|
8
|
+
$repo=Split-Path -Parent $PSScriptRoot
|
|
9
|
+
$productionState=Join-Path $env:USERPROFILE '.deadbyte-mcp'
|
|
10
|
+
$parentId='v0.15.74-e84bf4eed16e9443'
|
|
11
|
+
$parentSha='e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47'
|
|
12
|
+
$parentGen='598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7'
|
|
13
|
+
$parentTarball='5da436a3f8068107e74caf6da58ff1e211d4a62f94266853136b601762f36f0c'
|
|
14
|
+
$nativeNode='C:\Program Files\nodejs\node.exe'
|
|
15
|
+
$node=if(Test-Path -LiteralPath $nativeNode -PathType Leaf){$nativeNode}else{(Get-Command node -ErrorAction Stop).Source}
|
|
16
|
+
function Sha([string]$file){
|
|
17
|
+
$sha=[Security.Cryptography.SHA256]::Create()
|
|
18
|
+
try{$stream=[IO.File]::OpenRead($file);try{return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}finally{$stream.Dispose()}}finally{$sha.Dispose()}
|
|
19
|
+
}
|
|
20
|
+
function Need([bool]$condition,[string]$message){if(-not $condition){throw $message}}
|
|
21
|
+
function Run-Node([string]$label,[string[]]$nodeArgs){
|
|
22
|
+
Need ($null -ne $nodeArgs -and $nodeArgs.Count -gt 0) "R206_${label}_NO_NODE_ARGUMENTS"
|
|
23
|
+
Write-Output "R206_STAGE_START=$label"
|
|
24
|
+
$global:LASTEXITCODE=0
|
|
25
|
+
& $node @nodeArgs
|
|
26
|
+
$exit=$global:LASTEXITCODE
|
|
27
|
+
if($exit -ne 0){throw "R206_${label}_FAILED exit=$exit"}
|
|
28
|
+
Write-Output "R206_STAGE_PASS=$label"
|
|
29
|
+
}
|
|
30
|
+
Push-Location $repo
|
|
31
|
+
$previousExpectedDevelopmentRoot=$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT
|
|
32
|
+
try{
|
|
33
|
+
$pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
|
|
34
|
+
$release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
|
|
35
|
+
Need (-not [string]::IsNullOrWhiteSpace([string]$release.r206.development_policy_root)) 'R206_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
|
|
36
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r206.development_policy_root)
|
|
37
|
+
Need ($pkg.version -eq '0.15.75' -and $release.version -eq '0.15.75' -and $release.train -eq 'R206') 'R206_CANDIDATE_VERSION_DRIFT'
|
|
38
|
+
Need ($release.source_predecessor.version -eq '0.15.75' -and $release.source_predecessor.train -eq 'R205') 'R206_SOURCE_PREDECESSOR_VERSION_DRIFT'
|
|
39
|
+
Need ($release.source_predecessor.manifest_sha256 -eq '166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92' -and $null -eq $release.source_predecessor.tarball_sha256) 'R206_SOURCE_PREDECESSOR_IDENTITY_DRIFT'
|
|
40
|
+
Need ($release.runtime_predecessor.release_id -eq $parentId -and $release.runtime_predecessor.manifest_sha256 -eq $parentSha -and $release.runtime_predecessor.generation_manifest_sha256 -eq $parentGen) 'R206_RUNTIME_PREDECESSOR_IDENTITY_DRIFT'
|
|
41
|
+
$active=Get-Content -LiteralPath (Join-Path $productionState 'active-release.json') -Raw | ConvertFrom-Json
|
|
42
|
+
Need ($active.version -eq '0.15.74' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R206_ACTIVE_RUNTIME_DRIFT'
|
|
43
|
+
Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R206_ACTIVE_MANIFEST_MISMATCH'
|
|
44
|
+
Write-Output 'R206_PREDECESSOR_PREFLIGHT=PASS'
|
|
45
|
+
if($Stage -eq 'preflight'){return}
|
|
46
|
+
if($Stage -in @('focused','all')){
|
|
47
|
+
$focused=@(
|
|
48
|
+
'test/r70-owner-approval.test.mjs',
|
|
49
|
+
'test/r89-privileged-install-boundary.test.mjs',
|
|
50
|
+
'test/r186-controller-owner-grant.test.mjs',
|
|
51
|
+
'test/r186-owner-consent-preflight.test.mjs',
|
|
52
|
+
'test/r186-owner-enrollment.test.mjs',
|
|
53
|
+
'test/r186-owner-grant-broker.test.mjs',
|
|
54
|
+
'test/r186-owner-local-signing.test.mjs',
|
|
55
|
+
'test/r186-owner-request.test.mjs',
|
|
56
|
+
'test/r186-owner-review-export.test.mjs',
|
|
57
|
+
'test/r188-owner-uac.test.mjs',
|
|
58
|
+
'test/r188-uac-boundary.test.mjs',
|
|
59
|
+
'test/r193-limited-migration-contract.test.mjs',
|
|
60
|
+
'test/r193-live-owner-subject.test.mjs',
|
|
61
|
+
'test/r193-native-process-observer.test.mjs',
|
|
62
|
+
'test/r193-native-token.test.mjs',
|
|
63
|
+
'test/r193-owner-enrollment-entrypoint.test.mjs',
|
|
64
|
+
'test/r193-owner-secret-acl.test.mjs',
|
|
65
|
+
'test/r193-owner-uac-broker.test.mjs',
|
|
66
|
+
'test/r193-owner-uac-entrypoint.test.mjs',
|
|
67
|
+
'test/r193-release-readiness.test.mjs',
|
|
68
|
+
'test/r193-release-identity.test.mjs',
|
|
69
|
+
'test/r194-release-identity.test.mjs',
|
|
70
|
+
'test/r194-release-readiness.test.mjs',
|
|
71
|
+
'test/r193-uac-r70-bridge.test.mjs',
|
|
72
|
+
'test/r194-windows-gate.test.mjs',
|
|
73
|
+
'test/r194-npm-auth-recovery.test.mjs',
|
|
74
|
+
'test/r194-npm-preauth.test.mjs'
|
|
75
|
+
'test/r195-canonical-owner-observation.test.mjs'
|
|
76
|
+
'test/r206-candidate-evidence.test.mjs'
|
|
77
|
+
'test/r206-release-contract.test.mjs'
|
|
78
|
+
'test/r206-release-readiness.test.mjs'
|
|
79
|
+
)
|
|
80
|
+
Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
|
|
81
|
+
if($Stage -eq 'focused'){return}
|
|
82
|
+
}
|
|
83
|
+
if($Stage -in @('full','all')){
|
|
84
|
+
$previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
|
|
85
|
+
$tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
|
|
86
|
+
$scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
|
|
87
|
+
Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R206_CROSS_VOLUME_DRIVE_UNAVAILABLE'
|
|
88
|
+
$crossVolume=Join-Path $scratchDrive 'DEADBYTE-R206-CrossVolume'
|
|
89
|
+
try{
|
|
90
|
+
[IO.Directory]::CreateDirectory($crossVolume)|Out-Null
|
|
91
|
+
$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
|
|
92
|
+
Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
|
|
93
|
+
}finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
|
|
94
|
+
if($Stage -eq 'full'){return}
|
|
95
|
+
}
|
|
96
|
+
if($Stage -in @('manifest','all')){
|
|
97
|
+
Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
|
|
98
|
+
if($Stage -eq 'manifest'){return}
|
|
99
|
+
}
|
|
100
|
+
if($Stage -in @('doctor','all')){
|
|
101
|
+
$previousStateRoot=$env:DEADBYTE_STATE_ROOT
|
|
102
|
+
$isolated=Join-Path $env:TEMP ('deadbyte-r206-doctor-'+[guid]::NewGuid().ToString('N'))
|
|
103
|
+
try{
|
|
104
|
+
[IO.Directory]::CreateDirectory($isolated)|Out-Null
|
|
105
|
+
$env:DEADBYTE_STATE_ROOT=$isolated
|
|
106
|
+
Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
|
|
107
|
+
}finally{
|
|
108
|
+
$env:DEADBYTE_STATE_ROOT=$previousStateRoot
|
|
109
|
+
Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
Write-Output 'R206_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
|
|
113
|
+
}finally{
|
|
114
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
|
|
115
|
+
Pop-Location
|
|
116
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#requires -Version 5.1
|
|
2
|
+
[CmdletBinding()]
|
|
3
|
+
param(
|
|
4
|
+
[ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight'
|
|
5
|
+
)
|
|
6
|
+
Set-StrictMode -Version Latest
|
|
7
|
+
$ErrorActionPreference='Stop'
|
|
8
|
+
$repo=Split-Path -Parent $PSScriptRoot
|
|
9
|
+
$productionState=Join-Path $env:USERPROFILE '.deadbyte-mcp'
|
|
10
|
+
$parentId='v0.15.75-9039fff265696091'
|
|
11
|
+
$parentSha='9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248'
|
|
12
|
+
$parentGen='83a212e01173c73f78cff2a6d26e6f3f50f476a8c0ea3cbbf592a466071909e9'
|
|
13
|
+
$parentTarball='c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9'
|
|
14
|
+
$nativeNode='C:\Program Files\nodejs\node.exe'
|
|
15
|
+
$node=if(Test-Path -LiteralPath $nativeNode -PathType Leaf){$nativeNode}else{(Get-Command node -ErrorAction Stop).Source}
|
|
16
|
+
function Sha([string]$file){
|
|
17
|
+
$sha=[Security.Cryptography.SHA256]::Create()
|
|
18
|
+
try{$stream=[IO.File]::OpenRead($file);try{return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}finally{$stream.Dispose()}}finally{$sha.Dispose()}
|
|
19
|
+
}
|
|
20
|
+
function Need([bool]$condition,[string]$message){if(-not $condition){throw $message}}
|
|
21
|
+
function Run-Node([string]$label,[string[]]$nodeArgs){
|
|
22
|
+
Need ($null -ne $nodeArgs -and $nodeArgs.Count -gt 0) "R207_${label}_NO_NODE_ARGUMENTS"
|
|
23
|
+
Write-Output "R207_STAGE_START=$label"
|
|
24
|
+
$global:LASTEXITCODE=0
|
|
25
|
+
& $node @nodeArgs
|
|
26
|
+
$exit=$global:LASTEXITCODE
|
|
27
|
+
if($exit -ne 0){throw "R207_${label}_FAILED exit=$exit"}
|
|
28
|
+
Write-Output "R207_STAGE_PASS=$label"
|
|
29
|
+
}
|
|
30
|
+
Push-Location $repo
|
|
31
|
+
$previousExpectedDevelopmentRoot=$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT
|
|
32
|
+
try{
|
|
33
|
+
$pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
|
|
34
|
+
$release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
|
|
35
|
+
Need (-not [string]::IsNullOrWhiteSpace([string]$release.r207.development_policy_root)) 'R207_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
|
|
36
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r207.development_policy_root)
|
|
37
|
+
Need ($pkg.version -eq '0.15.76' -and $release.version -eq '0.15.76' -and $release.train -eq 'R207') 'R207_CANDIDATE_VERSION_DRIFT'
|
|
38
|
+
Need ($release.source_predecessor.version -eq '0.15.75' -and $release.source_predecessor.train -eq 'R206') 'R207_SOURCE_PREDECESSOR_VERSION_DRIFT'
|
|
39
|
+
Need ($release.source_predecessor.manifest_sha256 -eq $parentSha -and $release.source_predecessor.tarball_sha256 -eq $parentTarball) 'R207_SOURCE_PREDECESSOR_IDENTITY_DRIFT'
|
|
40
|
+
Need ($release.runtime_predecessor.release_id -eq $parentId -and $release.runtime_predecessor.manifest_sha256 -eq $parentSha -and $release.runtime_predecessor.generation_manifest_sha256 -eq $parentGen) 'R207_RUNTIME_PREDECESSOR_IDENTITY_DRIFT'
|
|
41
|
+
$active=Get-Content -LiteralPath (Join-Path $productionState 'active-release.json') -Raw | ConvertFrom-Json
|
|
42
|
+
Need ($active.version -eq '0.15.75' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R207_ACTIVE_RUNTIME_DRIFT'
|
|
43
|
+
Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R207_ACTIVE_MANIFEST_MISMATCH'
|
|
44
|
+
Write-Output 'R207_PREDECESSOR_PREFLIGHT=PASS'
|
|
45
|
+
if($Stage -eq 'preflight'){return}
|
|
46
|
+
if($Stage -in @('focused','all')){
|
|
47
|
+
$focused=@(
|
|
48
|
+
'test/r70-owner-approval.test.mjs',
|
|
49
|
+
'test/r89-privileged-install-boundary.test.mjs',
|
|
50
|
+
'test/r186-controller-owner-grant.test.mjs',
|
|
51
|
+
'test/r186-owner-consent-preflight.test.mjs',
|
|
52
|
+
'test/r186-owner-enrollment.test.mjs',
|
|
53
|
+
'test/r186-owner-grant-broker.test.mjs',
|
|
54
|
+
'test/r186-owner-local-signing.test.mjs',
|
|
55
|
+
'test/r186-owner-request.test.mjs',
|
|
56
|
+
'test/r186-owner-review-export.test.mjs',
|
|
57
|
+
'test/r188-owner-uac.test.mjs',
|
|
58
|
+
'test/r188-uac-boundary.test.mjs',
|
|
59
|
+
'test/r193-live-owner-subject.test.mjs',
|
|
60
|
+
'test/r193-owner-enrollment-entrypoint.test.mjs',
|
|
61
|
+
'test/r193-owner-secret-acl.test.mjs',
|
|
62
|
+
'test/r193-owner-uac-broker.test.mjs',
|
|
63
|
+
'test/r193-owner-uac-entrypoint.test.mjs',
|
|
64
|
+
'test/r195-canonical-owner-observation.test.mjs',
|
|
65
|
+
'test/r207-owner-enrollment-io.test.mjs',
|
|
66
|
+
'test/r207-release-contract.test.mjs'
|
|
67
|
+
)
|
|
68
|
+
Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
|
|
69
|
+
if($Stage -eq 'focused'){return}
|
|
70
|
+
}
|
|
71
|
+
if($Stage -in @('full','all')){
|
|
72
|
+
$previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
|
|
73
|
+
$tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
|
|
74
|
+
$scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
|
|
75
|
+
Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R207_CROSS_VOLUME_DRIVE_UNAVAILABLE'
|
|
76
|
+
$crossVolume=Join-Path $scratchDrive 'DEADBYTE-R207-CrossVolume'
|
|
77
|
+
try{
|
|
78
|
+
[IO.Directory]::CreateDirectory($crossVolume)|Out-Null
|
|
79
|
+
$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
|
|
80
|
+
Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
|
|
81
|
+
}finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
|
|
82
|
+
if($Stage -eq 'full'){return}
|
|
83
|
+
}
|
|
84
|
+
if($Stage -in @('manifest','all')){
|
|
85
|
+
Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
|
|
86
|
+
if($Stage -eq 'manifest'){return}
|
|
87
|
+
}
|
|
88
|
+
if($Stage -in @('doctor','all')){
|
|
89
|
+
$previousStateRoot=$env:DEADBYTE_STATE_ROOT
|
|
90
|
+
$isolated=Join-Path $env:TEMP ('deadbyte-r207-doctor-'+[guid]::NewGuid().ToString('N'))
|
|
91
|
+
try{
|
|
92
|
+
[IO.Directory]::CreateDirectory($isolated)|Out-Null
|
|
93
|
+
$env:DEADBYTE_STATE_ROOT=$isolated
|
|
94
|
+
Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
|
|
95
|
+
}finally{
|
|
96
|
+
$env:DEADBYTE_STATE_ROOT=$previousStateRoot
|
|
97
|
+
Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
Write-Output 'R207_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
|
|
101
|
+
}finally{
|
|
102
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
|
|
103
|
+
Pop-Location
|
|
104
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
[CmdletBinding()]
|
|
2
|
+
param(
|
|
3
|
+
[string]$RuntimeRoot = '',
|
|
4
|
+
[string]$OutputPath = '',
|
|
5
|
+
[string[]]$AllowedActions = @('pointer_move','click_primary','click_secondary','double_click_primary','scroll','key_chord','text_input')
|
|
6
|
+
)
|
|
7
|
+
$ErrorActionPreference='Stop'
|
|
8
|
+
Set-StrictMode -Version Latest
|
|
9
|
+
function Get-Sha256Hex {
|
|
10
|
+
param([Parameter(Mandatory=$true)][string]$Path)
|
|
11
|
+
$Stream=[System.IO.File]::OpenRead([System.IO.Path]::GetFullPath($Path))
|
|
12
|
+
try{$Hasher=[System.Security.Cryptography.SHA256]::Create();try{return ([System.BitConverter]::ToString($Hasher.ComputeHash($Stream))).Replace('-','').ToLowerInvariant()}finally{$Hasher.Dispose()}}
|
|
13
|
+
finally{$Stream.Dispose()}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
$Root=Split-Path -Parent $PSScriptRoot
|
|
17
|
+
$Controller=Join-Path $Root 'controller'
|
|
18
|
+
if([string]::IsNullOrWhiteSpace($RuntimeRoot)){ $RuntimeRoot=Join-Path $Controller 'runtime' }
|
|
19
|
+
if([string]::IsNullOrWhiteSpace($OutputPath)){ $OutputPath=Join-Path $Controller 'deadbyte-desktop-policy.json' }
|
|
20
|
+
$RuntimeRoot=[System.IO.Path]::GetFullPath($RuntimeRoot)
|
|
21
|
+
$OutputPath=[System.IO.Path]::GetFullPath($OutputPath)
|
|
22
|
+
$Observer=[System.IO.Path]::GetFullPath((Join-Path $Root 'bin\deadbyte-desktop-observer-r40.exe'))
|
|
23
|
+
$Input=[System.IO.Path]::GetFullPath((Join-Path $Root 'bin\deadbyte-desktop-input-r40.exe'))
|
|
24
|
+
$Grounder=[System.IO.Path]::GetFullPath((Join-Path $Root 'bin\deadbyte-desktop-uia-r199-fixed.exe'))
|
|
25
|
+
if(-not (Test-Path -LiteralPath $Observer -PathType Leaf)){throw "observer binary missing: $Observer"}
|
|
26
|
+
if(-not (Test-Path -LiteralPath $Input -PathType Leaf)){throw "input binary missing: $Input"}
|
|
27
|
+
if(-not (Test-Path -LiteralPath $Grounder -PathType Leaf)){throw "UIA grounder binary missing: $Grounder"}
|
|
28
|
+
$Known=@('pointer_move','click_primary','click_secondary','double_click_primary','scroll','key_chord','text_input')
|
|
29
|
+
if($AllowedActions.Count -lt 1){throw 'AllowedActions cannot be empty'}
|
|
30
|
+
$Unique=@($AllowedActions | Sort-Object -Unique)
|
|
31
|
+
if($Unique.Count -ne $AllowedActions.Count -or @($AllowedActions | Where-Object { $_ -notin $Known }).Count -gt 0){throw 'AllowedActions invalid'}
|
|
32
|
+
New-Item -ItemType Directory -Force -Path $RuntimeRoot | Out-Null
|
|
33
|
+
$Evidence=Join-Path $RuntimeRoot 'desktop-evidence'
|
|
34
|
+
New-Item -ItemType Directory -Force -Path $Evidence | Out-Null
|
|
35
|
+
$Grant=Join-Path $RuntimeRoot 'desktop-grant.json'
|
|
36
|
+
Remove-Item -LiteralPath $Grant -Force -ErrorAction SilentlyContinue
|
|
37
|
+
$Policy=[ordered]@{
|
|
38
|
+
schema='deadbyte.desktop-policy.v1'
|
|
39
|
+
enabled=$true
|
|
40
|
+
grant_file=$Grant
|
|
41
|
+
evidence_dir=$Evidence
|
|
42
|
+
observer=[ordered]@{
|
|
43
|
+
executable=$Observer
|
|
44
|
+
sha256=Get-Sha256Hex -Path $Observer
|
|
45
|
+
backend='gdi-bitblt-fallback'
|
|
46
|
+
}
|
|
47
|
+
input=[ordered]@{
|
|
48
|
+
executable=$Input
|
|
49
|
+
sha256=Get-Sha256Hex -Path $Input
|
|
50
|
+
}
|
|
51
|
+
grounder=[ordered]@{
|
|
52
|
+
executable=$Grounder
|
|
53
|
+
sha256=Get-Sha256Hex -Path $Grounder
|
|
54
|
+
}
|
|
55
|
+
allowed_input_desktops=@('Default')
|
|
56
|
+
allowed_actions=@($AllowedActions)
|
|
57
|
+
limits=[ordered]@{
|
|
58
|
+
max_frame_age_ms=2000
|
|
59
|
+
max_frame_bytes=134217728
|
|
60
|
+
capture_timeout_ms=10000
|
|
61
|
+
input_timeout_ms=5000
|
|
62
|
+
ground_timeout_ms=5000
|
|
63
|
+
post_observe_timeout_ms=10000
|
|
64
|
+
max_preview_bytes=1048576
|
|
65
|
+
max_text_bytes=4096
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
$Parent=Split-Path -Parent $OutputPath
|
|
69
|
+
New-Item -ItemType Directory -Force -Path $Parent | Out-Null
|
|
70
|
+
$Json=$Policy | ConvertTo-Json -Depth 8
|
|
71
|
+
$Utf8=New-Object System.Text.UTF8Encoding($false)
|
|
72
|
+
$Tmp=$OutputPath+'.tmp'
|
|
73
|
+
[System.IO.File]::WriteAllText($Tmp,$Json,$Utf8)
|
|
74
|
+
Move-Item -LiteralPath $Tmp -Destination $OutputPath -Force
|
|
75
|
+
[pscustomobject]@{
|
|
76
|
+
status='created'
|
|
77
|
+
policy_path=$OutputPath
|
|
78
|
+
policy_sha256=Get-Sha256Hex -Path $OutputPath
|
|
79
|
+
observer_sha256=$Policy.observer.sha256
|
|
80
|
+
input_sha256=$Policy.input.sha256
|
|
81
|
+
grounder_sha256=$Policy.grounder.sha256
|
|
82
|
+
grant_file=$Grant
|
|
83
|
+
grant_state='DISARMED'
|
|
84
|
+
action_kinds=@($AllowedActions)
|
|
85
|
+
}|ConvertTo-Json -Depth 6
|
|
@@ -15,6 +15,9 @@ import {assertR167NpmPublishReady,assertR167PackedIdentity} from './npm-release-
|
|
|
15
15
|
import {assertR168NpmPublishReady,assertR168PackedIdentity} from './npm-release-readiness-r168.mjs';
|
|
16
16
|
import {assertR193NpmPublishReady,assertR193PackedIdentity} from './npm-release-readiness-r193.mjs';
|
|
17
17
|
import {assertR194NpmPublishReady,assertR194PackedIdentity} from './npm-release-readiness-r194.mjs';
|
|
18
|
+
import {assertR195NpmPublishReady,assertR195PackedIdentity} from './npm-release-readiness-r195.mjs';
|
|
19
|
+
import {assertR206NpmPublishReady,assertR206PackedIdentity} from './npm-release-readiness-r206.mjs';
|
|
20
|
+
import {assertR207NpmPublishReady,assertR207PackedIdentity} from './npm-release-readiness-r207.mjs';
|
|
18
21
|
import {resumePackRecord} from '../src/npm-publication-resume-r168.mjs';
|
|
19
22
|
import { existsSync,mkdtempSync,readdirSync,readFileSync,rmSync } from 'node:fs';
|
|
20
23
|
import { resolveStateRoot } from '../src/state-root.mjs';
|
|
@@ -157,6 +160,18 @@ async function main() {
|
|
|
157
160
|
if (!publishOnly) throw new Error('PUBLISH_BLOCKED R194 requires --publish-only; activation remains separately authorized');
|
|
158
161
|
r194Readiness=await assertR194NpmPublishReady(release,{root});
|
|
159
162
|
}
|
|
163
|
+
let r195Readiness=null;
|
|
164
|
+
let r206Readiness=null;
|
|
165
|
+
if (!isVerifyOnly && version==='0.15.75') {
|
|
166
|
+
if (!publishOnly) throw new Error('PUBLISH_BLOCKED R206 requires --publish-only; owner enrollment and activation remain separate');
|
|
167
|
+
if(release.train==='R206')r206Readiness=await assertR206NpmPublishReady(release,{root});
|
|
168
|
+
else r195Readiness=await assertR195NpmPublishReady(release,{root});
|
|
169
|
+
}
|
|
170
|
+
let r207Readiness=null;
|
|
171
|
+
if (!isVerifyOnly && version==='0.15.76') {
|
|
172
|
+
if (!publishOnly) throw new Error('PUBLISH_BLOCKED R207 requires --publish-only; owner enrollment and activation remain separate');
|
|
173
|
+
r207Readiness=await assertR207NpmPublishReady(release,{root});
|
|
174
|
+
}
|
|
160
175
|
if (release.parent?.release_id !== provenance.parent_release_id ||
|
|
161
176
|
release.parent?.manifest_sha256 !== provenance.parent_manifest_sha256 ||
|
|
162
177
|
release.parent?.generation_manifest_sha256 !== provenance.parent_generation_manifest_sha256) {
|
|
@@ -304,7 +319,19 @@ async function main() {
|
|
|
304
319
|
...r194Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
|
|
305
320
|
observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
|
|
306
321
|
});
|
|
322
|
+
if(r195Readiness)assertR195PackedIdentity({
|
|
323
|
+
...r195Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
|
|
324
|
+
observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
|
|
325
|
+
});
|
|
326
|
+
if(r206Readiness)assertR206PackedIdentity({
|
|
327
|
+
...r206Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
|
|
328
|
+
observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
|
|
329
|
+
});
|
|
307
330
|
|
|
331
|
+
if(r207Readiness)assertR207PackedIdentity({
|
|
332
|
+
...r207Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
|
|
333
|
+
observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
|
|
334
|
+
});
|
|
308
335
|
console.log('[6/7] Publishing artifact to npm registry...');
|
|
309
336
|
publishAttempted = true;
|
|
310
337
|
const ownerAuth=async subject=>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {createHash} from 'node:crypto';
|
|
2
|
+
import {lstat,readFile} from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
6
|
+
const hex64=value=>typeof value==='string'&&/^[0-9a-f]{64}$/.test(value);
|
|
7
|
+
const fail=message=>{throw new Error(`PUBLISH_BLOCKED R195 ${message}`);};
|
|
8
|
+
const required=(value,message)=>{if(!value)fail(message);};
|
|
9
|
+
|
|
10
|
+
async function checkedFile(file,expected,{maxBytes=64*1024*1024}={}){
|
|
11
|
+
required(hex64(expected),'evidence digest missing');
|
|
12
|
+
let info;try{info=await lstat(file);}catch{fail('evidence file absent');}
|
|
13
|
+
required(info.isFile()&&!info.isSymbolicLink()&&info.size>0&&info.size<=maxBytes,'evidence file invalid');
|
|
14
|
+
const bytes=await readFile(file);
|
|
15
|
+
required(sha256(bytes)===expected,'evidence digest differs');
|
|
16
|
+
return bytes;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function tapSummary(text,label){
|
|
20
|
+
const summaries=[...text.matchAll(/^# tests (\d+)\s*\r?\n# suites (\d+)\s*\r?\n# pass (\d+)\s*\r?\n# fail (\d+)\s*\r?\n# cancelled (\d+)\s*\r?\n# skipped (\d+)/gm)];
|
|
21
|
+
required(summaries.length>0,`${label} TAP summary absent`);
|
|
22
|
+
const last=summaries.at(-1);
|
|
23
|
+
return {tests:Number(last[1]),passes:Number(last[3]),fails:Number(last[4]),cancelled:Number(last[5]),skips:Number(last[6])};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function assertR195PackedIdentity({tarball_sha256,tarball_integrity,tarball_shasum,observedSha256,observedIntegrity,observedShasum}={}){
|
|
27
|
+
required(hex64(tarball_sha256)&&typeof tarball_integrity==='string'&&tarball_integrity.startsWith('sha512-')&&
|
|
28
|
+
typeof tarball_shasum==='string'&&/^[0-9a-f]{40}$/.test(tarball_shasum),'verified tarball identity invalid');
|
|
29
|
+
required(observedSha256===tarball_sha256&&observedIntegrity===tarball_integrity&&observedShasum===tarball_shasum,
|
|
30
|
+
'repacked tarball differs from verified closure bytes');
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function assertR195NpmPublishReady(release,{root,closureRoot=process.env.DEADBYTE_R195_CLOSURE_ROOT}={}){
|
|
35
|
+
required(release?.version==='0.15.75'&&release?.train==='R195'&&
|
|
36
|
+
release?.r195?.scope==='CANONICAL_PROTECTED_OWNER_OBSERVATION','candidate metadata invalid');
|
|
37
|
+
required(release?.r195?.public_tool_delta===0&&release?.r195?.authority_scope_delta===0,'public authority surface widened');
|
|
38
|
+
required(release?.parent?.version==='0.15.74'&&release?.parent?.release_id==='v0.15.74-e84bf4eed16e9443'&&
|
|
39
|
+
release?.parent?.manifest_sha256==='e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47'&&
|
|
40
|
+
release?.parent?.generation_manifest_sha256==='598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7','lineage mismatch');
|
|
41
|
+
required(root&&path.isAbsolute(root)&&closureRoot&&path.isAbsolute(closureRoot),'closure root absent');
|
|
42
|
+
const expected=path.resolve(root,'..','..','testing','r195-final-closure');
|
|
43
|
+
required(path.resolve(closureRoot).toLowerCase()===expected.toLowerCase(),'closure root outside scoped testing folder');
|
|
44
|
+
let closure;try{closure=JSON.parse(await readFile(path.join(closureRoot,'closure.json'),'utf8'));}catch{fail('closure unreadable');}
|
|
45
|
+
required(closure?.schema==='deadbyte.r195-release-closure.v1'&&closure.status==='RELEASE_READY'&&
|
|
46
|
+
closure.version==='0.15.75'&&closure.train==='R195','closure status mismatch');
|
|
47
|
+
required(closure.production_release_id===release.parent.release_id&&closure.production_manifest_sha256===release.parent.manifest_sha256&&
|
|
48
|
+
closure.production_generation_manifest_sha256===release.parent.generation_manifest_sha256,'production predecessor mismatch');
|
|
49
|
+
required(hex64(closure.manifest_sha256)&&closure.manifest_sha256===sha256(await readFile(path.join(root,'MANIFEST.SHA256'))),'final manifest drift');
|
|
50
|
+
required(closure.compact_tools===43&&closure.full_tools===117,'catalog count mismatch');
|
|
51
|
+
required(closure.owner_enrollment==='NOT_RUN'&&closure.production_activation==='NOT_RUN','prepublication closure crossed authority boundary');
|
|
52
|
+
const receipt=JSON.parse((await checkedFile(path.join(closureRoot,'protected-install-receipt.json'),closure.protected_receipt_sha256)).toString('utf8'));
|
|
53
|
+
required(receipt?.status==='PASS'&&receipt.package_version==='0.15.75'&&receipt.source_manifest_sha256===closure.manifest_sha256&&
|
|
54
|
+
receipt.protected_manifest_sha256===closure.manifest_sha256,'protected exact-byte receipt mismatch');
|
|
55
|
+
const focused=(await checkedFile(path.join(closureRoot,'windows-focused.stdout.log'),closure.focused_stdout_sha256)).toString('utf8');
|
|
56
|
+
const full=(await checkedFile(path.join(closureRoot,'windows-full.stdout.log'),closure.full_stdout_sha256)).toString('utf8');
|
|
57
|
+
const verify=(await checkedFile(path.join(closureRoot,'npm-verify.stdout.log'),closure.verify_stdout_sha256)).toString('utf8');
|
|
58
|
+
required(focused.includes('R195_STAGE_PASS=focused'),'focused protected gate incomplete');
|
|
59
|
+
const focusedSummary=tapSummary(focused,'focused');
|
|
60
|
+
required(focusedSummary.fails===0&&focusedSummary.cancelled===0&&focusedSummary.passes>=70&&focusedSummary.skips<=3,'focused regression count mismatch');
|
|
61
|
+
required(full.includes('R195_STAGE_PASS=full'),'full protected gate incomplete');
|
|
62
|
+
const summary=tapSummary(full,'full');
|
|
63
|
+
required(summary.tests>=2200&&summary.passes>=2100&&summary.fails===0&&summary.cancelled===0&&summary.skips<=70&&summary.passes+summary.skips===summary.tests,'full regression count mismatch');
|
|
64
|
+
required(verify.includes('VERIFY-ONLY PIPELINE PASS')&&verify.includes('Artifact isolation gate PASS')&&verify.includes('VERIFIED_TARBALL '),'npm exact-artifact verification incomplete');
|
|
65
|
+
const line=verify.split(/\r?\n/).find(value=>value.startsWith('VERIFIED_TARBALL '));
|
|
66
|
+
let artifact;try{artifact=JSON.parse(line.slice('VERIFIED_TARBALL '.length));}catch{fail('tarball evidence malformed');}
|
|
67
|
+
required(artifact.filename==='deadbyte-mcp-0.15.75.tgz'&&artifact.bytes>0&&artifact.sha256===closure.tarball_sha256&&
|
|
68
|
+
artifact.integrity===closure.tarball_integrity&&artifact.shasum===closure.tarball_shasum,'tarball identity mismatch');
|
|
69
|
+
return Object.freeze({status:'R195_RELEASE_READY_EVIDENCE_BOUND',manifest_sha256:closure.manifest_sha256,
|
|
70
|
+
tarball_sha256:artifact.sha256,tarball_integrity:artifact.integrity,tarball_shasum:artifact.shasum,
|
|
71
|
+
tests:summary.tests,passes:summary.passes,skips:summary.skips});
|
|
72
|
+
}
|