deadbyte-mcp 0.15.45 → 0.15.46

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 (35) hide show
  1. package/MANIFEST.SHA256 +34 -24
  2. package/PROVENANCE.json +260 -257
  3. package/README.txt +22 -21
  4. package/RELEASE.json +367 -346
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +501 -503
  7. package/bridge/package.json +1 -1
  8. package/controller/deadbyte-controller.ps1 +20 -6
  9. package/controller/deadbyte-process-policy.json +4 -4
  10. package/package.json +2 -2
  11. package/scripts/gate-windows-r72.ps1 +76 -0
  12. package/scripts/npm-release-r48.mjs +2 -0
  13. package/scripts/npm-release-readiness-r72.mjs +76 -0
  14. package/src/deadbyte-cli.mjs +722 -721
  15. package/src/launcher-isolation.mjs +58 -0
  16. package/src/remote-authority.mjs +75 -75
  17. package/src/remote-mcp-machine-smoke-client.mjs +84 -84
  18. package/src/runtime-update.mjs +2056 -2008
  19. package/src/staging-input-isolation.mjs +79 -0
  20. package/src/version.mjs +1 -1
  21. package/test/deferred-slot-operation-behavior.test.mjs +2 -2
  22. package/test/r58-cleanup-retention.test.mjs +3 -3
  23. package/test/r58-concurrent-recovery.test.mjs +3 -3
  24. package/test/r58-stale-owner.test.mjs +1 -1
  25. package/test/r59-tool-surface-compat.test.mjs +2 -2
  26. package/test/r60-authority-coherence.test.mjs +10 -2
  27. package/test/r71-isolated-slot-rollback-restore.test.mjs +11 -11
  28. package/test/r71-release-identity.test.mjs +12 -10
  29. package/test/r72-launcher-isolation.test.mjs +99 -0
  30. package/test/r72-publication-fence.test.mjs +56 -0
  31. package/test/r72-publication-output-integrity.test.mjs +110 -0
  32. package/test/r72-remote-safe-contract.test.mjs +101 -0
  33. package/test/r72-staging-input-isolation.test.mjs +87 -0
  34. package/test/r72-staging-workspace-isolation.test.mjs +114 -0
  35. package/test/remote-session-cli.test.mjs +110 -64
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deadbyte-chatgpt-bridge",
3
- "version": "0.15.45",
3
+ "version": "0.15.46",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "engines": {
@@ -1346,15 +1346,29 @@ function Arm-Autonomous($Cfg) {
1346
1346
  Write-Host 'AUTONOMOUS PLANE ENABLED UNTIL EXPLICIT REVOKE'
1347
1347
  }
1348
1348
 
1349
+ function Get-AutonomousRevocationLeaseFile($Cfg) {
1350
+ if ([string]::IsNullOrWhiteSpace([string]$Cfg.AutonomousPolicyFile)) { return $null }
1351
+ # Revocation may not depend on approval/root checks used only for issuing grants.
1352
+ # The source remains the bound policy snapshot, never a caller-supplied path.
1353
+ $snapshot = Read-ControllerPolicySnapshot ([string]$Cfg.AutonomousPolicyFile) 'autonomous'
1354
+ $policy = $snapshot.Policy
1355
+ if ($policy.schema -ne 'deadbyte.autonomous-policy.v1' -or $policy.enabled -ne $true) { Fail 'autonomous policy schema/enabled mismatch' }
1356
+ if ([string]::IsNullOrWhiteSpace([string]$policy.lease_file)) { Fail 'autonomous policy lease_file missing' }
1357
+ $leaseFile = [System.IO.Path]::GetFullPath([string]$policy.lease_file)
1358
+ $runtimeReal = [System.IO.Path]::GetFullPath($RuntimeDir).TrimEnd('\') + '\'
1359
+ if (-not $leaseFile.StartsWith($runtimeReal, [System.StringComparison]::OrdinalIgnoreCase)) { Fail 'autonomous policy lease_file must live under controller runtime directory' }
1360
+ return $leaseFile
1361
+ }
1362
+
1349
1363
  function Disarm-Autonomous($Cfg, [switch]$Quiet) {
1350
1364
  if ([string]::IsNullOrWhiteSpace([string]$Cfg.AutonomousPolicyFile)) { return }
1351
- $meta = Get-AutonomousPolicyMetadata $Cfg
1365
+ $leaseFile = Get-AutonomousRevocationLeaseFile $Cfg
1352
1366
  $epochError = $null
1353
- if (Test-Path -LiteralPath $meta.LeaseFile -PathType Leaf) {
1354
- try { Invoke-AuthorityEpochCommand $Cfg 'autonomous' 'user-revoke' $meta.LeaseFile | Out-Null } catch { $epochError = $_.Exception }
1355
- Remove-Item -LiteralPath $meta.LeaseFile -Force -ErrorAction SilentlyContinue
1367
+ if (Test-Path -LiteralPath $leaseFile -PathType Leaf) {
1368
+ try { Invoke-AuthorityEpochCommand $Cfg 'autonomous' 'user-revoke' $leaseFile | Out-Null } catch { $epochError = $_.Exception }
1369
+ Remove-Item -LiteralPath $leaseFile -Force -ErrorAction SilentlyContinue
1356
1370
  }
1357
- if (Test-Path -LiteralPath $meta.LeaseFile) { throw 'Autonomous authority revocation failed: grant remains present' }
1371
+ if (Test-Path -LiteralPath $leaseFile) { throw 'Autonomous authority revocation failed: grant remains present' }
1358
1372
  if ($null -ne $epochError) { throw $epochError }
1359
1373
  if (-not $Quiet) { Write-Host 'AUTONOMOUS PLANE DISARMED' }
1360
1374
  }
@@ -1642,7 +1656,7 @@ function Invoke-MachineSmoke($Cfg) {
1642
1656
  Wait-PublicDnsReady $Cfg $url
1643
1657
  $probeArgs = @($url)
1644
1658
  if (-not [string]::IsNullOrWhiteSpace([string]$env:DEADBYTE_REMOTE_PROBE_MODE)) {
1645
- if ([string]$env:DEADBYTE_REMOTE_PROBE_MODE -notin @('default','desktop','host','full','revoked')) { Fail 'invalid remote enforcement probe mode' }
1659
+ if ([string]$env:DEADBYTE_REMOTE_PROBE_MODE -notin @('default','operator','desktop','host','full','revoked')) { Fail 'invalid remote enforcement probe mode' }
1646
1660
  $probeArgs += [string]$env:DEADBYTE_REMOTE_PROBE_MODE
1647
1661
  }
1648
1662
  Invoke-CoreGate $Cfg 'remote-mcp-machine-smoke-client.mjs' $probeArgs
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "schema": "deadbyte.process-policy.v1",
3
3
  "enabled": true,
4
- "grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.45-r71\\controller\\runtime\\process-grant.json",
5
- "state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.45-r71\\controller\\runtime\\process-state",
4
+ "grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.46-r72\\controller\\runtime\\process-grant.json",
5
+ "state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.46-r72\\controller\\runtime\\process-state",
6
6
  "native_host": {
7
- "path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.45-r71\\bin\\deadbyte-process-host.exe",
7
+ "path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.46-r72\\bin\\deadbyte-process-host.exe",
8
8
  "sha256": "daf9cfb371bee88cafbf5597eaa507fec504dbe0b0ddd40d0c3c2e02817f49e4"
9
9
  },
10
10
  "roots": {
11
11
  "core": {
12
- "path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.45-r71",
12
+ "path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.46-r72",
13
13
  "deny_paths": [
14
14
  "node_modules",
15
15
  "controller/runtime",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deadbyte-mcp",
3
- "version": "0.15.45",
3
+ "version": "0.15.46",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Authenticated MCP agentic runtime with signed skills, persistent model backends, identity-bound remote devices, durable job supervision, immutable release slots, and separately revocable machine authority.",
@@ -42,7 +42,7 @@
42
42
  "contained:run": "node src/contained-cli.mjs workspaces/demo input.txt",
43
43
  "contained:smoke": "node src/contained-smoke.mjs",
44
44
  "mcp:contained:smoke": "node src/mcp-contained-smoke-client.mjs",
45
- "gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r71.ps1",
45
+ "gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r72.ps1",
46
46
  "authority:smoke": "node src/authority-smoke.mjs",
47
47
  "mcp:remote:smoke": "node src/remote-mcp-smoke-client.mjs",
48
48
  "mcp:host:smoke": "node src/mcp-host-smoke-client.mjs",
@@ -0,0 +1,76 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param([ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight')
4
+ Set-StrictMode -Version Latest
5
+ $ErrorActionPreference='Stop'
6
+ $repo=Split-Path -Parent $PSScriptRoot
7
+ $state=Join-Path $env:USERPROFILE '.deadbyte-mcp'
8
+ $parentId='v0.15.45-34aa8d1241cfb8bf'
9
+ $parentSha='34aa8d1241cfb8bf0b5ba303bf3c06e0e9e1bf01f64457bca659d6dd4d634fdc'
10
+ $parentGen='ff2b73410062688651abd7bc2dd7b2b8c87810a28e3808bfe1f4352a25b0e6e4'
11
+ function Sha([string]$file){
12
+ $sha=[System.Security.Cryptography.SHA256]::Create()
13
+ try {
14
+ $stream=[System.IO.File]::OpenRead($file)
15
+ try {return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}
16
+ finally {$stream.Dispose()}
17
+ } finally {$sha.Dispose()}
18
+ }
19
+ function Run-Node([string]$label,[string[]]$nodeArgs) {
20
+ Write-Output "R72_STAGE_START=$label"
21
+ & node @nodeArgs
22
+ if($LASTEXITCODE -ne 0){throw "R72_${label}_FAILED exit=$LASTEXITCODE"}
23
+ Write-Output "R72_STAGE_PASS=$label"
24
+ }
25
+ Push-Location $repo
26
+ try {
27
+ $pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
28
+ $release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
29
+ if($pkg.version -ne '0.15.46' -or $release.version -ne '0.15.46' -or $release.train -ne 'R72'){
30
+ throw 'R72_CANDIDATE_VERSION_DRIFT'
31
+ }
32
+ if($release.parent.release_id -ne $parentId -or $release.parent.manifest_sha256 -ne $parentSha -or
33
+ $release.parent.generation_manifest_sha256 -ne $parentGen){throw 'R72_PARENT_IDENTITY_DRIFT'}
34
+ $parentRoot=Join-Path $state "releases\$parentId"
35
+ if(-not (Test-Path -LiteralPath $parentRoot -PathType Container)){throw 'R72_PARENT_SLOT_MISSING'}
36
+ if((Sha (Join-Path $parentRoot 'MANIFEST.SHA256')) -ne $parentSha){throw 'R72_PARENT_MANIFEST_MISMATCH'}
37
+ $active=Get-Content -LiteralPath (Join-Path $state 'active-release.json') -Raw | ConvertFrom-Json
38
+ if($active.version -ne '0.15.45' -or $active.release_id -ne $parentId -or
39
+ $active.manifest_sha256 -ne $parentSha -or $active.generation_manifest_sha256 -ne $parentGen){
40
+ throw 'R72_PRODUCTION_PREDECESSOR_DRIFT'
41
+ }
42
+ Write-Output 'R72_PREDECESSOR_PREFLIGHT=PASS'
43
+ if($Stage -eq 'preflight'){return}
44
+ if($Stage -in @('focused','all')){
45
+ Run-Node -label 'focused' -nodeArgs @('--test','--test-concurrency=1',
46
+ 'test/r72-remote-safe-contract.test.mjs','test/r72-publication-fence.test.mjs',
47
+ 'test/r60-authority-coherence.test.mjs','test/r58-cleanup-retention.test.mjs',
48
+ 'test/remote-session-cli.test.mjs','test/r70-controller-autonomous-root.test.mjs',
49
+ 'test/r70-controller-owner-issue-boundary.test.mjs','test/r71-release-identity.test.mjs',
50
+ 'test/r71-isolated-slot-rollback-restore.test.mjs','test/r59-tool-surface-compat.test.mjs')
51
+ if($Stage -eq 'focused'){return}
52
+ }
53
+ if($Stage -in @('full','all')){
54
+ & powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -File (Join-Path $repo 'scripts\verify-r70-full-regression.ps1')
55
+ if($LASTEXITCODE -ne 0){throw "R72_FULL_REGRESSION_FAILED exit=$LASTEXITCODE"}
56
+ Write-Output 'R72_FULL_REGRESSION_PASS'
57
+ if($Stage -eq 'full'){return}
58
+ }
59
+ if($Stage -in @('manifest','all')){
60
+ Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
61
+ if($Stage -eq 'manifest'){return}
62
+ }
63
+ if($Stage -in @('doctor','all')){
64
+ $previous=$env:DEADBYTE_STATE_ROOT
65
+ $isolated=Join-Path $env:TEMP ('deadbyte-r72-doctor-'+[guid]::NewGuid().ToString('N'))
66
+ try{
67
+ New-Item -ItemType Directory -Path $isolated -Force | Out-Null
68
+ $env:DEADBYTE_STATE_ROOT=$isolated
69
+ Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
70
+ }finally{
71
+ $env:DEADBYTE_STATE_ROOT=$previous
72
+ Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
73
+ }
74
+ }
75
+ Write-Output 'R72_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
76
+ }finally{Pop-Location}
@@ -5,6 +5,7 @@ import { mkdtemp, readFile, rm, unlink, mkdir } from 'node:fs/promises';
5
5
  import {preserveNpmTarball,assertVacantPackDestination} from './npm-preserve-artifact-r67.mjs';
6
6
  import {assertR67NpmPublishReady} from './npm-release-readiness-r67.mjs';
7
7
  import {assertR71NpmPublishReady} from './npm-release-readiness-r71.mjs';
8
+ import {assertR72NpmPublishReady} from './npm-release-readiness-r72.mjs';
8
9
  import { existsSync } from 'node:fs';
9
10
  import { resolveStateRoot } from '../src/state-root.mjs';
10
11
  import path from 'node:path';
@@ -91,6 +92,7 @@ async function main() {
91
92
  }
92
93
  if (!isVerifyOnly && version==='0.15.44') assertR67NpmPublishReady(release);
93
94
  if (!isVerifyOnly && version==='0.15.45') assertR71NpmPublishReady(release);
95
+ if (!isVerifyOnly && version==='0.15.46') await assertR72NpmPublishReady(release,{root});
94
96
  if (release.parent?.release_id !== provenance.parent_release_id ||
95
97
  release.parent?.manifest_sha256 !== provenance.parent_manifest_sha256 ||
96
98
  release.parent?.generation_manifest_sha256 !== provenance.parent_generation_manifest_sha256) {
@@ -0,0 +1,76 @@
1
+ /** R72 publication fence: exact v0.15.45 parent, final manifest and external gate evidence.
2
+ * This deliberately does NOT generate, sign or upgrade release evidence. */
3
+ import {createHash} from 'node:crypto';
4
+ import {readFile,lstat} from 'node:fs/promises';
5
+ import path from 'node:path';
6
+
7
+ const HEX64=/^[0-9a-f]{64}$/;
8
+ const expectedParent=Object.freeze({
9
+ version:'0.15.45',
10
+ release_id:'v0.15.45-34aa8d1241cfb8bf',
11
+ manifest_sha256:'34aa8d1241cfb8bf0b5ba303bf3c06e0e9e1bf01f64457bca659d6dd4d634fdc',
12
+ generation_manifest_sha256:'ff2b73410062688651abd7bc2dd7b2b8c87810a28e3808bfe1f4352a25b0e6e4'
13
+ });
14
+ const evidenceGates=['full_regression','windows_lifecycle','package_acceptance','independent_judge'];
15
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
16
+ function reject(reason){throw new Error(`PUBLISH_BLOCKED R72 ${reason}`);}
17
+ function exactParent(subject){return expectedParent.version===subject?.version&&
18
+ expectedParent.release_id===subject?.release_id&&
19
+ expectedParent.manifest_sha256===subject?.manifest_sha256&&
20
+ expectedParent.generation_manifest_sha256===subject?.generation_manifest_sha256;}
21
+
22
+ export async function assertR72NpmPublishReady(release,{root}={}){
23
+ if(release?.version!=='0.15.46'||release?.train!=='R72'||
24
+ release?.name!=='deadbyte-mcp'||!exactParent(release?.parent)||
25
+ !exactParent(release?.runtime_predecessor))reject('release identity or predecessor mismatch');
26
+ const status=release.r72_hotfix;
27
+ for(const [name,value] of Object.entries({
28
+ status:'CANDIDATE_SEALED',windows_regression:'PASS',package_acceptance:'PASS',
29
+ manifest:'PASS',remote_lifecycle:'PASS',security_gate:'PASS',independent_judge:'PASS'
30
+ }))if(status?.[name]!==value)reject(`${name}=${String(status?.[name]??'MISSING')}; require ${value}`);
31
+ if(!root||!path.isAbsolute(root))reject('candidate root missing');
32
+ const manifest=await readFile(path.join(root,'MANIFEST.SHA256')).catch(()=>reject('candidate manifest unavailable'));
33
+ const manifestSha256=sha(manifest);
34
+ const evidenceRoot=path.join(root,'testing','r72-release-evidence');
35
+ // Evidence and transcript storage must not be junctions/symlinks to another tree.
36
+ for(const dir of [evidenceRoot,path.join(evidenceRoot,'outputs')]){
37
+ const info=await lstat(dir).catch(()=>reject('evidence/output directory missing'));
38
+ if(!info.isDirectory()||info.isSymbolicLink())reject('evidence/output directory is not a real directory');
39
+ }
40
+ let ready;
41
+ try{ready=JSON.parse(await readFile(path.join(evidenceRoot,'ready.json'),'utf8'));}
42
+ catch{reject('independent release evidence index missing/invalid');}
43
+ if(ready?.schema!=='deadbyte.r72-release-evidence-index.v1'||ready?.version!=='0.15.46'||
44
+ ready?.manifest_sha256!==manifestSha256||!exactParent(ready?.parent))reject('evidence index subject mismatch');
45
+ for(const gate of evidenceGates){
46
+ const hash=ready?.gate_sha256?.[gate];
47
+ if(!HEX64.test(String(hash??'')))reject(`${gate} receipt identity missing`);
48
+ let bytes,receipt;
49
+ try{bytes=await readFile(path.join(evidenceRoot,`${gate}.json`));receipt=JSON.parse(bytes.toString('utf8'));}
50
+ catch{reject(`${gate} receipt missing/invalid`);}
51
+ if(sha(bytes)!==hash||receipt?.schema!=='deadbyte.r72-gate-result.v1'||
52
+ receipt?.gate!==gate||receipt?.version!=='0.15.46'||
53
+ receipt?.manifest_sha256!==manifestSha256||
54
+ receipt?.status!=='PASS'||receipt?.exit_code!==0)reject(`${gate} receipt tamper or failed gate`);
55
+ if(!HEX64.test(String(receipt.output_sha256??'')))reject(`${gate} missing bound command output`);
56
+ // Exact, gate-specific transcript path: a self-declared digest alone is not evidence.
57
+ const relativeOutput=`outputs/${gate}.log`;
58
+ if(receipt.output_file!==relativeOutput)reject(`${gate} output path identity mismatch`);
59
+ const outputPath=path.join(evidenceRoot,'outputs',`${gate}.log`);
60
+ const outputInfo=await lstat(outputPath).catch(()=>reject(`${gate} output missing/unavailable`));
61
+ if(!outputInfo.isFile()||outputInfo.isSymbolicLink())reject(`${gate} output must be a regular non-symlink file`);
62
+ if(outputInfo.size<1||outputInfo.size>64*1024*1024)reject(`${gate} output size invalid`);
63
+ const output=await readFile(outputPath).catch(()=>reject(`${gate} output unavailable`));
64
+ if(sha(output)!==receipt.output_sha256)reject(`${gate} output hash mismatch`);
65
+ if(gate==='full_regression'&&(!Number.isSafeInteger(receipt.pass_count)||receipt.pass_count<1||receipt.fail_count!==0))
66
+ reject('full regression count contract invalid');
67
+ if(gate==='windows_lifecycle'&&(
68
+ receipt.safe_default_arm_count!==0||receipt.operator_owner_consent_enforced!==true||
69
+ receipt.stale_owner_recovery_verified!==true||receipt.signed_epoch_fail_closed!==true))
70
+ reject('Windows lifecycle or R70 owner authority verification missing');
71
+ if(gate==='independent_judge'&&receipt.independent_verification!=='PASS')
72
+ reject('independent judge verdict unavailable');
73
+ }
74
+ return Object.freeze({status:'R72_RELEASE_READY_EVIDENCE_BOUND',version:'0.15.46',
75
+ manifest_sha256:manifestSha256,evidence_count:evidenceGates.length});
76
+ }