deadbyte-mcp 0.15.74 → 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.
Files changed (103) hide show
  1. package/MANIFEST.SHA256 +102 -42
  2. package/PROVENANCE.json +19 -21
  3. package/README.txt +23 -18
  4. package/RELEASE.json +51 -18
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +22 -2
  7. package/bin/deadbyte-desktop-uia-r199-fixed.exe +0 -0
  8. package/bin/deadbyte-desktop-uia-r199-fixed.obj +0 -0
  9. package/bin/deadbyte-desktop-uia-r199.exe +0 -0
  10. package/bin/deadbyte-desktop-uia-r199.obj +0 -0
  11. package/bin/deadbyte-fs-read-r197-fixed.exe +0 -0
  12. package/bin/deadbyte-fs-read-r198.exe +0 -0
  13. package/bin/deadbyte-fs-read-r198.obj +0 -0
  14. package/bin/deadbyte-root-relative-probe-r197.exe +0 -0
  15. package/bridge/package.json +1 -1
  16. package/controller/deadbyte-process-policy.json +4 -4
  17. package/docs/R184-package-lock.json +2 -8
  18. package/native/deadbyte-desktop-uia-r199.cpp +345 -0
  19. package/native/deadbyte-fs-read-r197.cpp +174 -0
  20. package/native/deadbyte-fs-read-r198.cpp +181 -0
  21. package/native/deadbyte-root-relative-probe-r197.cpp +97 -0
  22. package/package.json +4 -2
  23. package/scripts/build-native-desktop-uia-r199-fixed.ps1 +28 -0
  24. package/scripts/build-native-desktop-uia-r199.ps1 +28 -0
  25. package/scripts/build-native-fs-read-r197-fixed.ps1 +28 -0
  26. package/scripts/build-native-fs-read-r197.ps1 +28 -0
  27. package/scripts/build-native-fs-read-r198.ps1 +28 -0
  28. package/scripts/build-native-root-probe-r197.ps1 +28 -0
  29. package/scripts/gate-windows-r195.ps1 +114 -0
  30. package/scripts/gate-windows-r206.ps1 +116 -0
  31. package/scripts/init-desktop-policy-r199.ps1 +85 -0
  32. package/scripts/npm-release-r48.mjs +17 -0
  33. package/scripts/npm-release-readiness-r195.mjs +72 -0
  34. package/scripts/npm-release-readiness-r206.mjs +76 -0
  35. package/scripts/r193-owner-request-live.mjs +5 -6
  36. package/scripts/r193-owner-uac-broker.mjs +3 -3
  37. package/scripts/r205-candidate-selection.mjs +22 -0
  38. package/src/candidate-selection-evidence-r206.mjs +71 -0
  39. package/src/candidate-selection-r205.mjs +96 -0
  40. package/src/desktop-postcondition-r196.mjs +30 -0
  41. package/src/desktop-runtime-r40.mjs +44 -7
  42. package/src/desktop-uia-identity-r199.mjs +51 -0
  43. package/src/desktop-uia-r40.mjs +9 -1
  44. package/src/machine-fs-handle-read-r196.mjs +43 -0
  45. package/src/machine-fs-native-read-r197.mjs +73 -0
  46. package/src/machine-fs-native-read-r198.mjs +76 -0
  47. package/src/machine-fs-read-worker.mjs +5 -25
  48. package/src/machine-fs.mjs +31 -16
  49. package/src/r195-canonical-owner-observation.mjs +15 -0
  50. package/src/remote-destination-journal-r202.mjs +120 -0
  51. package/src/remote-device-r44.mjs +89 -14
  52. package/src/remote-payload-boundary-r201.mjs +71 -0
  53. package/src/remote-terminal-evidence-r200.mjs +60 -0
  54. package/src/version.mjs +1 -1
  55. package/test/desktop-runtime-r40.test.mjs +111 -0
  56. package/test/desktop-uia-r40.test.mjs +15 -0
  57. package/test/fixtures/r197-junction-swap-worker.mjs +21 -0
  58. package/test/fixtures/r203-journal-writer.mjs +6 -0
  59. package/test/process-policy-refresh.test.mjs +4 -4
  60. package/test/r130-release-security-contract.test.mjs +8 -8
  61. package/test/r132-release-identity.test.mjs +7 -7
  62. package/test/r153-prepublish-identity.test.mjs +1 -1
  63. package/test/r160-release-contract.test.mjs +3 -3
  64. package/test/r165-live-cli-skew.test.mjs +1 -1
  65. package/test/r167-release-contract.test.mjs +11 -11
  66. package/test/r168-release-contract.test.mjs +4 -4
  67. package/test/r172-release-contract.test.mjs +6 -6
  68. package/test/r173-release-contract.test.mjs +16 -16
  69. package/test/r179-release-contract.test.mjs +12 -12
  70. package/test/r190-release-contract.test.mjs +10 -10
  71. package/test/r191-release-contract.test.mjs +12 -12
  72. package/test/r192-release-identity.test.mjs +9 -9
  73. package/test/r193-release-identity.test.mjs +24 -22
  74. package/test/r193-release-readiness.test.mjs +2 -2
  75. package/test/r193-windows-gate.test.mjs +8 -8
  76. package/test/r194-release-identity.test.mjs +19 -15
  77. package/test/r194-release-readiness.test.mjs +2 -2
  78. package/test/r194-windows-gate.test.mjs +7 -6
  79. package/test/r195-canonical-owner-observation.test.mjs +32 -0
  80. package/test/r195-release-readiness.test.mjs +22 -0
  81. package/test/r196-desktop-postcondition.test.mjs +53 -0
  82. package/test/r196-handle-bound-read.test.mjs +99 -0
  83. package/test/r196-remote-outcome.test.mjs +94 -0
  84. package/test/r197-namespace-race.test.mjs +41 -0
  85. package/test/r197-native-dispatch-race.test.mjs +49 -0
  86. package/test/r197-native-file-read.test.mjs +60 -0
  87. package/test/r197-native-root-open.test.mjs +61 -0
  88. package/test/r198-root-identity.test.mjs +88 -0
  89. package/test/r199-native-uia-worker.test.mjs +28 -0
  90. package/test/r199-uia-identity.test.mjs +43 -0
  91. package/test/r200-remote-reconcile.test.mjs +106 -0
  92. package/test/r201-payload-boundary.test.mjs +78 -0
  93. package/test/r201-payload-fuzz.test.mjs +37 -0
  94. package/test/r201-tool-boundary-fuzz.test.mjs +120 -0
  95. package/test/r202-destination-journal.test.mjs +92 -0
  96. package/test/r203-atomic-journal.test.mjs +86 -0
  97. package/test/r205-candidate-selection-cli.test.mjs +31 -0
  98. package/test/r205-candidate-selection.test.mjs +83 -0
  99. package/test/r206-candidate-evidence.test.mjs +64 -0
  100. package/test/r206-release-contract.test.mjs +42 -0
  101. package/test/r206-release-readiness.test.mjs +23 -0
  102. package/test/r59-tool-surface-compat.test.mjs +1 -1
  103. 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,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,8 @@ 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';
