deadbyte-mcp 0.15.46 → 0.15.48

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 (98) hide show
  1. package/MANIFEST.SHA256 +97 -45
  2. package/PROVENANCE.json +22 -11
  3. package/README.txt +18 -18
  4. package/RELEASE.json +378 -369
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +2 -2
  7. package/bin/deadbyte-epoch-lock-r85.node +0 -0
  8. package/bin/deadbyte-kernel-lock-r74.exe +0 -0
  9. package/bridge/package.json +1 -1
  10. package/controller/deadbyte-process-policy.json +7 -7
  11. package/docs/R73-CAPABILITY-GAP-MATRIX.json +17 -0
  12. package/docs/R73-EXECUTION-CONTRACT.md +11 -0
  13. package/docs/R73-IMPLEMENTATION-CHANGELOG.md +12 -0
  14. package/docs/R73-REMAINING-DEFECTS.md +9 -0
  15. package/docs/R74-KERNEL-LOCK-BINARY.json +11 -0
  16. package/docs/R75-RECOVERY-HANDOFF.md +16 -0
  17. package/docs/R85-EPOCH-LOCK-BINARY.json +13 -0
  18. package/native/deadbyte-epoch-lock-r85.cpp +241 -0
  19. package/native/deadbyte-kernel-lock-r74.cpp +65 -0
  20. package/package.json +1 -1
  21. package/scripts/build-epoch-lock-r85.ps1 +34 -0
  22. package/scripts/build-kernel-lock-r74.ps1 +28 -0
  23. package/scripts/deploy-r48.mjs +3 -1
  24. package/scripts/gate-windows-r72.ps1 +2 -2
  25. package/scripts/npm-prepublish-contract-r74.mjs +113 -0
  26. package/scripts/npm-release-r48.mjs +24 -4
  27. package/scripts/npm-release-readiness-r108.mjs +134 -0
  28. package/scripts/npm-release-readiness-r74.mjs +46 -0
  29. package/scripts/r73-atomic-benchmark.mjs +39 -0
  30. package/scripts/r75-npm-bin-integrity-gate.mjs +33 -0
  31. package/scripts/release-manifest.mjs +1 -1
  32. package/scripts/verify-r70-full-regression.ps1 +12 -2
  33. package/src/activation-authority-proof-r75.mjs +67 -0
  34. package/src/activation-continuity-engine-r65.mjs +17 -4
  35. package/src/activation-preflight-r65.mjs +13 -0
  36. package/src/atomic-mutation.mjs +99 -9
  37. package/src/authority-continuity-r65.mjs +265 -21
  38. package/src/deadbyte-cli.mjs +55 -18
  39. package/src/epoch-lock-r85.mjs +48 -0
  40. package/src/foreground-marker-cas-win32.mjs +284 -0
  41. package/src/foreground-process-identity.mjs +3 -3
  42. package/src/kernel-lock-r74.mjs +125 -0
  43. package/src/privileged-install-trust-r89.mjs +196 -0
  44. package/src/remote-session-guardian.mjs +9 -7
  45. package/src/runtime-update.mjs +5 -22
  46. package/src/version.mjs +1 -1
  47. package/src/windows-powershell-environment.mjs +24 -0
  48. package/test/atomic-mutation.test.mjs +68 -2
  49. package/test/cli-entrypoint.test.mjs +1 -1
  50. package/test/commander-schema-differential-r48.test.mjs +1 -1
  51. package/test/helpers/r75-authority-proof.mjs +9 -0
  52. package/test/r100-posix-owned-lock-race.test.mjs +72 -0
  53. package/test/r101-acl-probe-environment.test.mjs +51 -0
  54. package/test/r106-trusted-powershell-spawn.test.mjs +53 -0
  55. package/test/r107-updater-powershell-path.test.mjs +77 -0
  56. package/test/r33-closeout-regression.test.mjs +2 -1
  57. package/test/r54-offline-predecessor-self-exclusion.test.mjs +2 -2
  58. package/test/r55-offline-predecessor-guardian-family.test.mjs +2 -2
  59. package/test/r56-rollback-launcher-restore.test.mjs +2 -2
  60. package/test/r57-core-startup-race.test.mjs +2 -2
  61. package/test/r58-concurrent-recovery.test.mjs +10 -7
  62. package/test/r58-stale-owner.test.mjs +5 -6
  63. package/test/r59-tool-surface-compat.test.mjs +1 -1
  64. package/test/r65-activation-orchestration.test.mjs +2 -1
  65. package/test/r65-activation-preflight.test.mjs +7 -6
  66. package/test/r65-authority-epoch-recovery.test.mjs +3 -1
  67. package/test/r65-authority-restored-safe.test.mjs +2 -1
  68. package/test/r65-deploy-preflight.test.mjs +13 -14
  69. package/test/r65-epoch-native-activation-integration.test.mjs +5 -4
  70. package/test/r65-legacy-authority-migration.test.mjs +2 -1
  71. package/test/r67-npm-cross-volume.test.mjs +9 -2
  72. package/test/r71-full-verifier-artifact.test.mjs +21 -15
  73. package/test/r71-isolated-slot-rollback-restore.test.mjs +3 -1
  74. package/test/r71-release-identity.test.mjs +3 -1
  75. package/test/r73-package-boundary.test.mjs +22 -0
  76. package/test/r74-kernel-lock.test.mjs +156 -0
  77. package/test/r74-prepublish-contract.test.mjs +89 -0
  78. package/test/r75-activation-authority-proof.test.mjs +46 -0
  79. package/test/r75-authority-evidence.test.mjs +77 -0
  80. package/test/r76-pinned-marker-cas.test.mjs +78 -0
  81. package/test/r77-epoch-grant-cas.test.mjs +51 -0
  82. package/test/r78-parent-junction-cas.test.mjs +62 -0
  83. package/test/r79-orphan-revocation-reconcile.test.mjs +88 -0
  84. package/test/r79-windows-fsync-regression.test.mjs +45 -0
  85. package/test/r80-durable-epoch-commit.test.mjs +76 -0
  86. package/test/r82-epoch-lock-owned-cas.test.mjs +93 -0
  87. package/test/r83-epoch-lock-fileid-cas.test.mjs +92 -0
  88. package/test/r84-epoch-lock-created-fileid.test.mjs +112 -0
  89. package/test/r85-epoch-lock-release-lifetime.test.mjs +25 -0
  90. package/test/r85-epoch-repeat-append.test.mjs +30 -0
  91. package/test/r86-epoch-cleanup-and-loader.test.mjs +126 -0
  92. package/test/r87-crashed-orphan-revoke-reconcile.test.mjs +110 -0
  93. package/test/r88-native-disposition-failure.test.mjs +35 -0
  94. package/test/r89-privileged-install-boundary.test.mjs +123 -0
  95. package/test/r92-acl-ace-applicability.test.mjs +45 -0
  96. package/test/r94-win32-propagation-enum.test.mjs +51 -0
  97. package/test/r99-privileged-import-closure.test.mjs +45 -0
  98. package/test/remote-session-cli.test.mjs +69 -9
