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.
Files changed (144) hide show
  1. package/MANIFEST.SHA256 +143 -35
  2. package/PROVENANCE.json +47 -21
  3. package/README.txt +29 -18
  4. package/RELEASE.json +85 -18
  5. package/SBOM.cdx.json +14 -2
  6. package/TEST-MATRIX.json +50 -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-owner-token-r193.exe +0 -0
  15. package/bin/deadbyte-root-relative-probe-r197.exe +0 -0
  16. package/bridge/package.json +1 -1
  17. package/controller/deadbyte-process-policy.json +4 -4
  18. package/docs/R184-package-lock.json +2 -8
  19. package/native/deadbyte-desktop-uia-r199.cpp +345 -0
  20. package/native/deadbyte-fs-read-r197.cpp +174 -0
  21. package/native/deadbyte-fs-read-r198.cpp +181 -0
  22. package/native/deadbyte-owner-token-r193.cpp +156 -0
  23. package/native/deadbyte-root-relative-probe-r197.cpp +97 -0
  24. package/package.json +4 -2
  25. package/scripts/build-native-desktop-uia-r199-fixed.ps1 +28 -0
  26. package/scripts/build-native-desktop-uia-r199.ps1 +28 -0
  27. package/scripts/build-native-fs-read-r197-fixed.ps1 +28 -0
  28. package/scripts/build-native-fs-read-r197.ps1 +28 -0
  29. package/scripts/build-native-fs-read-r198.ps1 +28 -0
  30. package/scripts/build-native-root-probe-r197.ps1 +28 -0
  31. package/scripts/gate-windows-r193.ps1 +108 -0
  32. package/scripts/gate-windows-r194.ps1 +112 -0
  33. package/scripts/gate-windows-r195.ps1 +114 -0
  34. package/scripts/gate-windows-r206.ps1 +116 -0
  35. package/scripts/init-desktop-policy-r199.ps1 +85 -0
  36. package/scripts/npm-interactive-r194.mjs +13 -0
  37. package/scripts/npm-publication-r65.mjs +64 -4
  38. package/scripts/npm-release-r48.mjs +75 -11
  39. package/scripts/npm-release-readiness-r193.mjs +80 -0
  40. package/scripts/npm-release-readiness-r194.mjs +80 -0
  41. package/scripts/npm-release-readiness-r195.mjs +72 -0
  42. package/scripts/npm-release-readiness-r206.mjs +76 -0
  43. package/scripts/r188-owner-uac-review.ps1 +91 -0
  44. package/scripts/r188-uac-review-preview.mjs +65 -0
  45. package/scripts/r193-compile-token.ps1 +22 -0
  46. package/scripts/r193-evidence-relocate.ps1 +12 -0
  47. package/scripts/r193-focused-gate.mjs +20 -0
  48. package/scripts/r193-import-r188-scripts.ps1 +14 -0
  49. package/scripts/r193-limited-subject-probe.ps1 +25 -0
  50. package/scripts/r193-migrate-runtime-limited.ps1 +103 -0
  51. package/scripts/r193-owner-keygen.mjs +43 -0
  52. package/scripts/r193-owner-request-live.mjs +49 -0
  53. package/scripts/r193-owner-uac-approve.ps1 +42 -0
  54. package/scripts/r193-owner-uac-broker.mjs +139 -0
  55. package/scripts/r193-owner-uac-enroll-and-approve.ps1 +62 -0
  56. package/scripts/r193-test-limited-token.ps1 +49 -0
  57. package/scripts/r193-toolchain-inventory.ps1 +7 -0
  58. package/scripts/r193-uac-bridge-focused.mjs +21 -0
  59. package/scripts/r205-candidate-selection.mjs +22 -0
  60. package/src/candidate-selection-evidence-r206.mjs +71 -0
  61. package/src/candidate-selection-r205.mjs +96 -0
  62. package/src/desktop-postcondition-r196.mjs +30 -0
  63. package/src/desktop-runtime-r40.mjs +44 -7
  64. package/src/desktop-uia-identity-r199.mjs +51 -0
  65. package/src/desktop-uia-r40.mjs +9 -1
  66. package/src/machine-fs-handle-read-r196.mjs +43 -0
  67. package/src/machine-fs-native-read-r197.mjs +73 -0
  68. package/src/machine-fs-native-read-r198.mjs +76 -0
  69. package/src/machine-fs-read-worker.mjs +5 -25
  70. package/src/machine-fs.mjs +31 -16
  71. package/src/r188-owner-uac.mjs +105 -0
  72. package/src/r188-uac-boundary.mjs +21 -0
  73. package/src/r193-live-owner-subject.mjs +110 -0
  74. package/src/r193-owner-secret-acl.mjs +67 -0
  75. package/src/r193-owner-uac-broker.mjs +85 -0
  76. package/src/r193-uac-r70-bridge.mjs +54 -0
  77. package/src/r195-canonical-owner-observation.mjs +15 -0
  78. package/src/remote-destination-journal-r202.mjs +120 -0
  79. package/src/remote-device-r44.mjs +89 -14
  80. package/src/remote-payload-boundary-r201.mjs +71 -0
  81. package/src/remote-terminal-evidence-r200.mjs +60 -0
  82. package/src/version.mjs +1 -1
  83. package/test/desktop-runtime-r40.test.mjs +111 -0
  84. package/test/desktop-uia-r40.test.mjs +15 -0
  85. package/test/fixtures/r197-junction-swap-worker.mjs +21 -0
  86. package/test/fixtures/r203-journal-writer.mjs +6 -0
  87. package/test/process-policy-refresh.test.mjs +4 -4
  88. package/test/r130-release-security-contract.test.mjs +8 -8
  89. package/test/r132-release-identity.test.mjs +7 -7
  90. package/test/r153-prepublish-identity.test.mjs +1 -1
  91. package/test/r160-release-contract.test.mjs +3 -3
  92. package/test/r165-live-cli-skew.test.mjs +1 -1
  93. package/test/r167-release-contract.test.mjs +11 -11
  94. package/test/r168-release-contract.test.mjs +4 -4
  95. package/test/r172-release-contract.test.mjs +6 -6
  96. package/test/r173-release-contract.test.mjs +16 -16
  97. package/test/r179-release-contract.test.mjs +12 -12
  98. package/test/r188-owner-uac.test.mjs +48 -0
  99. package/test/r188-uac-boundary.test.mjs +42 -0
  100. package/test/r190-release-contract.test.mjs +10 -10
  101. package/test/r191-release-contract.test.mjs +12 -12
  102. package/test/r192-release-identity.test.mjs +10 -10
  103. package/test/r193-limited-migration-contract.test.mjs +26 -0
  104. package/test/r193-live-owner-subject.test.mjs +61 -0
  105. package/test/r193-native-process-observer.test.mjs +36 -0
  106. package/test/r193-native-token.test.mjs +43 -0
  107. package/test/r193-owner-enrollment-entrypoint.test.mjs +38 -0
  108. package/test/r193-owner-secret-acl.test.mjs +23 -0
  109. package/test/r193-owner-uac-broker.test.mjs +82 -0
  110. package/test/r193-owner-uac-entrypoint.test.mjs +36 -0
  111. package/test/r193-release-identity.test.mjs +58 -0
  112. package/test/r193-release-readiness.test.mjs +87 -0
  113. package/test/r193-uac-r70-bridge.test.mjs +88 -0
  114. package/test/r193-windows-gate.test.mjs +30 -0
  115. package/test/r194-npm-auth-recovery.test.mjs +77 -0
  116. package/test/r194-npm-preauth.test.mjs +57 -0
  117. package/test/r194-release-identity.test.mjs +47 -0
  118. package/test/r194-release-readiness.test.mjs +87 -0
  119. package/test/r194-windows-gate.test.mjs +22 -0
  120. package/test/r195-canonical-owner-observation.test.mjs +32 -0
  121. package/test/r195-release-readiness.test.mjs +22 -0
  122. package/test/r196-desktop-postcondition.test.mjs +53 -0
  123. package/test/r196-handle-bound-read.test.mjs +99 -0
  124. package/test/r196-remote-outcome.test.mjs +94 -0
  125. package/test/r197-namespace-race.test.mjs +41 -0
  126. package/test/r197-native-dispatch-race.test.mjs +49 -0
  127. package/test/r197-native-file-read.test.mjs +60 -0
  128. package/test/r197-native-root-open.test.mjs +61 -0
  129. package/test/r198-root-identity.test.mjs +88 -0
  130. package/test/r199-native-uia-worker.test.mjs +28 -0
  131. package/test/r199-uia-identity.test.mjs +43 -0
  132. package/test/r200-remote-reconcile.test.mjs +106 -0
  133. package/test/r201-payload-boundary.test.mjs +78 -0
  134. package/test/r201-payload-fuzz.test.mjs +37 -0
  135. package/test/r201-tool-boundary-fuzz.test.mjs +120 -0
  136. package/test/r202-destination-journal.test.mjs +92 -0
  137. package/test/r203-atomic-journal.test.mjs +86 -0
  138. package/test/r205-candidate-selection-cli.test.mjs +31 -0
  139. package/test/r205-candidate-selection.test.mjs +83 -0
  140. package/test/r206-candidate-evidence.test.mjs +64 -0
  141. package/test/r206-release-contract.test.mjs +42 -0
  142. package/test/r206-release-readiness.test.mjs +23 -0
  143. package/test/r59-tool-surface-compat.test.mjs +1 -1
  144. 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
- if(states.some(item=>item.state==='AUTH_REQUIRED'))return result('AUTH_REQUIRED');
125
- const accepted=states.some(item=>item.state==='SUBMISSION_ACCEPTED');
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();