18
20
  import {resumePackRecord} from '../src/npm-publication-resume-r168.mjs';
19
21
  import { existsSync,mkdtempSync,readdirSync,readFileSync,rmSync } from 'node:fs';
20
22
  import { resolveStateRoot } from '../src/state-root.mjs';
@@ -157,6 +159,13 @@ async function main() {
157
159
  if (!publishOnly) throw new Error('PUBLISH_BLOCKED R194 requires --publish-only; activation remains separately authorized');
158
160
  r194Readiness=await assertR194NpmPublishReady(release,{root});
159
161
  }
162
+ let r195Readiness=null;
163
+ let r206Readiness=null;
164
+ if (!isVerifyOnly && version==='0.15.75') {
165
+ if (!publishOnly) throw new Error('PUBLISH_BLOCKED R206 requires --publish-only; owner enrollment and activation remain separate');
166
+ if(release.train==='R206')r206Readiness=await assertR206NpmPublishReady(release,{root});
167
+ else r195Readiness=await assertR195NpmPublishReady(release,{root});
168
+ }
160
169
  if (release.parent?.release_id !== provenance.parent_release_id ||
161
170
  release.parent?.manifest_sha256 !== provenance.parent_manifest_sha256 ||
162
171
  release.parent?.generation_manifest_sha256 !== provenance.parent_generation_manifest_sha256) {
@@ -304,6 +313,14 @@ async function main() {
304
313
  ...r194Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
305
314
  observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
306
315
  });