@@ -0,0 +1,77 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import childProcess from 'node:child_process';
4
+ import {syncBuiltinESMExports} from 'node:module';
5
+ import {mkdtemp,writeFile,rm} from 'node:fs/promises';
6
+ import os from 'node:os';
7
+ import path from 'node:path';
8
+ import {loadPowerShellDataFile,runControllerStartNoCapture,windowsPowerShellEnvironment} from '../src/runtime-update.mjs';
9
+
10
+ test('updater PowerShell environment rejects case-colliding Windows root keys',()=>{
11
+ const environment=windowsPowerShellEnvironment({
12
+ SystemRoot:'C:\\Windows',SYSTEMROOT:'C:\\untrusted-root',
13
+ WINDIR:'C:\\Windows',windir:'C:\\untrusted-root'
14
+ });
15
+ assert.deepEqual(Object.keys(environment).filter(key=>key.toLowerCase()==='systemroot'),['SystemRoot']);
16
+ assert.deepEqual(Object.keys(environment).filter(key=>key.toLowerCase()==='windir'),['WINDIR']);
17
+ assert.equal(environment.SystemRoot,'C:\\Windows');
18
+ assert.equal(environment.WINDIR,'C:\\Windows');
19
+ });
20
+
21
+ test('real updater PowerShell still loads read-only config under poisoned Windows roots',
22
+ {skip:process.platform!=='win32',concurrency:false},async()=>{
23
+ const scratch=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r107-ps-'));
24
+ const priorRoot=process.env.SystemRoot;
25
+ const priorWindir=process.env.WINDIR;
26
+ try{
27
+ const config=path.join(scratch,'config.psd1');
28
+ await writeFile(config,"@{ Schema = 'r107.test'; Enabled = $true }\n",{flag:'wx'});
29
+ process.env.SystemRoot='C:\\untrusted-root';
30
+ process.env.WINDIR='C:\\untrusted-root';
31
+ assert.deepEqual(await loadPowerShellDataFile(config),{Enabled:true,Schema:'r107.test'});
32
+ }finally{
33
+ if(priorRoot===undefined)delete process.env.SystemRoot;
34
+ else process.env.SystemRoot=priorRoot;
35
+ if(priorWindir===undefined)delete process.env.WINDIR;
36
+ else process.env.WINDIR=priorWindir;
37
+ await rm(scratch,{recursive:true,force:true});
38
+ }
39
+ });
40
+
41
+ test('runtime updater cannot launch caller-selected PowerShell for config and controller work',
42
+ {skip:process.platform!=='win32',concurrency:false},async()=>{
43
+ const originalSpawn=childProcess.spawnSync;
44
+ const originalRoot=process.env.SystemRoot;
45
+ const originalWindir=process.env.WINDIR;
46
+ let call=null;
47
+ try{
48
+ process.env.SystemRoot='C:\\untrusted-root';
49
+ process.env.WINDIR='C:\\untrusted-root';
50
+ childProcess.spawnSync=(file,args,options)=>{
51
+ call={file,args,options};
52
+ return {status:0,signal:null,error:null,stdout:'{}\n',stderr:''};
53
+ };
54
+ syncBuiltinESMExports();
55
+ assert.deepEqual(await loadPowerShellDataFile('C:\\scratch\\controller.psd1'),{});
56
+ assert.ok(call,'updater must dispatch its PowerShell subprocess');
57
+ assert.equal(call.file,'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe');
58
+ assert.equal(call.options.env.SystemRoot,'C:\\Windows');
59
+ assert.equal(call.options.env.WINDIR,'C:\\Windows');
60
+ assert.equal(call.options.shell,undefined);
61
+ call=null;
62
+ const started=runControllerStartNoCapture({kind:'legacy',
63
+ controller_path:'C:\\scratch\\deadbyte-controller.ps1',cwd:'C:\\scratch'},1000);
64
+ assert.equal(started.status,0);
65
+ assert.equal(call.file,'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe');
66
+ assert.ok(call.args.includes('start'));
67
+ assert.equal(call.options.env.SystemRoot,'C:\\Windows');
68
+ assert.equal(call.options.env.WINDIR,'C:\\Windows');
69
+ }finally{
70
+ childProcess.spawnSync=originalSpawn;
71
+ syncBuiltinESMExports();
72
+ if(originalRoot===undefined)delete process.env.SystemRoot;
73
+ else process.env.SystemRoot=originalRoot;
74
+ if(originalWindir===undefined)delete process.env.WINDIR;
75
+ else process.env.WINDIR=originalWindir;
76
+ }
77
+ });
@@ -4,13 +4,14 @@ import { createHash } from 'node:crypto';
4
4
  import { mkdtemp, mkdir, readFile, rm, writeFile, readdir } from 'node:fs/promises';
5
5
  import os from 'node:os';
6
6
  import path from 'node:path';
7
+ import {fileURLToPath} from 'node:url';
7
8
  import { spawn } from 'node:child_process';
8
9
  import * as parity from '../scripts/release-parity-r39.mjs';
9
10
  import { createToolAudit } from '../src/tool-audit.mjs';
10
11
  import { verifyAuditChain } from '../src/audit-verify.mjs';
11
12
  import { generateTrustKeypair } from '../src/trust.mjs';
12
13
 
13
- const root = path.resolve(new URL('../', import.meta.url).pathname.replace(/^\/(?:([A-Za-z]:))/,'$1'));
14
+ const root = path.resolve(fileURLToPath(new URL('../', import.meta.url)));
14
15
  const sha256 = bytes => createHash('sha256').update(bytes).digest('hex');
15
16
  const temp = prefix => mkdtemp(path.join(os.tmpdir(), prefix));
