deadbyte-mcp 0.15.72 → 0.15.75
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 +143 -35
- package/PROVENANCE.json +47 -21
- package/README.txt +29 -18
- package/RELEASE.json +85 -18
- package/SBOM.cdx.json +14 -2
- package/TEST-MATRIX.json +50 -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-owner-token-r193.exe +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-owner-token-r193.cpp +156 -0
- package/native/deadbyte-root-relative-probe-r197.cpp +97 -0
- package/package.json +4 -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-r193.ps1 +108 -0
- package/scripts/gate-windows-r194.ps1 +112 -0
- package/scripts/gate-windows-r195.ps1 +114 -0
- package/scripts/gate-windows-r206.ps1 +116 -0
- package/scripts/init-desktop-policy-r199.ps1 +85 -0
- package/scripts/npm-interactive-r194.mjs +13 -0
- package/scripts/npm-publication-r65.mjs +64 -4
- package/scripts/npm-release-r48.mjs +75 -11
- package/scripts/npm-release-readiness-r193.mjs +80 -0
- package/scripts/npm-release-readiness-r194.mjs +80 -0
- package/scripts/npm-release-readiness-r195.mjs +72 -0
- package/scripts/npm-release-readiness-r206.mjs +76 -0
- package/scripts/r188-owner-uac-review.ps1 +91 -0
- package/scripts/r188-uac-review-preview.mjs +65 -0
- package/scripts/r193-compile-token.ps1 +22 -0
- package/scripts/r193-evidence-relocate.ps1 +12 -0
- package/scripts/r193-focused-gate.mjs +20 -0
- package/scripts/r193-import-r188-scripts.ps1 +14 -0
- package/scripts/r193-limited-subject-probe.ps1 +25 -0
- package/scripts/r193-migrate-runtime-limited.ps1 +103 -0
- package/scripts/r193-owner-keygen.mjs +43 -0
- package/scripts/r193-owner-request-live.mjs +49 -0
- package/scripts/r193-owner-uac-approve.ps1 +42 -0
- package/scripts/r193-owner-uac-broker.mjs +139 -0
- package/scripts/r193-owner-uac-enroll-and-approve.ps1 +62 -0
- package/scripts/r193-test-limited-token.ps1 +49 -0
- package/scripts/r193-toolchain-inventory.ps1 +7 -0
- package/scripts/r193-uac-bridge-focused.mjs +21 -0
- 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/r188-owner-uac.mjs +105 -0
- package/src/r188-uac-boundary.mjs +21 -0
- package/src/r193-live-owner-subject.mjs +110 -0
- package/src/r193-owner-secret-acl.mjs +67 -0
- package/src/r193-owner-uac-broker.mjs +85 -0
- package/src/r193-uac-r70-bridge.mjs +54 -0
- package/src/r195-canonical-owner-observation.mjs +15 -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/r188-owner-uac.test.mjs +48 -0
- package/test/r188-uac-boundary.test.mjs +42 -0
- 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 +10 -10
- package/test/r193-limited-migration-contract.test.mjs +26 -0
- package/test/r193-live-owner-subject.test.mjs +61 -0
- package/test/r193-native-process-observer.test.mjs +36 -0
- package/test/r193-native-token.test.mjs +43 -0
- package/test/r193-owner-enrollment-entrypoint.test.mjs +38 -0
- package/test/r193-owner-secret-acl.test.mjs +23 -0
- package/test/r193-owner-uac-broker.test.mjs +82 -0
- package/test/r193-owner-uac-entrypoint.test.mjs +36 -0
- package/test/r193-release-identity.test.mjs +58 -0
- package/test/r193-release-readiness.test.mjs +87 -0
- package/test/r193-uac-r70-bridge.test.mjs +88 -0
- package/test/r193-windows-gate.test.mjs +30 -0
- package/test/r194-npm-auth-recovery.test.mjs +77 -0
- package/test/r194-npm-preauth.test.mjs +57 -0
- package/test/r194-release-identity.test.mjs +47 -0
- package/test/r194-release-readiness.test.mjs +87 -0
- package/test/r194-windows-gate.test.mjs +22 -0
- 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/r59-tool-surface-compat.test.mjs +1 -1
- package/test/r64-machine-fs-large-read.test.mjs +26 -12
|
@@ -0,0 +1,108 @@
|
|
|
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.72-0a5d9436e06e2d9e'
|
|
11
|
+
$parentSha='0a5d9436e06e2d9e7cf9179417465955d8ca5ba88655b13dd019190243c1cc90'
|
|
12
|
+
$parentGen='aec7b998306a3bbbcc59088648e7bc46ca7e203d749d4550b5b5f372032f92b0'
|
|
13
|
+
$parentTarball='15ab5d9808cbca342aee3f64c6d1123e8fbb72964674eab460e355c8675bf84d'
|
|
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) "R193_${label}_NO_NODE_ARGUMENTS"
|
|
23
|
+
Write-Output "R193_STAGE_START=$label"
|
|
24
|
+
$global:LASTEXITCODE=0
|
|
25
|
+
& $node @nodeArgs
|
|
26
|
+
$exit=$global:LASTEXITCODE
|
|
27
|
+
if($exit -ne 0){throw "R193_${label}_FAILED exit=$exit"}
|
|
28
|
+
Write-Output "R193_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.r192.development_policy_root)) 'R193_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
|
|
36
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r192.development_policy_root)
|
|
37
|
+
Need ($pkg.version -eq '0.15.73' -and $release.version -eq '0.15.73' -and $release.train -eq 'R193') 'R193_CANDIDATE_VERSION_DRIFT'
|
|
38
|
+
Need ($release.source_predecessor.version -eq '0.15.72' -and $release.source_predecessor.train -eq 'R192') 'R193_SOURCE_PREDECESSOR_VERSION_DRIFT'
|
|
39
|
+
Need ($release.source_predecessor.manifest_sha256 -eq $parentSha -and $release.source_predecessor.tarball_sha256 -eq $parentTarball) 'R193_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) 'R193_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.72' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R193_ACTIVE_RUNTIME_DRIFT'
|
|
43
|
+
Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R193_ACTIVE_MANIFEST_MISMATCH'
|
|
44
|
+
Write-Output 'R193_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/r193-uac-r70-bridge.test.mjs',
|
|
70
|
+
'test/r193-windows-gate.test.mjs'
|
|
71
|
+
)
|
|
72
|
+
Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
|
|
73
|
+
if($Stage -eq 'focused'){return}
|
|
74
|
+
}
|
|
75
|
+
if($Stage -in @('full','all')){
|
|
76
|
+
$previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
|
|
77
|
+
$tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
|
|
78
|
+
$scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
|
|
79
|
+
Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R193_CROSS_VOLUME_DRIVE_UNAVAILABLE'
|
|
80
|
+
$crossVolume=Join-Path $scratchDrive 'DEADBYTE-R193-CrossVolume'
|
|
81
|
+
try{
|
|
82
|
+
[IO.Directory]::CreateDirectory($crossVolume)|Out-Null
|
|
83
|
+
$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
|
|
84
|
+
Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
|
|
85
|
+
}finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
|
|
86
|
+
if($Stage -eq 'full'){return}
|
|
87
|
+
}
|
|
88
|
+
if($Stage -in @('manifest','all')){
|
|
89
|
+
Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
|
|
90
|
+
if($Stage -eq 'manifest'){return}
|
|
91
|
+
}
|
|
92
|
+
if($Stage -in @('doctor','all')){
|
|
93
|
+
$previousStateRoot=$env:DEADBYTE_STATE_ROOT
|
|
94
|
+
$isolated=Join-Path $env:TEMP ('deadbyte-r193-doctor-'+[guid]::NewGuid().ToString('N'))
|
|
95
|
+
try{
|
|
96
|
+
[IO.Directory]::CreateDirectory($isolated)|Out-Null
|
|
97
|
+
$env:DEADBYTE_STATE_ROOT=$isolated
|
|
98
|
+
Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
|
|
99
|
+
}finally{
|
|
100
|
+
$env:DEADBYTE_STATE_ROOT=$previousStateRoot
|
|
101
|
+
Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
Write-Output 'R193_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
|
|
105
|
+
}finally{
|
|
106
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
|
|
107
|
+
Pop-Location
|
|
108
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
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.72-0a5d9436e06e2d9e'
|
|
11
|
+
$parentSha='0a5d9436e06e2d9e7cf9179417465955d8ca5ba88655b13dd019190243c1cc90'
|
|
12
|
+
$parentGen='aec7b998306a3bbbcc59088648e7bc46ca7e203d749d4550b5b5f372032f92b0'
|
|
13
|
+
$parentTarball='15ab5d9808cbca342aee3f64c6d1123e8fbb72964674eab460e355c8675bf84d'
|
|
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) "R194_${label}_NO_NODE_ARGUMENTS"
|
|
23
|
+
Write-Output "R194_STAGE_START=$label"
|
|
24
|
+
$global:LASTEXITCODE=0
|
|
25
|
+
& $node @nodeArgs
|
|
26
|
+
$exit=$global:LASTEXITCODE
|
|
27
|
+
if($exit -ne 0){throw "R194_${label}_FAILED exit=$exit"}
|
|
28
|
+
Write-Output "R194_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.r194.development_policy_root)) 'R194_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
|
|
36
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r194.development_policy_root)
|
|
37
|
+
Need ($pkg.version -eq '0.15.74' -and $release.version -eq '0.15.74' -and $release.train -eq 'R194') 'R194_CANDIDATE_VERSION_DRIFT'
|
|
38
|
+
Need ($release.source_predecessor.version -eq '0.15.73' -and $release.source_predecessor.train -eq 'R193') 'R194_SOURCE_PREDECESSOR_VERSION_DRIFT'
|
|
39
|
+
Need ($release.source_predecessor.manifest_sha256 -eq 'e0b3f8b333f1c1260a97b178d1a8beff5742355296a9fe7daba378612604a3bd' -and $release.source_predecessor.tarball_sha256 -eq '13c3dd23a535609aa53173b328c7d9299d5dcada684f3253a88af6a4b300c534') 'R194_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) 'R194_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.72' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R194_ACTIVE_RUNTIME_DRIFT'
|
|
43
|
+
Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R194_ACTIVE_MANIFEST_MISMATCH'
|
|
44
|
+
Write-Output 'R194_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
|
+
)
|
|
76
|
+
Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
|
|
77
|
+
if($Stage -eq 'focused'){return}
|
|
78
|
+
}
|
|
79
|
+
if($Stage -in @('full','all')){
|
|
80
|
+
$previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
|
|
81
|
+
$tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
|
|
82
|
+
$scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
|
|
83
|
+
Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R194_CROSS_VOLUME_DRIVE_UNAVAILABLE'
|
|
84
|
+
$crossVolume=Join-Path $scratchDrive 'DEADBYTE-R194-CrossVolume'
|
|
85
|
+
try{
|
|
86
|
+
[IO.Directory]::CreateDirectory($crossVolume)|Out-Null
|
|
87
|
+
$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
|
|
88
|
+
Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
|
|
89
|
+
}finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
|
|
90
|
+
if($Stage -eq 'full'){return}
|
|
91
|
+
}
|
|
92
|
+
if($Stage -in @('manifest','all')){
|
|
93
|
+
Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
|
|
94
|
+
if($Stage -eq 'manifest'){return}
|
|
95
|
+
}
|
|
96
|
+
if($Stage -in @('doctor','all')){
|
|
97
|
+
$previousStateRoot=$env:DEADBYTE_STATE_ROOT
|
|
98
|
+
$isolated=Join-Path $env:TEMP ('deadbyte-r194-doctor-'+[guid]::NewGuid().ToString('N'))
|
|
99
|
+
try{
|
|
100
|
+
[IO.Directory]::CreateDirectory($isolated)|Out-Null
|
|
101
|
+
$env:DEADBYTE_STATE_ROOT=$isolated
|
|
102
|
+
Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
|
|
103
|
+
}finally{
|
|
104
|
+
$env:DEADBYTE_STATE_ROOT=$previousStateRoot
|
|
105
|
+
Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
Write-Output 'R194_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
|
|
109
|
+
}finally{
|
|
110
|
+
$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
|
|
111
|
+
Pop-Location
|
|
112
|
+
}
|
|
@@ -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,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
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// R194 publication failure boundary: do not infer auth failure from a generic 404.
|
|
2
|
+
// Only an explicit npm auth code, or the exact npm registry PUT permission refusal,
|
|
3
|
+
// can be treated as a definitively rejected submission.
|
|
4
|
+
const AUTH_CODE = /(?:^|\s)(?:E401|E403|EOTP|ENEEDAUTH|EAUTH)(?:\s|$)/i;
|
|
5
|
+
const PERMISSION = /(?:you do not have permission to access it|you (?:don't|do not) have permission to publish|permission denied|forbidden|not authorized)/i;
|
|
6
|
+
const REGISTRY_PUT = /\b404\s+Not\s+Found\s+-\s+PUT\s+https:\/\/registry\.npmjs\.org\/deadbyte-mcp(?:\s|\?|\b)/i;
|
|
7
|
+
export function classifyNpmPublishFailure({exitCode,output}={}){
|
|
8
|
+
if(exitCode===0)return 'SUBMISSION_ACCEPTED';
|
|
9
|
+
const text=typeof output==='string'?output.slice(-65536):'';
|
|
10
|
+
if(AUTH_CODE.test(text))return 'EAUTH';
|
|
11
|
+
if(REGISTRY_PUT.test(text)&&PERMISSION.test(text))return 'EAUTH';
|
|
12
|
+
return 'OUTCOME_UNKNOWN';
|
|
13
|
+
}
|
|
@@ -55,7 +55,7 @@ function result(state,extra={}){return Object.freeze({state,...extra});}
|
|
|
55
55
|
// The no-clobber claim is the dispatch fence: once it exists, no invocation may
|
|
56
56
|
// submit the same immutable npm version again, even if the first process dies.
|
|
57
57
|
export async function reconcileNpmPublication({recordPath,version,manifestSha256,localBytes,publish,lookup,tags,fetchTarball,
|
|
58
|
-
timeoutMs=180000,pollMs=1500,sleep=pause,now=()=>performance.now()}){
|
|
58
|
+
timeoutMs=180000,pollMs=1500,sleep=pause,now=()=>performance.now(),authorizeAuthRetry=null,authorizePublish=null}){
|
|
59
59
|
if(!path.isAbsolute(recordPath)||!/^\d+\.\d+\.\d+$/.test(version)||!HEX64.test(String(manifestSha256))||!Buffer.isBuffer(localBytes)||
|
|
60
60
|
!Number.isSafeInteger(timeoutMs)||timeoutMs<0||timeoutMs>900000||!Number.isSafeInteger(pollMs)||pollMs<1||pollMs>30000||
|
|
61
61
|
[publish,lookup,tags,fetchTarball,sleep,now].some(fn=>typeof fn!=='function'))throw new Error('npm publication reconciliation inputs invalid');
|
|
@@ -97,6 +97,14 @@ export async function reconcileNpmPublication({recordPath,version,manifestSha256
|
|
|
97
97
|
}
|
|
98
98
|
if(!claim){
|
|
99
99
|
if(observed)return observed; // Registry outage: do not submit while identity is unknown.
|
|
100
|
+
// R194: check authenticated package ownership before creating the irreversible claim.
|
|
101
|
+
if(authorizePublish!==null){
|
|
102
|
+
if(typeof authorizePublish!=='function')throw new Error('npm owner preflight invalid');
|
|
103
|
+
let authorized=false;
|
|
104
|
+
try{authorized=(await authorizePublish(Object.freeze({version,manifest_sha256:manifestSha256,tarball_sha256:tarballSha256})))===true;}
|
|
105
|
+
catch{return result('AUTH_REQUIRED',{reason:'owner authentication preflight failed before submission'});}
|
|
106
|
+
if(!authorized)return result('AUTH_REQUIRED',{reason:'owner authentication preflight is not confirmed'});
|
|
107
|
+
}
|
|
100
108
|
let created=false;
|
|
101
109
|
try{
|
|
102
110
|
await publishClaim(claimFile,{schema:'deadbyte.npm-publication-claim.r65.v1',version,manifest_sha256:manifestSha256,tarball_sha256:tarballSha256,created_at_utc:new Date().toISOString()});
|
|
@@ -114,15 +122,67 @@ export async function reconcileNpmPublication({recordPath,version,manifestSha256
|
|
|
114
122
|
await publish();
|
|
115
123
|
await event(recordPath,'SUBMISSION_ACCEPTED',{tarball_sha256:tarballSha256});
|
|
116
124
|
}catch(error){
|
|
117
|
-
const auth=/E401|E403|EOTP|authentication|one-time password|2FA/i.test(String(error?.code??'')+' '+String(error?.message??''));
|
|
125
|
+
const auth=/E401|E403|EOTP|EAUTH|ENEEDAUTH|authentication|one-time password|2FA/i.test(String(error?.code??'')+' '+String(error?.message??''));
|
|
118
126
|
await event(recordPath,auth?'AUTH_REQUIRED':'OUTCOME_UNKNOWN',{error_code:String(error?.code??'UNKNOWN').slice(0,64)});
|
|
119
127
|
return result(auth?'AUTH_REQUIRED':'OUTCOME_UNKNOWN',{reason:String(error?.code??error?.message??error)});
|
|
120
128
|
}
|
|
121
129
|
}
|
|
122
130
|
}
|
|
123
131
|
const states=await priorState(recordPath);
|
|
124
|
-
|
|
125
|
-
|
|
132
|
+
const authRejected=states.some(item=>item.state==='AUTH_REQUIRED');
|
|
133
|
+
let accepted=states.some(item=>item.state==='SUBMISSION_ACCEPTED');
|
|
134
|
+
if(authRejected&&!accepted){
|
|
135
|
+
// An original ambiguous outcome cannot become retryable via a later login.
|
|
136
|
+
if(states.some(item=>item.state==='OUTCOME_UNKNOWN'))
|
|
137
|
+
return result('OUTCOME_UNKNOWN',{reason:'submission outcome is ambiguous; original claim retained'});
|
|
138
|
+
const retryFile=path.join(recordPath,'auth-retry-claim.json');
|
|
139
|
+
const retry=await readClaim(retryFile);
|
|
140
|
+
if(retry?.incomplete)return result('OUTCOME_UNKNOWN',{reason:'incomplete auth retry claim'});
|
|
141
|
+
if(retry){
|
|
142
|
+
if(retry.schema!=='deadbyte.npm-auth-retry-claim.r194.v1'||retry.version!==version||
|
|
143
|
+
retry.manifest_sha256!==manifestSha256||retry.tarball_sha256!==tarballSha256)
|
|
144
|
+
return result('REGISTRY_REJECTED',{reason:'auth retry claim artifact mismatch'});
|
|
145
|
+
return result('AUTH_REQUIRED',{reason:'one-time auth retry was already dispatched or claimed; do not retry'});
|
|
146
|
+
}
|
|
147
|
+
if(typeof authorizeAuthRetry!=='function')return result('AUTH_REQUIRED');
|
|
148
|
+
let allowed=false;
|
|
149
|
+
try{
|
|
150
|
+
allowed=(await authorizeAuthRetry(Object.freeze({
|
|
151
|
+
version,manifest_sha256:manifestSha256,tarball_sha256:tarballSha256
|
|
152
|
+
})))===true;
|
|
153
|
+
}catch{return result('AUTH_REQUIRED',{reason:'fresh authenticated owner check failed'});}
|
|
154
|
+
if(!allowed)return result('AUTH_REQUIRED',{reason:'authenticated owner preflight not confirmed'});
|
|
155
|
+
// Re-read registry just before the one-time retry fence.
|
|
156
|
+
const beforeRetry=await check();
|
|
157
|
+
if(beforeRetry?.state==='REGISTRY_IDENTITY_VERIFIED'||beforeRetry?.state==='REGISTRY_REJECTED')return beforeRetry;
|
|
158
|
+
if(beforeRetry?.state==='OUTCOME_UNKNOWN')return beforeRetry;
|
|
159
|
+
try{
|
|
160
|
+
await writeExclusive(retryFile,{
|
|
161
|
+
schema:'deadbyte.npm-auth-retry-claim.r194.v1',version,
|
|
162
|
+
manifest_sha256:manifestSha256,tarball_sha256:tarballSha256,
|
|
163
|
+
created_at_utc:new Date().toISOString()
|
|
164
|
+
});
|
|
165
|
+
}catch(error){
|
|
166
|
+
if(error?.code==='EEXIST')return result('AUTH_REQUIRED',{reason:'concurrent auth retry already claimed; do not dispatch'});
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
// A durable retry claim is written BEFORE any additional network effect.
|
|
170
|
+
await event(recordPath,'AUTH_RETRY_STARTED',{tarball_sha256:tarballSha256});
|
|
171
|
+
try{
|
|
172
|
+
await publish();
|
|
173
|
+
await event(recordPath,'SUBMISSION_ACCEPTED',{tarball_sha256:tarballSha256,retry:'auth-only'});
|
|
174
|
+
accepted=true;
|
|
175
|
+
}catch(error){
|
|
176
|
+
const auth=/E401|E403|EOTP|EAUTH|ENEEDAUTH|authentication|one-time password|2FA/i.test(
|
|
177
|
+
String(error?.code??'')+' '+String(error?.message??''));
|
|
178
|
+
await event(recordPath,auth?'AUTH_REQUIRED':'OUTCOME_UNKNOWN',{
|
|
179
|
+
error_code:String(error?.code??'UNKNOWN').slice(0,64),retry:'auth-only'
|
|
180
|
+
});
|
|
181
|
+
return result(auth?'AUTH_REQUIRED':'OUTCOME_UNKNOWN',{
|
|
182
|
+
reason:'one-time auth retry rejected or unverified; retry claim retained'
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
126
186
|
const started=now();
|
|
127
187
|
do{
|
|
128
188
|
observed=await check();
|