316
+ if(r195Readiness)assertR195PackedIdentity({
317
+ ...r195Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
318
+ observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
319
+ });
320
+ if(r206Readiness)assertR206PackedIdentity({
321
+ ...r206Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
322
+ observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
323
+ });
307
324
 
308
325
  console.log('[6/7] Publishing artifact to npm registry...');
309
326
  publishAttempted = true;
@@ -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
+ }
@@ -0,0 +1,76 @@
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 R206 ${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 assertR206PackedIdentity({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 assertR206NpmPublishReady(release,{root,closureRoot=process.env.DEADBYTE_R206_CLOSURE_ROOT}={}){
35
+ required(release?.version==='0.15.75'&&release?.train==='R206'&&
36
+ release?.r206?.scope==='EVIDENCE_BOUND_CANDIDATE_SELECTION_RELEASE_CLOSURE','candidate metadata invalid');
37
+ required(release?.r206?.public_tool_delta===0&&release?.r206?.authority_scope_delta===0&&
38
+ release?.r206?.selector_release_authority===false,'public authority surface widened');
39
+ required(release?.source_predecessor?.train==='R205'&&
40
+ release?.source_predecessor?.manifest_sha256==='166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92',
41
+ 'source predecessor mismatch');
42
+ required(release?.parent?.version==='0.15.74'&&release?.parent?.release_id==='v0.15.74-e84bf4eed16e9443'&&
43
+ release?.parent?.manifest_sha256==='e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47'&&
44
+ release?.parent?.generation_manifest_sha256==='598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7','lineage mismatch');
45
+ required(root&&path.isAbsolute(root)&&closureRoot&&path.isAbsolute(closureRoot),'closure root absent');
46
+ const expected=path.resolve(root,'..','..','testing','r206-final-closure');
47
+ required(path.resolve(closureRoot).toLowerCase()===expected.toLowerCase(),'closure root outside scoped testing folder');
48
+ let closure;try{closure=JSON.parse(await readFile(path.join(closureRoot,'closure.json'),'utf8'));}catch{fail('closure unreadable');}
49
+ required(closure?.schema==='deadbyte.r206-release-closure.v1'&&closure.status==='RELEASE_READY'&&
50
+ closure.version==='0.15.75'&&closure.train==='R206','closure status mismatch');
51
+ required(closure.production_release_id===release.parent.release_id&&closure.production_manifest_sha256===release.parent.manifest_sha256&&
52
+ closure.production_generation_manifest_sha256===release.parent.generation_manifest_sha256,'production predecessor mismatch');
53
+ required(hex64(closure.manifest_sha256)&&closure.manifest_sha256===sha256(await readFile(path.join(root,'MANIFEST.SHA256'))),'final manifest drift');
54
+ required(closure.compact_tools===43&&closure.full_tools===117,'catalog count mismatch');
55
+ required(closure.owner_enrollment==='NOT_RUN'&&closure.production_activation==='NOT_RUN','prepublication closure crossed authority boundary');
56
+ const receipt=JSON.parse((await checkedFile(path.join(closureRoot,'protected-install-receipt.json'),closure.protected_receipt_sha256)).toString('utf8'));
57
+ required(receipt?.status==='PASS'&&receipt.package_version==='0.15.75'&&receipt.source_manifest_sha256===closure.manifest_sha256&&
58
+ receipt.protected_manifest_sha256===closure.manifest_sha256,'protected exact-byte receipt mismatch');
59
+ const focused=(await checkedFile(path.join(closureRoot,'windows-focused.stdout.log'),closure.focused_stdout_sha256)).toString('utf8');
60
+ const full=(await checkedFile(path.join(closureRoot,'windows-full.stdout.log'),closure.full_stdout_sha256)).toString('utf8');
61
+ const verify=(await checkedFile(path.join(closureRoot,'npm-verify.stdout.log'),closure.verify_stdout_sha256)).toString('utf8');
62
+ required(focused.includes('R206_STAGE_PASS=focused'),'focused protected gate incomplete');
63
+ const focusedSummary=tapSummary(focused,'focused');
64
+ required(focusedSummary.fails===0&&focusedSummary.cancelled===0&&focusedSummary.passes>=70&&focusedSummary.skips<=3,'focused regression count mismatch');
65
+ required(full.includes('R206_STAGE_PASS=full'),'full protected gate incomplete');
66
+ const summary=tapSummary(full,'full');
67
+ 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');
68
+ required(verify.includes('VERIFY-ONLY PIPELINE PASS')&&verify.includes('Artifact isolation gate PASS')&&verify.includes('VERIFIED_TARBALL '),'npm exact-artifact verification incomplete');
69
+ const line=verify.split(/\r?\n/).find(value=>value.startsWith('VERIFIED_TARBALL '));
70
+ let artifact;try{artifact=JSON.parse(line.slice('VERIFIED_TARBALL '.length));}catch{fail('tarball evidence malformed');}
71
+ required(artifact.filename==='deadbyte-mcp-0.15.75.tgz'&&artifact.bytes>0&&artifact.sha256===closure.tarball_sha256&&
72
+ artifact.integrity===closure.tarball_integrity&&artifact.shasum===closure.tarball_shasum,'tarball identity mismatch');
73
+ return Object.freeze({status:'R206_RELEASE_READY_EVIDENCE_BOUND',manifest_sha256:closure.manifest_sha256,
74
+ tarball_sha256:artifact.sha256,tarball_integrity:artifact.integrity,tarball_shasum:artifact.shasum,
75
+ tests:summary.tests,passes:summary.passes,skips:summary.skips});
76
+ }
@@ -1,7 +1,5 @@
1
1
  // Protected, fixed-scope request generation after Limited migration.
2
2
  import {createHash} from 'node:crypto';
3
- import {execFile} from 'node:child_process';
4
- import {promisify} from 'node:util';
5
3
  import {lstat,open,readFile} from 'node:fs/promises';
6
4
  import path from 'node:path';
7
5
  import {fileURLToPath} from 'node:url';
@@ -10,6 +8,9 @@ import {inspectTrustedInstallation} from '../src/privileged-install-trust-r89.mj
10
8
  import {parseManifest,verifyManifestTreeExact} from '../src/release-slot.mjs';
11
9
  import {createR188OwnerUacRequest} from '../src/r188-owner-uac.mjs';
12
10
  import {createR193LiveMachineEpoch} from '../src/r193-live-owner-subject.mjs';
11
+ import {observeCanonicalController} from '../src/r195-canonical-owner-observation.mjs';
12
+ import {execFile} from 'node:child_process';
13
+ import {promisify} from 'node:util';
13
14
  const execFileAsync=promisify(execFile);
14
15
  const THIS=fileURLToPath(import.meta.url),ROOT=path.resolve(path.dirname(THIS),'..');
15
16
  const STATE='C:\\Users\\DEADBYTE\\.deadbyte-mcp',RUNTIME=path.win32.join(STATE,'runtime');
@@ -21,6 +22,7 @@ async function main(){
21
22
  const manifestPath=path.join(ROOT,'MANIFEST.SHA256');
22
23
  await inspectTrustedInstallation(['C:\\Program Files\\nodejs\\node.exe',THIS,manifestPath,
23
24
  path.join(ROOT,'src','r188-owner-uac.mjs'),path.join(ROOT,'src','r193-live-owner-subject.mjs'),
25
+ path.join(ROOT,'src','r195-canonical-owner-observation.mjs'),
24
26
  path.join(ROOT,'src','privileged-install-trust-r89.mjs')]);
25
27
  const manifestBytes=await bounded(manifestPath,1024*1024);
26
28
  await verifyManifestTreeExact(ROOT,parseManifest(manifestBytes.toString('utf8')));
@@ -32,10 +34,7 @@ async function main(){
32
34
  if(!coding.roots?.core?.path||!Array.isArray(autonomous.root_ids)||autonomous.root_ids.length!==1||autonomous.root_ids[0]!=='core')
33
35
  throw Error('R193 request policy root is not the bounded core project');
34
36
  const env={...process.env,DEADBYTE_CONTROLLER_CONFIG:pointer.config_path,DEADBYTE_CONTROLLER_RUNTIME_ROOT:RUNTIME};
35
- const controller=path.join(ROOT,'controller','deadbyte-controller.ps1');
36
- const {stdout}=await execFileAsync(PS,['-NoLogo','-NoProfile','-NonInteractive','-ExecutionPolicy','Bypass','-File',controller,'status','-Json'],
37
- {env,windowsHide:true,timeout:20000,maxBuffer:1024*1024,encoding:'utf8'});
38
- const observation=JSON.parse(stdout);
37
+ const observation=await observeCanonicalController({stateRoot:STATE,powershell:PS,env,execFileAsync});
39
38
  if(observation.state!=='ONLINE'||!observation.supervisor?.running)throw Error('R193 request requires ONLINE Limited runtime');
40
39
  const machineEpoch=createR193LiveMachineEpoch({activePointer:pointer,controllerObservation:observation});
41
40
  const request=createR188OwnerUacRequest({machineEpoch,releaseManifestSha256:sha(manifestBytes),
@@ -15,6 +15,7 @@ import {buildR193LiveOwnerBoundary} from '../src/r193-live-owner-subject.mjs';
15
15
  import {approveR193OwnerRequest} from '../src/r193-owner-uac-broker.mjs';
16
16
  import {createR186OwnerAnchor} from '../src/r186-owner-anchor.mjs';
17
17
  import {inspectR193OwnerSecretAcl} from '../src/r193-owner-secret-acl.mjs';
18
+ import {observeCanonicalController} from '../src/r195-canonical-owner-observation.mjs';
18
19
 
19
20
  const execFileAsync=promisify(execFile);
20
21
  const THIS=fileURLToPath(import.meta.url),ROOT=path.resolve(path.dirname(THIS),'..');
@@ -61,6 +62,7 @@ async function live(request){
61
62
  const protectedFiles=[NODE,THIS,manifestPath,NATIVE,
62
63
  path.join(ROOT,'src','r193-live-owner-subject.mjs'),
63
64
  path.join(ROOT,'src','r193-owner-uac-broker.mjs'),
65
+ path.join(ROOT,'src','r195-canonical-owner-observation.mjs'),
64
66
  path.join(ROOT,'src','r193-uac-r70-bridge.mjs'),
65
67
  path.join(ROOT,'src','r193-owner-secret-acl.mjs'),
66
68
  path.join(ROOT,'src','r188-owner-uac.mjs'),
@@ -77,11 +79,9 @@ async function live(request){
77
79
  const codingPath=path.win32.join(generation,'coding-policy.json');
78
80
  const autonomousPath=path.win32.join(generation,'autonomous-policy.json');
79
81
  const configPath=pointer.config_path;
80
- const controller=path.join(ROOT,'controller','deadbyte-controller.ps1');
81
82
  const env={...process.env,DEADBYTE_CONTROLLER_CONFIG:configPath,
82
83
  DEADBYTE_CONTROLLER_RUNTIME_ROOT:RUNTIME};
83
- const observation=await jsonExec(PS,['-NoLogo','-NoProfile','-NonInteractive',
84
- '-ExecutionPolicy','Bypass','-File',controller,'status','-Json'],{env});
84
+ const observation=await observeCanonicalController({stateRoot:STATE,powershell:PS,env,execFileAsync});
85
85
  const supervisor=JSON.parse((await bounded(path.win32.join(RUNTIME,'supervisor.instance.json'),64*1024)).toString('utf8'));
86
86
  const sources={bridge:observation.bridge,core:observation.core,cloud:observation.cloud,supervisor};
87
87
  const processReports={};
@@ -0,0 +1,22 @@
1
+ // Read-only bounded stdin candidate comparison. Does not promote, publish, or grant authority.
2
+ import { evaluateCandidateSelectionR205 } from '../src/candidate-selection-r205.mjs';
3
+
4
+ const MAX_BYTES=64*1024;
5
+ let length=0;
6
+ const parts=[];
7
+ try{
8
+ for await (const chunk of process.stdin){
9
+ length+=chunk.length;
10
+ if(length>MAX_BYTES)throw Error('R205_INPUT_LIMIT_EXCEEDED');
11
+ parts.push(chunk);
12
+ }
13
+ if(length<1)throw Error('R205_INPUT_EMPTY');
14
+ const raw=Buffer.concat(parts).toString('utf8');
15
+ const parsed=JSON.parse(raw);
16
+ const result=evaluateCandidateSelectionR205(parsed);
17
+ process.stdout.write(JSON.stringify(result)+'\n');
18
+ if(result.state!=='PROVISIONAL_CANDIDATE')process.exitCode=2;
19
+ }catch(error){
20
+ process.stderr.write('R205_SELECTION_REFUSED '+String(error?.message??error)+'\n');
21
+ process.exitCode=3;
22
+ }