16
17
  const run = (command,args,options={}) => new Promise((resolve,reject)=>{
@@ -1,11 +1,11 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { pathToFileURL } from 'node:url';
3
+ import { fileURLToPath,pathToFileURL } from 'node:url';
4
4
  import path from 'node:path';
5
5
 
6
6
  const target=process.env.R54_RUNTIME_UPDATE_PATH
7
7
  ? path.resolve(process.env.R54_RUNTIME_UPDATE_PATH)
8
- : path.resolve(new URL('../src/runtime-update.mjs',import.meta.url).pathname.replace(/^\/(?:[A-Za-z]:)/,m=>m.slice(1)));
8
+ : fileURLToPath(new URL('../src/runtime-update.mjs',import.meta.url));
9
9
  const runtimeUpdate=await import(pathToFileURL(target).href+'?r54='+Date.now());
10
10
 
11
11
  test('R54 exposes behavior-testable offline recovery blocker selection',()=>{
@@ -1,11 +1,11 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { pathToFileURL } from 'node:url';
3
+ import { fileURLToPath,pathToFileURL } from 'node:url';
4
4
  import path from 'node:path';
5
5
 
6
6
  const target=process.env.R55_RUNTIME_UPDATE_PATH
7
7
  ? path.resolve(process.env.R55_RUNTIME_UPDATE_PATH)
8
- : path.resolve(new URL('../src/runtime-update.mjs',import.meta.url).pathname.replace(/^\/(?:[A-Za-z]:)/,m=>m.slice(1)));
8
+ : fileURLToPath(new URL('../src/runtime-update.mjs',import.meta.url));
9
9
  const runtimeUpdate=await import(pathToFileURL(target).href+'?r55='+Date.now());
10
10
  const nonce='a'.repeat(64);
11
11
 
@@ -2,13 +2,13 @@ import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import { createHash } from 'node:crypto';
4
4
  import { readFile } from 'node:fs/promises';
5
- import { pathToFileURL } from 'node:url';
5
+ import { fileURLToPath,pathToFileURL } from 'node:url';
6
6
  import os from 'node:os';
7
7
  import path from 'node:path';
8
8
 
9
9
  const target=process.env.R56_RUNTIME_UPDATE_PATH
10
10
  ? path.resolve(process.env.R56_RUNTIME_UPDATE_PATH)
11
- : path.resolve(new URL('../src/runtime-update.mjs',import.meta.url).pathname.replace(/^\/(?:[A-Za-z]:)/,m=>m.slice(1)));
11
+ : fileURLToPath(new URL('../src/runtime-update.mjs',import.meta.url));
12
12
  const runtimeUpdate=await import(pathToFileURL(target).href+'?r56='+Date.now());
13
13
  const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
14
14
  const stateRoot=path.resolve(process.env.R56_STATE_ROOT||path.join(os.homedir(),'.deadbyte-mcp'));
@@ -1,12 +1,12 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import { readFile } from 'node:fs/promises';
4
- import { pathToFileURL } from 'node:url';
4
+ import { fileURLToPath,pathToFileURL } from 'node:url';
5
5
  import path from 'node:path';
6
6
 
7
7
  const target=process.env.R57_RUNTIME_UPDATE_PATH
8
8
  ? path.resolve(process.env.R57_RUNTIME_UPDATE_PATH)
9
- : path.resolve(new URL('../src/runtime-update.mjs',import.meta.url).pathname.replace(/^\/(?:[A-Za-z]:)/,m=>m.slice(1)));
9
+ : fileURLToPath(new URL('../src/runtime-update.mjs',import.meta.url));
10
10
  const runtimeUpdate=await import(pathToFileURL(target).href+'?r57='+Date.now());
11
11
  const coreRoot='C:\\slot\\core';
12
12
  const bridge={pid:20396,component:'bridge',script_path:'C:\\slot\\bridge\\src\\bridge.mjs',script_sha256:'a'.repeat(64)};
@@ -6,7 +6,7 @@ import {fileURLToPath} from 'node:url';
6
6
  import {spawn} from 'node:child_process';
7
7
  import {setTimeout as delay} from 'node:timers/promises';
8
8
 
9
- test('R58 simultaneous stale recovery cannot both revoke the shared authority', {timeout:90000},async()=>{
9
+ test('R75 simultaneous owner-unverified recovery attempts both retain authority and marker', {timeout:30000},async()=>{
10
10
  const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});
11
11
  const root=await mkdtemp(path.join(base,'concurrent-recovery-'));await mkdir(path.join(root,'bin'));await mkdir(path.join(root,'runtime'));
12
12
  const trace=path.join(root,'trace.txt'),markerPath=path.join(root,'runtime','remote-session.json');
@@ -47,14 +47,17 @@ exit 0
47
47
  const c=spawn(process.execPath,[fileURLToPath(new URL('../src/deadbyte-cli.mjs',import.meta.url)),'remote'],{env:{...process.env,DEADBYTE_STATE_ROOT:root},stdio:['pipe','pipe','pipe'],windowsHide:true});
48
48
  const o={stdout:'',stderr:''};c.stdout.on('data',b=>{o.stdout+=b;});c.stderr.on('data',b=>{o.stderr+=b;});o.exit=new Promise(resolve=>c.once('exit',resolve));children.push(c);outputs.push(o);
49
49
  }
50
- const until=Date.now()+45000;let commands=[];
51
- while(Date.now()<until){try{commands=(await readFile(trace,'utf8')).trim().split(/\r?\n/);}catch{}if(outputs.some(o=>o.stdout.includes('[READY]')))break;await delay(50);}
52
- await writeFile(path.join(root,'observation.json'),JSON.stringify({commands,outputs:outputs.map(o=>({stdout:o.stdout,stderr:o.stderr})),simulation:'concurrent stale marker recovery with delayed second park'}),{flag:'wx'});
53
- assert.ok(outputs.some(o=>o.stdout.includes('[READY]')),'a recovered foreground must become ready');
54
- for(const cmd of ['disarmautonomous','disarmcoding','disarmprocess','disarmdesktop','disarmhost'])assert.equal(commands.filter(x=>x===cmd).length,1,`stale recovery must serialize ${cmd}`);
50
+ const exits=await Promise.race([Promise.all(outputs.map(o=>o.exit)),delay(15000,null,{ref:false}).then(()=>null)]);
51
+ assert.ok(exits,'both owner-unverified attempts must terminate');
52
+ const commands=await readFile(trace,'utf8').catch(error=>error.code==='ENOENT'?'':Promise.reject(error));
53
+ await writeFile(path.join(root,'observation.json'),JSON.stringify({commands,exits,outputs:outputs.map(o=>({stdout:o.stdout,stderr:o.stderr})),simulation:'concurrent owner-unverified stale marker'}),{flag:'wx'});
54
+ assert.ok(exits.every(code=>code!==0));
55
+ for(const output of outputs)assert.match(output.stderr,/ownership unverified.*marker retained|already claimed \(startup\/recovery lock\)/i);
56
+ assert.equal(commands,'','neither attempt may touch authority');
57
+ assert.equal(JSON.parse(await readFile(markerPath,'utf8')).pid,2147483000);
55
58
  }finally{
56
59
  for(const c of children)if(c.exitCode===null)c.stdin.end();
57
- await Promise.race([Promise.all(outputs.map(o=>o.exit)),delay(30000)]);
60
+ await Promise.race([Promise.all(outputs.map(o=>o.exit)),delay(30000,null,{ref:false})]);
58
61
  for(const c of children)if(c.exitCode===null&&c.signalCode===null)c.kill();
59
62
  }
60
63
  });
@@ -46,7 +46,7 @@ test('R58 live unrelated PID is not accepted as a remote foreground owner', {tim
46
46
  assert.notEqual(code,0);
47
47
  });
48
48
 
49
- test('R58 bound stale birth identity reconciles on the first invocation without killing a reused PID', {timeout:60000}, async()=>{
49
+ test('R75 bound stale birth identity retains marker without touching a reused PID or authority', {timeout:60000}, async()=>{
50
50
  const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';
51
51
  await mkdir(base,{recursive:true});const root=await mkdtemp(path.join(base,'stale-birth-'));
52
52
  await mkdir(path.join(root,'runtime'));await mkdir(path.join(root,'bin'));
@@ -61,11 +61,10 @@ test('R58 bound stale birth identity reconciles on the first invocation without
61
61
  let stdout='',stderr='';child.stdout.on('data',b=>{stdout+=b;});child.stderr.on('data',b=>{stderr+=b;});
62
62
  const code=await new Promise(resolve=>child.once('close',resolve));
63
63
  await writeFile(path.join(root,'observation.json'),JSON.stringify({code,stdout,stderr,simulation:'birth identity drift at a live unrelated numeric PID'}),{flag:'wx'});
64
- assert.match(stdout,/Stale remote session/);
65
- assert.doesNotMatch(stderr,/already active|ownership unverified/);
66
- assert.deepEqual((await readFile(trace,'utf8')).trim().split(/\r?\n/).slice(0,7),['disarmautonomous','disarmcoding','disarmprocess','disarmdesktop','disarmhost','status','park']);
67
- assert.match(stderr,/without a verified ONLINE runtime/,'fixture deliberately has no real runtime; recovery must already have converged');
68
- await assert.rejects(readFile(markerPath),{code:'ENOENT'});
64
+ assert.notEqual(code,0);
65
+ assert.match(stderr,/owner identity mismatch; marker retained/i);
66
+ assert.equal(await readFile(trace,'utf8').catch(error=>error.code==='ENOENT'?'':Promise.reject(error)),'','identity drift must cause no authority commands');
67
+ assert.deepEqual(JSON.parse(await readFile(markerPath,'utf8')),marker);
69
68
  assert.equal(foregroundAlive(),true,'unrelated live process must not be killed');
70
69
  function foregroundAlive(){try{process.kill(process.pid,0);return true;}catch{return false;}}
71
70
  });
@@ -83,7 +83,7 @@ test('R72 compact baseline permits only R64 read offset and authorized coding-on
83
83
  assert.deepEqual(diff.added,[]);
84
84
  assert.deepEqual(diff.removed,[]);
85
85
  const packageVersion=JSON.parse(await readFile(path.join(repoRoot,'package.json'),'utf8')).version;
86
- if(['0.15.41','0.15.42','0.15.43','0.15.44','0.15.45','0.15.46'].includes(packageVersion)){
86
+ if(['0.15.41','0.15.42','0.15.43','0.15.44','0.15.45','0.15.46','0.15.47','0.15.48'].includes(packageVersion)){
87
87
  assert.deepEqual([...diff.schema_changed].sort(),['machine_fs','native_diff_preview']);
88
88
  assert.equal(diff.unchanged.length,41);
89
89
  const prior=baseline.tools.find(tool=>tool.name==='machine_fs');
@@ -1,6 +1,7 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import {orchestrateActivation} from '../src/activation-preflight-r65.mjs';
4
+ import {withAuthorityProof} from './helpers/r75-authority-proof.mjs';
4
5
 
5
6
  const parent={release_id:'v0.15.41-63a78ad159ad3003',version:'0.15.41',manifest_sha256:'63a78ad159ad3003db3fefafcd468bef22599c829a867f4f10a46c7a20748b3e',generation_manifest_sha256:'19ae2efcdcde9f80c474f0e55851d4ada51c22813d3e05af03b11acb28c3fca5'};
6
7
  const candidate={version:'0.15.42',manifest_sha256:'a'.repeat(64)};
@@ -19,7 +20,7 @@ function fixture(initial={}){
19
20
  let current={state:'ONLINE',local_ready:true,...ids,supervisor:{running:true},authority:authorityEntries(initialVector,initial.epochNative===true),policy_sha256:policies,
20
21
  active_release_id:parent.release_id,active_manifest_sha256:parent.manifest_sha256,active_generation_manifest_sha256:parent.generation_manifest_sha256,...initial};
21
22
  if(initial.authority)current={...current,authority:authorityEntries(initial.authority,initial.epochNative===true)};
22
- return {calls,observe:async()=>current,command:async name=>{
23
+ return {calls,observe:async()=>withAuthorityProof(current),command:async name=>{
23
24
  calls.push(name);
24
25
  if(name.startsWith('disarm')){
25
26
  const plane=name.slice(6);
@@ -1,6 +1,7 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import {classifyActivationPreflight,authorityTransitionPlan} from '../src/activation-preflight-r65.mjs';
4
+ import {withAuthorityProof} from './helpers/r75-authority-proof.mjs';
4
5
 
5
6
  const parent={release_id:'v0.15.41-63a78ad159ad3003',version:'0.15.41',manifest_sha256:'63a78ad159ad3003db3fefafcd468bef22599c829a867f4f10a46c7a20748b3e',generation_manifest_sha256:'19ae2efcdcde9f80c474f0e55851d4ada51c22813d3e05af03b11acb28c3fca5'};
6
7
  const candidate={version:'0.15.42',manifest_sha256:'a'.repeat(64)};
@@ -8,7 +9,7 @@ const authority={process:true,coding:true,autonomous:true,desktop:false,host:fal
8
9
  const policies={process:'1'.repeat(64),coding:'2'.repeat(64),autonomous:'3'.repeat(64),desktop:'4'.repeat(64),host:'5'.repeat(64)};
9
10
  const online={state:'ONLINE',local_ready:true,bridge:{alive:true,reason:'verified',pid:10},core:{alive:true,reason:'verified',pid:11},cloud:{alive:true,reason:'verified',pid:12},supervisor:{running:true},authority,policy_sha256:policies,
10
11
  active_release_id:parent.release_id,active_manifest_sha256:parent.manifest_sha256,active_generation_manifest_sha256:parent.generation_manifest_sha256};
11
- const input={pointer:parent,expectedParent:parent,candidate,expectedCandidate:candidate,observation:online};
12
+ const input={pointer:parent,expectedParent:parent,candidate,expectedCandidate:candidate,observation:withAuthorityProof(online)};
12
13
 
13
14
  test('preflight accepts exact online predecessor with full observed identity and authority vector',()=>{
14
15
  const result=classifyActivationPreflight(input);
@@ -19,7 +20,7 @@ test('preflight accepts exact online predecessor with full observed identity and
19
20
 
20
21
  test('host armed is not safe; plan only disarms Host and restores exact captured vector',()=>{
21
22
  const armed={...authority,host:true};
22
- const result=classifyActivationPreflight({...input,observation:{...online,authority:armed}});
23
+ const result=classifyActivationPreflight({...input,observation:withAuthorityProof({...online,authority:armed})});
23
24
  assert.equal(result.state,'ONLINE_HOST_ARMED');assert.equal(result.safe_to_activate,false);
24
25
  const plan=authorityTransitionPlan(result.authority);
25
26
  assert.deepEqual(plan.before,['disarmhost']);
@@ -27,9 +28,9 @@ test('host armed is not safe; plan only disarms Host and restores exact captured
27
28
  });
28
29
 
29
30
  test('parked dirty, generation drift and identity loss fail closed without an activation command',()=>{
30
- assert.equal(classifyActivationPreflight({...input,observation:{...online,state:'PARKED'}}).state,'PARKED_DIRTY');
31
+ assert.equal(classifyActivationPreflight({...input,observation:withAuthorityProof({...online,state:'PARKED'})}).state,'PARKED_DIRTY');
31
32
  assert.equal(classifyActivationPreflight({...input,pointer:{...parent,generation_manifest_sha256:'b'.repeat(64)}}).state,'POINTER_DRIFT');
32
- assert.equal(classifyActivationPreflight({...input,observation:{...online,active_release_id:'wrong'}}).state,'POINTER_DRIFT');
33
- assert.equal(classifyActivationPreflight({...input,observation:{...online,policy_sha256:{...policies,host:null}}}).state,'UNKNOWN');
34
- assert.equal(classifyActivationPreflight({...input,observation:{...online,cloud:{alive:false,reason:'missing'}}}).state,'RUNTIME_DRIFT');
33
+ assert.equal(classifyActivationPreflight({...input,observation:withAuthorityProof({...online,active_release_id:'wrong'})}).state,'POINTER_DRIFT');
34
+ assert.equal(classifyActivationPreflight({...input,observation:withAuthorityProof({...online,policy_sha256:{...policies,host:null}})}).state,'UNKNOWN');
35
+ assert.equal(classifyActivationPreflight({...input,observation:withAuthorityProof({...online,cloud:{alive:false,reason:'missing'}})}).state,'RUNTIME_DRIFT');
35
36
  });
@@ -19,7 +19,9 @@ test('dead-owner epoch lock is recovered but a live-owner lock is never stolen',
19
19
  const runtime=await prepareAuthorityTestTrust(root);
20
20
  const dir=path.join(runtime,'authority-epochs','coding');
21
21
  await mkdir(dir,{recursive:true});
22
- await writeFile(path.join(dir,'.lock'),JSON.stringify({schema:'deadbyte.authority-epoch-lock.r65.v1',pid:2147483647,token:'dead',created_at_utc:'2026-10-06T00:00:00Z'}));
22
+ await writeFile(path.join(dir,'.lock'),JSON.stringify({schema:'deadbyte.authority-epoch-lock.r65.v1',pid:2147483647,token:'dead',created_at_utc:'2026-10-06T00:00:00Z',
23
+ owner_identity:{schema:'deadbyte.foreground-process.v1',pid:2147483647,parent_pid:0,creation_utc:'2026-01-01T00:00:00Z',
24
+ executable_path:process.execPath,command_line_sha256:'0'.repeat(64)}}));
23
25
  const store=createAuthorityEpochStore({runtimeDir:runtime});
24
26
  const nonce='1'.repeat(64),grant=grantBytes(nonce);
25
27
  const head=await store.append({plane:'coding',action:'grant',grantBytes:grant,grantInstanceNonce:nonce,updateId:null});
@@ -7,6 +7,7 @@ import path from 'node:path';
7
7
  import {orchestrateActivation} from '../src/activation-preflight-r65.mjs';
8
8
  import {createAuthorityEpochStore} from '../src/authority-continuity-r65.mjs';
9
9
  import {createEpochNativeContinuityEngine} from '../src/activation-continuity-engine-r65.mjs';
10
+ import {withAuthorityProof} from './helpers/r75-authority-proof.mjs';
10
11
 
11
12
  const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
12
13
  const parent={release_id:'v0.15.41-parent',version:'0.15.41',manifest_sha256:'a'.repeat(64),generation_manifest_sha256:'b'.repeat(64)};
@@ -26,7 +27,7 @@ test('orchestrator reports RESTORED_SAFE when all restored authority is safe but
26
27
  return {authority_outcomes:{process:'RESTORED_SAFE',coding:'NOT_APPLICABLE',autonomous:'NOT_APPLICABLE',desktop:'NOT_APPLICABLE',host:'NOT_APPLICABLE'},restored_nonces:{process:'8'.repeat(64)},reauth_planes:[]};}
27
28
  };
28
29
  const result=await orchestrateActivation({pointer:parent,expectedParent:parent,candidate,expectedCandidate:candidate,
29
- observe:async()=>current,command:async()=>{throw new Error('generic command forbidden');},
30
+ observe:async()=>withAuthorityProof(current),command:async()=>{throw new Error('generic command forbidden');},
30
31
  activate:async()=>({verified:true,release_id:'v0.15.42-candidate'}),continuityEngine});
31
32
  assert.equal(result.state,'ACTIVATED');
32
33
  assert.equal(result.authority_continuity,'RESTORED_SAFE');
@@ -11,8 +11,9 @@ const root=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
11
11
  test('deploy dry preflight observes isolated authority without opening an update transaction', {skip:process.platform!=='win32'},async()=>{
12
12
  const isolated=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-deploy-preflight-'));
13
13
  try{
14
- const state=path.join(isolated,'state'),bin=path.join(state,'bin');
14
+ const state=path.join(isolated,'state'),bin=path.join(state,'bin'),runtime=path.join(state,'runtime');
15
15
  await mkdir(bin,{recursive:true});
16
+ await mkdir(runtime,{recursive:true});
16
17
  const release=JSON.parse(await readFile(path.join(root,'RELEASE.json'),'utf8'));
17
18
  const parent=release.parent;
18
19
  const generationRoot=path.join(state,'generations',`${parent.release_id}-fixture`);
@@ -20,9 +21,11 @@ test('deploy dry preflight observes isolated authority without opening an update
20
21
  await mkdir(generationRoot,{recursive:true});await mkdir(policyRoot,{recursive:true});
21
22
  const fields={process:'ProcessPolicyFile',coding:'CodingPolicyFile',autonomous:'AutonomousPolicyFile',desktop:'DesktopPolicyFile',host:'HostPolicyFile'};
22
23
  const policyLines=[];
24
+ const grantField={process:'grant_file',coding:'lease_file',autonomous:'lease_file',desktop:'grant_file',host:'arm_file'};
23
25
  for(const [plane,key] of Object.entries(fields)){
24
26
  const file=path.join(policyRoot,`${plane}.json`);
25
- await writeFile(file,JSON.stringify({schema:`fixture.${plane}`,enabled:true}));
27
+ await writeFile(file,JSON.stringify({schema:`deadbyte.${plane}-policy.v${plane==='host'?2:1}`,enabled:true,
28
+ [grantField[plane]]:path.join(runtime,`${plane}-grant.json`)}));
26
29
  policyLines.push(`${key} = '${file.replaceAll("'","''")}'`);
27
30
  }
28
31
  await writeFile(path.join(generationRoot,'controller-config.psd1'),`@{ ${policyLines.join('; ')} }\n`);
@@ -30,26 +33,22 @@ test('deploy dry preflight observes isolated authority without opening an update
30
33
  release_root:path.join(state,'releases',parent.release_id),generation_root:generationRoot,
31
34
  launcher_sha256:'a'.repeat(64),config_path:path.join(generationRoot,'controller-config.psd1')}));
32
35
  const ps1=`param([string]$Command,[switch]$Json)\nif($Command -ne 'status' -or -not $Json){throw 'unexpected mutating command'}\n@{schema='deadbyte.controller-observation.v1';state='ONLINE';local_ready=$true;bridge=@{alive=$true;reason='verified';pid=10};core=@{alive=$true;reason='verified';pid=11};cloud=@{alive=$true;reason='verified';pid=12};supervisor=@{running=$true};authority=@{process=@{armed=$true;configured=$true;reason='fixture'};coding=@{armed=$true;configured=$true;reason='fixture'};autonomous=@{armed=$true;configured=$true;reason='fixture'};desktop=@{armed=$false;configured=$true;reason='fixture'};host=@{armed=$false;configured=$true;reason='fixture'}}} | ConvertTo-Json -Depth 6 -Compress\n`;
33
- await writeFile(path.join(bin,'DEADBYTE-MCP.ps1'),ps1);
36
+ const cleanPs1=ps1.replaceAll('armed=$true','armed=$false').replaceAll("reason='fixture'","reason='disarmed'");
37
+ await writeFile(path.join(bin,'DEADBYTE-MCP.ps1'),cleanPs1);
34
38
  const run=spawnSync(process.execPath,[path.join(root,'scripts','deploy-r48.mjs'),'--preflight'],{
35
39
  env:{...process.env,DEADBYTE_STATE_ROOT:state},cwd:root,encoding:'utf8',timeout:20000,windowsHide:true});
36
40
  assert.equal(run.status,0,run.stderr);
37
41
  const result=JSON.parse(run.stdout.trim());
38
42
  assert.equal(result.state,'ONLINE_READY');
39
- assert.equal(result.authority_continuity,'REAUTH_REQUIRED');
40
- assert.deepEqual(result.reauth_planes,['process','coding','autonomous']);
41
- const hostOnly=ps1.replace('process=@{armed=$true','process=@{armed=$false')
42
- .replace('coding=@{armed=$true','coding=@{armed=$false')
43
- .replace('autonomous=@{armed=$true','autonomous=@{armed=$false')
44
- .replace('host=@{armed=$false','host=@{armed=$true');
45
- await writeFile(path.join(bin,'DEADBYTE-MCP.ps1'),hostOnly);
43
+ assert.equal(result.authority_continuity,'NOT_APPLICABLE');
44
+ assert.deepEqual(result.reauth_planes,[]);
45
+ const unverified=cleanPs1.replace("host=@{armed=$false;configured=$true;reason='disarmed'", "host=@{armed=$false;configured=$true;reason='unverified'");
46
+ await writeFile(path.join(bin,'DEADBYTE-MCP.ps1'),unverified);
46
47
  const hostRun=spawnSync(process.execPath,[path.join(root,'scripts','deploy-r48.mjs'),'--preflight'],{
47
48
  env:{...process.env,DEADBYTE_STATE_ROOT:state},cwd:root,encoding:'utf8',timeout:20000,windowsHide:true});
48
49
  assert.equal(hostRun.status,0,hostRun.stderr);
49
50
  const hostResult=JSON.parse(hostRun.stdout.trim());
50
- assert.equal(hostResult.state,'ONLINE_HOST_ARMED');
51
- assert.equal(hostResult.authority_continuity,'REAUTH_REQUIRED');
52
- assert.deepEqual(hostResult.reauth_planes,['host']);
53
- assert.deepEqual((await readdir(state)).sort(),['active-release.json','bin','generations','policies']);
51
+ assert.equal(hostResult.state,'AUTHORITY_UNVERIFIED');
52
+ assert.deepEqual((await readdir(state)).sort(),['active-release.json','bin','generations','policies','runtime']);
54
53
  }finally{await rm(isolated,{recursive:true,force:true});}
55
54
  });
@@ -7,6 +7,7 @@ import path from 'node:path';
7
7
  import {orchestrateActivation} from '../src/activation-preflight-r65.mjs';
8
8
  import {createAuthorityEpochStore} from '../src/authority-continuity-r65.mjs';
9
9
  import {createEpochNativeContinuityEngine} from '../src/activation-continuity-engine-r65.mjs';
10
+ import {withAuthorityProof} from './helpers/r75-authority-proof.mjs';
10
11
 
11
12
  const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
12
13
  const parent={release_id:'v0.15.41-parent',version:'0.15.41',manifest_sha256:'a'.repeat(64),generation_manifest_sha256:'b'.repeat(64)};
@@ -44,7 +45,7 @@ test('epoch-native orchestrator handles BOM-encoded process grant with transacti
44
45
  const grant=JSON.parse(new TextDecoder('utf-8',{fatal:true}).decode(bytes));
45
46
  armed=(await store.verifyGrant({plane:'process',grantBytes:bytes,grantInstanceNonce:grant.instance_nonce,policyBytes})).trusted;
46
47
  }
47
- return {state:'ONLINE',local_ready:true,...ids,supervisor:{running:true},authority:{
48
+ return withAuthorityProof({state:'ONLINE',local_ready:true,...ids,supervisor:{running:true},authority:{
48
49
  process:{configured:true,armed,reason:armed?'standing-grant':'disarmed',epoch_seq:armed?head.seq:null,epoch_sha256:armed?head.event_sha256:null},
49
50
  coding:{configured:true,armed:false,reason:'disarmed',epoch_seq:null,epoch_sha256:null},
50
51
  autonomous:{configured:true,armed:false,reason:'disarmed',epoch_seq:null,epoch_sha256:null},
@@ -53,7 +54,7 @@ test('epoch-native orchestrator handles BOM-encoded process grant with transacti
53
54
  },policy_sha256:{process:sha(policyBytes),...dummy},
54
55
  active_release_id:switched?'v0.15.42-candidate':parent.release_id,
55
56
  active_manifest_sha256:switched?candidate.manifest_sha256:parent.manifest_sha256,
56
- active_generation_manifest_sha256:switched?'9'.repeat(64):parent.generation_manifest_sha256};
57
+ active_generation_manifest_sha256:switched?'9'.repeat(64):parent.generation_manifest_sha256});
57
58
  };
58
59
  const engine=createEpochNativeContinuityEngine({stateRoot:state,
59
60
  predecessorPolicyPaths:{process:beforePath,coding:null,autonomous:null,desktop:null,host:null},
@@ -107,7 +108,7 @@ test('epoch-native explicit user revoke after transaction revoke wins over orche
107
108
  const grant=JSON.parse(new TextDecoder('utf-8',{fatal:true}).decode(bytes));
108
109
  armed=(await store.verifyGrant({plane:'process',grantBytes:bytes,grantInstanceNonce:grant.instance_nonce,policyBytes})).trusted;
109
110
  }
110
- return {state:'ONLINE',local_ready:true,...ids,supervisor:{running:true},authority:{
111
+ return withAuthorityProof({state:'ONLINE',local_ready:true,...ids,supervisor:{running:true},authority:{
111
112
  process:{configured:true,armed,reason:armed?'standing-grant':'disarmed',epoch_seq:armed?head.seq:null,epoch_sha256:armed?head.event_sha256:null},
112
113
  coding:{configured:true,armed:false,reason:'disarmed',epoch_seq:null,epoch_sha256:null},
113
114
  autonomous:{configured:true,armed:false,reason:'disarmed',epoch_seq:null,epoch_sha256:null},
@@ -116,7 +117,7 @@ test('epoch-native explicit user revoke after transaction revoke wins over orche
116
117
  },policy_sha256:{process:sha(policyBytes),...dummy},
117
118
  active_release_id:switched?'v0.15.42-candidate':parent.release_id,
118
119
  active_manifest_sha256:switched?candidate.manifest_sha256:parent.manifest_sha256,
119
- active_generation_manifest_sha256:switched?'9'.repeat(64):parent.generation_manifest_sha256};
120
+ active_generation_manifest_sha256:switched?'9'.repeat(64):parent.generation_manifest_sha256});
120
121
  };
121
122
  const engine=createEpochNativeContinuityEngine({stateRoot:state,
122
123
  predecessorPolicyPaths:{process:beforePath,coding:null,autonomous:null,desktop:null,host:null},
@@ -1,6 +1,7 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import {classifyAuthorityContinuity,orchestrateActivation} from '../src/activation-preflight-r65.mjs';
4
+ import {withAuthorityProof} from './helpers/r75-authority-proof.mjs';
4
5
 
5
6
  const parent={release_id:'v0.15.41-parent',version:'0.15.41',manifest_sha256:'1'.repeat(64),generation_manifest_sha256:'2'.repeat(64)};
6
7
  const candidate={version:'0.15.42',manifest_sha256:'3'.repeat(64)};
@@ -15,7 +16,7 @@ function fixture(vector){
15
16
  authority:Object.fromEntries(Object.entries(vector).map(([plane,armed])=>[plane,legacyEntry(armed)]))};
16
17
  return {
17
18
  calls,
18
- observe:async()=>observation,
19
+ observe:async()=>withAuthorityProof(observation),
19
20
  command:async command=>{
20
21
  calls.push(command);
21
22
  if(command.startsWith('disarm')){
@@ -13,8 +13,15 @@ const artifact=Buffer.concat([Buffer.from('R67 immutable npm tarball fixture\\n'
13
13
  const integrity='sha512-'+digest(artifact,'sha512');
14
14
 
15
15
  async function fixture(fn){
16
- await mkdir(path.join(root,'tmp'),{recursive:true});
17
- const srcDir=await mkdtemp(path.join(root,'tmp','r67-xdev-src-'));
16
+ const scratch=path.resolve(process.env.DEADBYTE_TEST_CROSS_VOLUME_ROOT||path.join(root,'tmp'));
17
+ if(path.parse(scratch).root.toLowerCase()===path.parse(tmpdir()).root.toLowerCase())
18
+ throw new Error('R67 cross-volume test requires source scratch on a different volume from TEMP');
19
+ if(process.env.DEADBYTE_TEST_CROSS_VOLUME_ROOT&&
20
+ (scratch.toLowerCase()===root.toLowerCase()||
21
+ scratch.toLowerCase().startsWith((root+path.sep).toLowerCase())))
22
+ throw new Error('R67 explicit scratch must be outside the installation root');
23
+ await mkdir(scratch,{recursive:true});
24
+ const srcDir=await mkdtemp(path.join(scratch,'r67-xdev-src-'));
18
25
  const dstDir=await mkdtemp(path.join(tmpdir(),'r67-xdev-dst-'));
19
26
  const source=path.join(srcDir,'deadbyte-mcp-0.15.44.tgz');
20
27
  const destination=path.join(dstDir,'deadbyte-mcp-0.15.44.tgz');
@@ -1,8 +1,9 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import {createHash} from 'node:crypto';
4
- import {readFile} from 'node:fs/promises';
4
+ import {mkdtemp,readFile,rm} from 'node:fs/promises';
5
5
  import {spawnSync} from 'node:child_process';
6
+ import os from 'node:os';
6
7
  import path from 'node:path';
7
8
  import {fileURLToPath} from 'node:url';
8
9
 
@@ -11,18 +12,23 @@ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
11
12
 
12
13
  test('R71 full verifier persists the complete stdout bytes beside its no-clobber result',async t=>{
13
14
  if(process.platform!=='win32'){t.skip('Windows PowerShell verifier only');return;}
14
- const run=spawnSync('powershell.exe',['-NoProfile','-ExecutionPolicy','Bypass','-File',
15
- path.join(root,'scripts','verify-r70-full-regression.ps1'),'-SelfTest'],
16
- {cwd:root,encoding:'utf8',windowsHide:true,timeout:30_000});
17
- assert.equal(run.status,0,run.stderr||run.stdout);
18
- const resultPath=/R70_FULL_TEST_ARTIFACT=([^\r\n]+)/.exec(run.stdout)?.[1];
19
- assert.ok(resultPath,'durable result path missing');
20
- const result=JSON.parse(await readFile(resultPath,'utf8'));
21
- assert.equal(result.mode,'synthetic-selftest');
22
- assert.equal(result.exit_code,1);
23
- assert.equal(typeof result.stdout_path,'string');
24
- const output=await readFile(result.stdout_path);
25
- assert.equal(sha(output),result.stdout_sha256);
26
- assert.match(output.toString('utf8'),/hash mismatch: SYNTHETIC_TEST/);
27
- assert.equal(output.toString('utf8').trimEnd().split('\n').length,result.total_line_count);
15
+ const scratch=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r71-verifier-'));
16
+ try{
17
+ const run=spawnSync('powershell.exe',['-NoProfile','-ExecutionPolicy','Bypass','-File',
18
+ path.join(root,'scripts','verify-r70-full-regression.ps1'),'-SelfTest',
19
+ '-EvidenceRoot',path.join(scratch,'evidence')],
20
+ {cwd:root,encoding:'utf8',windowsHide:true,timeout:30_000});
21
+ assert.equal(run.status,0,run.stderr||run.stdout);
22
+ const resultPath=/R70_FULL_TEST_ARTIFACT=([^\r\n]+)/.exec(run.stdout)?.[1];
23
+ assert.ok(resultPath,'durable result path missing');
24
+ assert.ok(path.resolve(resultPath).startsWith(path.resolve(scratch)+path.sep));
25
+ const result=JSON.parse(await readFile(resultPath,'utf8'));
26
+ assert.equal(result.mode,'synthetic-selftest');
27
+ assert.equal(result.exit_code,1);
28
+ assert.equal(typeof result.stdout_path,'string');
29
+ const output=await readFile(result.stdout_path);
30
+ assert.equal(sha(output),result.stdout_sha256);
31
+ assert.match(output.toString('utf8'),/hash mismatch: SYNTHETIC_TEST/);
32
+ assert.equal(output.toString('utf8').trimEnd().split('\n').length,result.total_line_count);
33
+ }finally{await rm(scratch,{recursive:true,force:true});}
28
34
  });
@@ -8,6 +8,7 @@ import {fileURLToPath} from 'node:url';
8
8
  import {atomicWriteActivePointer,materializeReleaseSlot,parseActivePointer,parseManifest,renderStableLauncherPs1,verifyManifestTreeExact} from '../src/release-slot.mjs';
9
9
 
10
10
  const candidate=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
11
+ const currentVersion=JSON.parse(await readFile(path.join(candidate,'package.json'),'utf8')).version;
11
12
  const parent=path.join(os.homedir(),'.deadbyte-mcp','releases','v0.15.45-34aa8d1241cfb8bf');
12
13
  const parentManifestSha='34aa8d1241cfb8bf0b5ba303bf3c06e0e9e1bf01f64457bca659d6dd4d634fdc';
13
14
  const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
@@ -22,7 +23,8 @@ async function generation(state,label){
22
23
  return {root,manifest_sha256:sha(manifest),config_path:path.join(root,'controller-config.psd1')};
23
24
  }
24
25
 
25
- test('R72 isolated immutable slot activates, rolls back exact active R71, and restores same R72 bytes with no authority',async()=>{
26
+ test('R72 isolated immutable slot activates, rolls back exact active R71, and restores same R72 bytes with no authority',
27
+ {skip:currentVersion!=='0.15.46'?'historical R72 slot simulation; current development version differs':false},async()=>{
26
28
  const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r72-slot-parity-'));
27
29
  const state=path.join(base,'state');
28
30
  try{
@@ -3,11 +3,13 @@ import assert from 'node:assert/strict';
3
3
  import {readFile} from 'node:fs/promises';
4
4
 
5
5
  const json=async rel=>JSON.parse(await readFile(new URL('../'+rel,import.meta.url),'utf8'));
6
+ const currentVersion=(await json('package.json')).version;
6
7
  const parent={version:'0.15.45',release_id:'v0.15.45-34aa8d1241cfb8bf',
7
8
  manifest_sha256:'34aa8d1241cfb8bf0b5ba303bf3c06e0e9e1bf01f64457bca659d6dd4d634fdc',
8
9
  generation_manifest_sha256:'ff2b73410062688651abd7bc2dd7b2b8c87810a28e3808bfe1f4352a25b0e6e4'};
9
10
 
10
- test('R72 current source, package, bridge, provenance and Windows gate bind exact predecessor',async()=>{
11
+ test('R72 current source, package, bridge, provenance and Windows gate bind exact predecessor',
12
+ {skip:currentVersion!=='0.15.46'?'historical R72 release identity; current development version differs':false},async()=>{
11
13
  const [pkg,lock,bridge,release,provenance,matrix,sbom,version]=await Promise.all([
12
14
  json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
13
15
  json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),
@@ -0,0 +1,22 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {spawnSync} from 'node:child_process';
4
+ import path from 'node:path';
5
+ import {fileURLToPath} from 'node:url';
6
+
7
+ const root=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
8
+ const npmCli=process.env.npm_execpath || path.join(path.dirname(process.execPath),'node_modules','npm','bin','npm-cli.js');
9
+
10
+ test('R73 npm dry-run package excludes generated test evidence and reference trees',()=>{
11
+ const result=spawnSync(process.execPath,[npmCli,'pack','--dry-run','--json'],{
12
+ cwd:root,encoding:'utf8',timeout:120000,windowsHide:true,env:{...process.env,npm_config_audit:'false'}
13
+ });
14
+ assert.equal(result.error,undefined,String(result.error));
15
+ assert.equal(result.status,0,result.stderr||result.stdout);
16
+ const parsed=JSON.parse(result.stdout);
17
+ const record=Array.isArray(parsed)?parsed[0]:parsed['deadbyte-mcp'];
18
+ assert.ok(record&&Array.isArray(record.files),'npm file inventory missing');
19
+ const leaked=record.files.map(row=>row.path).filter(name=>
20
+ /^(?:testing|references|\.git)(?:\/|$)|(?:^|\/)\.env(?:\.|$)/i.test(name));
21
+ assert.deepEqual(leaked,[],'generated evidence or private trees must not enter npm package');
22
+ });