deadbyte-mcp 0.15.34 → 0.15.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MANIFEST.SHA256 +67 -22
- package/PROVENANCE.json +57 -30
- package/README.txt +18 -14
- package/RELEASE.json +40 -31
- package/SBOM.cdx.json +25 -3
- package/TEST-MATRIX.json +129 -48
- package/bridge/package.json +11 -0
- package/bridge/src/bridge.mjs +412 -0
- package/bridge/src/node-http-adapter.mjs +56 -0
- package/bridge/src/public-tool-definitions.mjs +14 -0
- package/bridge/src/r40-governor.mjs +160 -0
- package/controller/deadbyte-controller.ps1 +84 -8
- package/controller/deadbyte-process-policy.json +4 -4
- package/package.json +5 -3
- package/scripts/bridge-benchmark-r58.mjs +67 -0
- package/scripts/deploy-r48.mjs +2 -3
- package/scripts/gate-windows-r58.ps1 +33 -0
- package/scripts/owner-probe-r58.mjs +31 -0
- package/scripts/performance-r58.mjs +57 -0
- package/scripts/public-baseline-r58.mjs +72 -0
- package/scripts/public-surface-r58.mjs +84 -0
- package/scripts/r58-cross-plane.ps1 +6 -0
- package/scripts/r58-focused.ps1 +6 -0
- package/scripts/windows-gate-evidence-r58.mjs +93 -0
- package/src/deadbyte-cli.mjs +40 -12
- package/src/doctor-foreground-r58.mjs +44 -0
- package/src/doctor-installation-r58.mjs +63 -0
- package/src/doctor-r45.mjs +21 -4
- package/src/doctor-runtime-r58.mjs +82 -0
- package/src/doctor-transactions-r58.mjs +40 -0
- package/src/foreground-process-identity.mjs +27 -0
- package/src/foreground-session-lock.mjs +20 -0
- package/src/foreground-session-lock.ps1 +15 -0
- package/src/release-generation.mjs +1 -0
- package/src/release-slot.mjs +2 -1
- package/src/remote-session-guardian.mjs +8 -1
- package/src/runtime-update.mjs +85 -2
- package/src/version.mjs +1 -1
- package/test/controller-r211.test.mjs +4 -1
- package/test/controller.test.mjs +2 -1
- package/test/helpers/r58-doctor-fixture.mjs +26 -0
- package/test/r49-windows-gate.test.mjs +2 -2
- package/test/r57-release-contract.test.mjs +5 -3
- package/test/r58-bridge-dependency-binding.test.mjs +62 -0
- package/test/r58-bundled-bridge.test.mjs +22 -0
- package/test/r58-cleanup-retention.test.mjs +45 -0
- package/test/r58-completed-update-receipt.test.mjs +76 -0
- package/test/r58-concurrent-recovery.test.mjs +54 -0
- package/test/r58-controller-core-observation.test.mjs +36 -0
- package/test/r58-controller-json.test.mjs +48 -0
- package/test/r58-controller-live-local.test.mjs +85 -0
- package/test/r58-controller-readonly.test.mjs +23 -0
- package/test/r58-controller-state-coherence.test.mjs +45 -0
- package/test/r58-doctor-cli.test.mjs +20 -0
- package/test/r58-doctor-foreground.test.mjs +50 -0
- package/test/r58-doctor-installation.test.mjs +55 -0
- package/test/r58-doctor-pointer.test.mjs +41 -0
- package/test/r58-doctor-runtime.test.mjs +45 -0
- package/test/r58-doctor-transactions.test.mjs +21 -0
- package/test/r58-guardian-channel.test.mjs +26 -0
- package/test/r58-launcher-shell.test.mjs +28 -0
- package/test/r58-owner-identity.test.mjs +20 -0
- package/test/r58-release-contract.test.mjs +49 -0
- package/test/r58-session-lock.test.mjs +26 -0
- package/test/r58-stale-owner.test.mjs +71 -0
- package/test/r58-windows-gate.test.mjs +31 -0
- package/test/release-generation.test.mjs +4 -1
- package/test/remote-session-cli.test.mjs +55 -2
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {mkdir,mkdtemp,writeFile,readFile,readdir} from 'node:fs/promises';
|
|
4
|
+
import {spawnSync} from 'node:child_process';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import {fileURLToPath} from 'node:url';
|
|
7
|
+
import {createHash} from 'node:crypto';
|
|
8
|
+
import {windowsPowerShellEnvironment} from '../src/runtime-update.mjs';
|
|
9
|
+
import {classifyDoctorControllerObservation} from '../src/doctor-runtime-r58.mjs';
|
|
10
|
+
|
|
11
|
+
const core=fileURLToPath(new URL('..',import.meta.url));
|
|
12
|
+
const controller=path.join(core,'controller','deadbyte-controller.ps1');
|
|
13
|
+
const sha=b=>createHash('sha256').update(b).digest('hex');
|
|
14
|
+
const quote=s=>"'"+s.replaceAll("'","''")+"'";
|
|
15
|
+
test('R58 real controller JSON status is bounded read-only and cannot select mutation',async()=>{
|
|
16
|
+
const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});
|
|
17
|
+
const root=await mkdtemp(path.join(base,'controller-json-'));
|
|
18
|
+
const script=path.join(root,'bridge.mjs');await writeFile(script,'// never executed fixture\n');
|
|
19
|
+
const helper=path.join(root,'public-tool-definitions.mjs');await writeFile(helper,'// pinned helper fixture\n');
|
|
20
|
+
const helperHash=sha(await readFile(helper));
|
|
21
|
+
const config=path.join(root,'config.psd1'),nodeHash=sha(await readFile(process.execPath)),scriptHash=sha(await readFile(script));
|
|
22
|
+
const spec=`@{ FilePath=${quote(process.execPath)}; FileSha256='${nodeHash}'; Arguments='UNLAUNCHED'; WorkingDirectory=${quote(root)} }`;
|
|
23
|
+
const bridge=spec.slice(0,-1)+`; ScriptPath=${quote(script)}; ScriptSha256='${scriptHash}'; Dependencies=@(@{Name='bridge-validator';Path=${quote(helper)};Sha256='${helperHash}'}) }`;
|
|
24
|
+
await writeFile(config,`@{ Schema='deadbyte.controller.v1'; CoreRoot=${quote(core)}; WorkspaceRoot=${quote(root)}; Bridge=${bridge}; Cloud=${spec}; MachineRuntimeEnabled=$false; AgentRuntimeEnabled=$false; ProcessRuntimeEnabled=$false; ProcessPolicyFile=''; CodingRuntimeEnabled=$false; CodingPolicyFile=''; DesktopRuntimeEnabled=$false; DesktopPolicyFile=''; AutonomousRuntimeEnabled=$false; AutonomousSupervisorEnabled=$false; AutonomousPolicyFile=''; HostPolicyFile=''; LocalReadyUri='http://127.0.0.1:1/health'; UrlRegex=''; McpUrlFile=''; McpPathFile=''; StartTimeoutSeconds=1; ProbeTimeoutSeconds=1 }`);
|
|
25
|
+
const runtime=path.join(root,'runtime');
|
|
26
|
+
const run=command=>spawnSync(path.join(process.env.SystemRoot,'System32/WindowsPowerShell/v1.0/powershell.exe'),['-NoProfile','-File',controller,command,'-Json'],{encoding:'utf8',timeout:20000,env:windowsPowerShellEnvironment({...process.env,DEADBYTE_STATE_ROOT:root,DEADBYTE_CONTROLLER_CONFIG:config,DEADBYTE_CONTROLLER_RUNTIME_ROOT:runtime})});
|
|
27
|
+
const before=await readdir(root);
|
|
28
|
+
const observed=run('status');assert.equal(observed.status,0,observed.stderr);
|
|
29
|
+
const value=JSON.parse(observed.stdout);assert.equal(value.schema,'deadbyte.controller-observation.v1');assert.equal(value.state,'OFFLINE');assert.equal(value.local_ready,false);
|
|
30
|
+
assert.equal(value.bridge.alive,false);assert.equal(value.cloud.alive,false);
|
|
31
|
+
assert.equal(value.core.alive,false);assert.equal(value.core.reason,'bridge-unavailable');
|
|
32
|
+
assert.equal(classifyDoctorControllerObservation(value,core).status,'PASS');
|
|
33
|
+
for(const plane of ['process','coding','autonomous','desktop','host'])assert.equal(value.authority[plane].armed,false);
|
|
34
|
+
assert.deepEqual(await readdir(root),before,'status must not create runtime/logs/grants');
|
|
35
|
+
const denied=run('armcoding');assert.notEqual(denied.status,0);assert.match(denied.stderr,/JSON.*status|status.*JSON/i);
|
|
36
|
+
assert.deepEqual(await readdir(root),before,'JSON option must not invoke mutation');
|
|
37
|
+
assert.ok(!observed.stdout.includes('UNLAUNCHED'),'never expose launch arguments');
|
|
38
|
+
await writeFile(helper,'// changed helper fixture\n');
|
|
39
|
+
const drift=run('status');assert.notEqual(drift.status,0);assert.match(drift.stderr,/Bridge dependency hash mismatch/);
|
|
40
|
+
assert.deepEqual(await readdir(root),before,'dependency drift must fail before runtime creation');
|
|
41
|
+
await writeFile(helper,'// pinned helper fixture\n');
|
|
42
|
+
const other=path.join(root,'other-core');await mkdir(path.join(other,'src'),{recursive:true});
|
|
43
|
+
await writeFile(path.join(other,'package.json'),'{"name":"deadbyte-mcp"}');await writeFile(path.join(other,'src','mcp-server.mjs'),'// fixture only');
|
|
44
|
+
const configBefore=await readFile(config,'utf8');await writeFile(config,configBefore.replace('CoreRoot='+quote(core),'CoreRoot='+quote(other)));
|
|
45
|
+
const inventory=await readdir(root),wrongRoot=run('status');
|
|
46
|
+
assert.notEqual(wrongRoot.status,0);assert.match(wrongRoot.stderr,/controller root mismatch/);
|
|
47
|
+
assert.deepEqual(await readdir(root),inventory,'wrong-root observation must fail without runtime creation');
|
|
48
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {mkdir,cp,readFile,writeFile} from 'node:fs/promises';
|
|
4
|
+
import {spawnSync} from 'node:child_process';
|
|
5
|
+
import {createServer} from 'node:net';
|
|
6
|
+
import {createHash,randomBytes,generateKeyPairSync} from 'node:crypto';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import {makeDoctorCliFixture} from './helpers/r58-doctor-fixture.mjs';
|
|
9
|
+
import {prepareBridgeSpec,windowsPowerShellEnvironment} from '../src/runtime-update.mjs';
|
|
10
|
+
import {queryForegroundIdentity as queryForegroundProcessIdentity,foregroundIdentityMatches as sameForegroundProcessIdentity} from '../src/foreground-process-identity.mjs';
|
|
11
|
+
|
|
12
|
+
const sha=b=>createHash('sha256').update(b).digest('hex');
|
|
13
|
+
const quote=s=>"'"+s.replaceAll("'","''")+"'";
|
|
14
|
+
const source=new URL('../controller/deadbyte-controller.ps1',import.meta.url);
|
|
15
|
+
|
|
16
|
+
test('R58 actual isolated controller/bridge/core reaches ONLINE and stops without an orphan core',async()=>{
|
|
17
|
+
const f=await makeDoctorCliFixture();
|
|
18
|
+
const bridgeRoot=path.join(f.pkg,'bridge');
|
|
19
|
+
const keys=generateKeyPairSync('ed25519'),trust=path.join(f.state,'trust');await mkdir(trust);
|
|
20
|
+
await writeFile(path.join(trust,'ed25519-private.pem'),keys.privateKey.export({type:'pkcs8',format:'pem'}));
|
|
21
|
+
await writeFile(path.join(trust,'ed25519-public.pem'),keys.publicKey.export({type:'spki',format:'pem'}));
|
|
22
|
+
await mkdir(path.join(f.pkg,'controller'));
|
|
23
|
+
const controller=path.join(f.pkg,'controller','deadbyte-controller.ps1');await cp(source,controller);
|
|
24
|
+
const manifest=await readFile(path.join(f.pkg,'MANIFEST.SHA256'),'utf8');
|
|
25
|
+
await writeFile(path.join(f.pkg,'MANIFEST.SHA256'),[...manifest.trim().split('\n'),sha(await readFile(controller))+' controller/deadbyte-controller.ps1'].sort().join('\n')+'\n');
|
|
26
|
+
const workspace=path.join(f.root,'workspace');await mkdir(workspace);
|
|
27
|
+
const listener=createServer();await new Promise(resolve=>listener.listen(0,'127.0.0.1',resolve));
|
|
28
|
+
const port=listener.address().port;await new Promise(resolve=>listener.close(resolve));
|
|
29
|
+
const cloud=path.join(f.root,'fixture-cloud.mjs');await writeFile(cloud,'setInterval(()=>{},1000);\n');
|
|
30
|
+
const url=path.join(f.root,'fixture-url.txt');await writeFile(url,'https://fixture.invalid/mcp\n');
|
|
31
|
+
const bridgeScript=path.join(bridgeRoot,'src','bridge.mjs'),nodeHash=sha(await readFile(process.execPath));
|
|
32
|
+
const preparedBridge=await prepareBridgeSpec({Bridge:{FilePath:process.execPath,FileSha256:nodeHash,Arguments:'src\\bridge.mjs',WorkingDirectory:bridgeRoot},Cloud:{}},{root:bridgeRoot,scriptSha256:sha(await readFile(bridgeScript))});
|
|
33
|
+
const dependencies=preparedBridge.Bridge.Dependencies.map(dependency=>`@{Name=${quote(dependency.Name)};Path=${quote(dependency.Path)};Sha256='${dependency.Sha256}'}`);
|
|
34
|
+
assert.deepEqual(preparedBridge.Bridge.Dependencies.map(x=>x.Name),['node-http-adapter.mjs','public-tool-definitions.mjs','r40-governor.mjs']);
|
|
35
|
+
const config=path.join(f.root,'controller-config.psd1'),runtime=path.join(f.state,'runtime');
|
|
36
|
+
await writeFile(config,`@{ Schema='deadbyte.controller.v1'; CoreRoot=${quote(f.pkg)}; WorkspaceRoot=${quote(workspace)}; Bridge=@{FilePath=${quote(process.execPath)};FileSha256='${nodeHash}';Arguments='src\\bridge.mjs';WorkingDirectory=${quote(bridgeRoot)};ScriptPath=${quote(bridgeScript)};ScriptSha256='${sha(await readFile(bridgeScript))}';Dependencies=@(${dependencies.join(';')})}; Cloud=@{FilePath=${quote(process.execPath)};FileSha256='${nodeHash}';Arguments=${quote('"'+cloud+'"')};WorkingDirectory=${quote(f.root)};Dependencies=@(@{Name='fixture-cloud';Path=${quote(cloud)};Sha256='${sha(await readFile(cloud))}'})}; MachineRuntimeEnabled=$false;AgentRuntimeEnabled=$false;ProcessRuntimeEnabled=$false;ProcessPolicyFile='';CodingRuntimeEnabled=$false;CodingPolicyFile='';MachineFsRuntimeEnabled=$false;ObservationRuntimeEnabled=$false;DesktopRuntimeEnabled=$false;DesktopPolicyFile='';AutonomousRuntimeEnabled=$false;AutonomousSupervisorEnabled=$false;AutonomousPolicyFile='';HostPolicyFile='';LocalReadyUri='http://127.0.0.1:${port}/healthz';UrlRegex='';McpUrlFile=${quote(url)};McpPathFile='';StartTimeoutSeconds=15;ProbeTimeoutSeconds=1 }`);
|
|
37
|
+
// Controller's existing audit mode requires machine runtime. It is observation
|
|
38
|
+
// only here; all optional authority planes remain disabled and unarmed.
|
|
39
|
+
const codingPolicy=path.join(f.root,'coding-policy.json');
|
|
40
|
+
await writeFile(codingPolicy,JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:path.join(runtime,'coding-grant.json'),evidence_dir:path.join(f.state,'evidence','coding'),roots:{fixture:{path:workspace,read:true,write:false,exec:false,deny_paths:[]}},commands:{},max_read_bytes:65536,max_write_bytes:65536}));
|
|
41
|
+
await writeFile(config,(await readFile(config,'utf8')).replace('MachineRuntimeEnabled=$false','MachineRuntimeEnabled=$true').replace("CodingRuntimeEnabled=$false;CodingPolicyFile=''",`CodingRuntimeEnabled=$true;CodingPolicyFile=${quote(codingPolicy)}`));
|
|
42
|
+
// Audit context and machine identity require an exact isolated active binding.
|
|
43
|
+
// Bind the fixture package bytes to its own generation; never borrow production
|
|
44
|
+
// pointers, generations, launchers or signing keys.
|
|
45
|
+
const pkgIdentity=JSON.parse(await readFile(path.join(f.pkg,'package.json'),'utf8'));
|
|
46
|
+
const releaseManifestSha=sha(await readFile(path.join(f.pkg,'MANIFEST.SHA256')));
|
|
47
|
+
const generation=path.join(f.state,'generations',`fixture-${randomBytes(8).toString('hex')}`);
|
|
48
|
+
await mkdir(generation,{recursive:true});
|
|
49
|
+
const generationConfig=path.join(generation,'controller-config.psd1');
|
|
50
|
+
await cp(config,generationConfig);
|
|
51
|
+
const generationManifestBytes=Buffer.from(`${sha(await readFile(generationConfig))} controller-config.psd1\n`,'utf8');
|
|
52
|
+
await writeFile(path.join(generation,'GENERATION.SHA256'),generationManifestBytes);
|
|
53
|
+
await writeFile(path.join(f.state,'active-release.json'),JSON.stringify({
|
|
54
|
+
schema:'deadbyte.active-release.v1',
|
|
55
|
+
release_id:`v${pkgIdentity.version}-${releaseManifestSha.slice(0,16)}`,
|
|
56
|
+
version:pkgIdentity.version,
|
|
57
|
+
manifest_sha256:releaseManifestSha,
|
|
58
|
+
release_root:f.pkg,
|
|
59
|
+
generation_root:generation,
|
|
60
|
+
generation_manifest_sha256:sha(generationManifestBytes),
|
|
61
|
+
launcher_sha256:'0'.repeat(64),
|
|
62
|
+
config_path:generationConfig
|
|
63
|
+
},null,2)+'\n');
|
|
64
|
+
const env=windowsPowerShellEnvironment({...f.env,DEADBYTE_CONTROLLER_CONFIG:config,DEADBYTE_CONTROLLER_RUNTIME_ROOT:runtime,DEADBYTE_BRIDGE_PORT:String(port),DEADBYTE_BRIDGE_PATH_TOKEN:randomBytes(32).toString('hex')});
|
|
65
|
+
const run=(command,json=false)=>spawnSync(path.join(process.env.SystemRoot,'System32/WindowsPowerShell/v1.0/powershell.exe'),['-NoProfile','-File',controller,command,...(json?['-Json']:[])],{env,encoding:'utf8',timeout:45000});
|
|
66
|
+
let coreIdentity=null;
|
|
67
|
+
try{
|
|
68
|
+
const cold=run('status',true);assert.equal(cold.status,0,cold.stderr);assert.equal(JSON.parse(cold.stdout).state,'OFFLINE');
|
|
69
|
+
const started=run('start');assert.equal(started.status,0,started.stderr);
|
|
70
|
+
const status=run('status',true);assert.equal(status.status,0,status.stderr);const observed=JSON.parse(status.stdout);
|
|
71
|
+
assert.equal(observed.state,'ONLINE');assert.equal(observed.local_ready,true);assert.equal(observed.core.alive,true);assert.equal(observed.core.parent_pid,observed.bridge.pid);
|
|
72
|
+
for(const plane of Object.values(observed.authority))assert.equal(plane.armed,false);
|
|
73
|
+
coreIdentity=await queryForegroundProcessIdentity(observed.core.pid);assert.ok(coreIdentity);
|
|
74
|
+
const stopped=run('stop');assert.equal(stopped.status,0,stopped.stderr);
|
|
75
|
+
const terminal=run('status',true);assert.equal(terminal.status,0,terminal.stderr);const end=JSON.parse(terminal.stdout);
|
|
76
|
+
assert.equal(end.state,'OFFLINE');assert.equal(end.local_ready,false);assert.equal(end.bridge.alive,false);assert.equal(end.cloud.alive,false);
|
|
77
|
+
assert.equal(await queryForegroundProcessIdentity(coreIdentity.pid),null,'owned core must be gone after supported stop');
|
|
78
|
+
}finally{
|
|
79
|
+
const cleanup=run('stop');
|
|
80
|
+
// Only this fixture's already observed exact process identity can be removed.
|
|
81
|
+
// A cleanup failure remains a test failure, never hidden as successful stop.
|
|
82
|
+
if(coreIdentity){const remaining=await queryForegroundProcessIdentity(coreIdentity.pid);if(remaining&&sameForegroundProcessIdentity(coreIdentity,remaining))process.kill(coreIdentity.pid);}
|
|
83
|
+
assert.equal(cleanup.status,0,cleanup.stderr);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {readFile,mkdir,mkdtemp,writeFile,readdir} from 'node:fs/promises';
|
|
4
|
+
import {spawnSync} from 'node:child_process';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import {windowsPowerShellEnvironment} from '../src/runtime-update.mjs';
|
|
7
|
+
|
|
8
|
+
test('R58 controller read-only dispatch must not create runtime/log state',async()=>{
|
|
9
|
+
const source=await readFile(new URL('../controller/deadbyte-controller.ps1',import.meta.url),'utf8');
|
|
10
|
+
const start=source.indexOf('function Run-CommandCore('),end=source.indexOf('function Run-Command(',start);
|
|
11
|
+
assert.ok(start>=0&&end>start);const dispatch=source.slice(start,end);
|
|
12
|
+
const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});
|
|
13
|
+
const root=await mkdtemp(path.join(base,'controller-readonly-'));
|
|
14
|
+
for(const command of ['status','url','hoststatus','processstatus','codingstatus','autonomousstatus','desktopstatus','supervisorstatus']){
|
|
15
|
+
const isolated=path.join(root,command);await mkdir(isolated);
|
|
16
|
+
const script=path.join(isolated,'fixture.ps1');
|
|
17
|
+
const prelude=`$ErrorActionPreference='Stop'\n$RuntimeDir='${path.join(isolated,'runtime').replaceAll("'","''")}'\n$LogDir=Join-Path $RuntimeDir 'logs'\nfunction Get-Config { return @{} }\nfunction Assert-ControllerRootBound($Cfg) {}\nfunction Ensure-Directory([string]$Path) { if (-not (Test-Path -LiteralPath $Path)) { New-Item -ItemType Directory -Path $Path | Out-Null } }\nfunction Show-State($Cfg) {}\nfunction Get-CurrentUrl($Cfg) { return 'FIXTURE' }\nfunction Show-HostStatus($Cfg) {}\nfunction Show-ProcessStatus($Cfg) {}\nfunction Show-CodingStatus($Cfg) {}\nfunction Show-AutonomousStatus($Cfg) {}\nfunction Show-DesktopStatus($Cfg) {}\nfunction Show-AutonomousSupervisorStatus($Cfg) {}\n`;
|
|
18
|
+
await writeFile(script,prelude+dispatch+`\nRun-CommandCore '${command}'\n`);
|
|
19
|
+
const observed=spawnSync(path.join(process.env.SystemRoot,'System32/WindowsPowerShell/v1.0/powershell.exe'),['-NoProfile','-File',script],{encoding:'utf8',timeout:20000,env:windowsPowerShellEnvironment(process.env)});
|
|
20
|
+
assert.equal(observed.status,0,observed.stderr);
|
|
21
|
+
assert.deepEqual(await readdir(isolated),['fixture.ps1'],command+' must not create runtime state');
|
|
22
|
+
}
|
|
23
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {readFile,mkdir,mkdtemp,writeFile} from 'node:fs/promises';
|
|
4
|
+
import {spawnSync} from 'node:child_process';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import {windowsPowerShellEnvironment} from '../src/runtime-update.mjs';
|
|
7
|
+
|
|
8
|
+
test('R58 controller human state cannot claim ONLINE/local ready without its verified core',async()=>{
|
|
9
|
+
const source=await readFile(new URL('../controller/deadbyte-controller.ps1',import.meta.url),'utf8');
|
|
10
|
+
const start=source.indexOf('function Get-ObservedState('),end=source.indexOf('function Wait-LocalReady(',start);
|
|
11
|
+
assert.ok(start>=0&&end>start);
|
|
12
|
+
const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});
|
|
13
|
+
const root=await mkdtemp(path.join(base,'state-coherence-'));
|
|
14
|
+
const cases=[
|
|
15
|
+
{bridge:true,cloud:true,ready:true,core:true,reason:'verified',state:'ONLINE',local:true},
|
|
16
|
+
{bridge:true,cloud:true,ready:true,core:false,reason:'startup-zero-child',state:'STARTING',local:false},
|
|
17
|
+
{bridge:true,cloud:true,ready:true,core:false,reason:'ambiguous-core',state:'FAILED',local:false},
|
|
18
|
+
{bridge:true,cloud:true,ready:true,core:false,reason:'wrong-core-generation',state:'FAILED',local:false},
|
|
19
|
+
{bridge:true,cloud:false,ready:true,core:true,reason:'verified',state:'FAILED',local:true},
|
|
20
|
+
{bridge:false,cloud:true,ready:false,core:false,reason:'bridge-unavailable',state:'PARKED',local:false},
|
|
21
|
+
{bridge:false,cloud:false,ready:false,core:false,reason:'bridge-unavailable',state:'OFFLINE',local:false},
|
|
22
|
+
{bridge:true,cloud:true,ready:false,core:true,reason:'verified',state:'FAILED',local:false}
|
|
23
|
+
];
|
|
24
|
+
const data=path.join(root,'cases.json');await writeFile(data,JSON.stringify(cases));
|
|
25
|
+
const script=path.join(root,'fixture.ps1');
|
|
26
|
+
await writeFile(script,`$ErrorActionPreference='Stop'\n${source.slice(start,end)}\nfunction Test-OwnedInstance([string]$Name) { return [pscustomobject]@{Alive=[bool]$script:Case.$Name;Reason='verified';Ledger=[pscustomobject]@{pid=20}} }\nfunction Test-LocalReadyOwned($Cfg,$Bridge) { return [bool]$script:Case.ready }\nfunction Get-DownstreamCoreObservation($Cfg,$Bridge) { $script:Queries++; return [pscustomobject]@{alive=[bool]$script:Case.core;reason=[string]$script:Case.reason;pid=21} }\n$cases=Get-Content -LiteralPath '${data.replaceAll("'","''")}' -Raw | ConvertFrom-Json\nforeach($case in $cases) { $script:Case=$case; $script:Queries=0; $s=Get-ObservedState @{}; [pscustomobject]@{state=$s.State;local_ready=$s.LocalReady;queries=$script:Queries} | ConvertTo-Json -Compress | Write-Output }\n`);
|
|
27
|
+
const r=spawnSync(path.join(process.env.SystemRoot,'System32/WindowsPowerShell/v1.0/powershell.exe'),['-NoProfile','-File',script],{encoding:'utf8',timeout:15000,env:windowsPowerShellEnvironment(process.env)});
|
|
28
|
+
assert.equal(r.status,0,r.stderr);
|
|
29
|
+
const rows=r.stdout.trim().split(/\r?\n/).map(JSON.parse);assert.equal(rows.length,cases.length);
|
|
30
|
+
rows.forEach((row,i)=>{assert.equal(row.state,cases[i].state,JSON.stringify(cases[i]));assert.equal(row.local_ready,cases[i].local);});
|
|
31
|
+
rows.forEach(row=>assert.equal(row.queries,1,'one observation, no duplicate core query or retry'));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('R58 controller startup readiness retries only zero-child core visibility and rejects ambiguity immediately',async()=>{
|
|
35
|
+
const source=await readFile(new URL('../controller/deadbyte-controller.ps1',import.meta.url),'utf8');
|
|
36
|
+
const start=source.indexOf('function Wait-LocalReady('),end=source.indexOf('function Wait-PublicDnsReady(',start);
|
|
37
|
+
assert.ok(start>=0&&end>start);
|
|
38
|
+
const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});
|
|
39
|
+
const root=await mkdtemp(path.join(base,'core-ready-')),script=path.join(root,'fixture.ps1');
|
|
40
|
+
await writeFile(script,`$ErrorActionPreference='Stop'\n${source.slice(start,end)}\nfunction Test-OwnedInstance([string]$Name) { return [pscustomobject]@{Alive=$true} }\nfunction Test-LocalReadyOwned($Cfg,$Bridge) { return $true }\nfunction Start-Sleep { param($Milliseconds) $script:Sleeps++ }\nfunction Get-DownstreamCoreObservation($Cfg,$Bridge) { $script:Queries++; if($script:Mode -eq 'race' -and $script:Queries -ge 2) { return [pscustomobject]@{alive=$true;reason='verified'} }; return [pscustomobject]@{alive=$false;reason=$(if($script:Mode -eq 'race' -or $script:Mode -eq 'timeout'){'startup-zero-child'}else{'ambiguous-core'})} }\nforeach($mode in @('race','ambiguous','timeout')) { $script:Mode=$mode; $script:Queries=0; $script:Sleeps=0; $ready=Wait-LocalReady @{StartTimeoutSeconds=$(if($mode -eq 'timeout'){0}else{2})}; [pscustomobject]@{mode=$mode;ready=$ready;queries=$script:Queries;sleeps=$script:Sleeps} | ConvertTo-Json -Compress | Write-Output }\n`);
|
|
41
|
+
const r=spawnSync(path.join(process.env.SystemRoot,'System32/WindowsPowerShell/v1.0/powershell.exe'),['-NoProfile','-File',script],{encoding:'utf8',timeout:15000,env:windowsPowerShellEnvironment(process.env)});
|
|
42
|
+
assert.equal(r.status,0,r.stderr);
|
|
43
|
+
const rows=r.stdout.trim().split(/\r?\n/).map(JSON.parse);
|
|
44
|
+
assert.deepEqual(rows,[{mode:'race',ready:true,queries:2,sleeps:1},{mode:'ambiguous',ready:false,queries:1,sleeps:0},{mode:'timeout',ready:false,queries:1,sleeps:0}]);
|
|
45
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {spawnSync} from 'node:child_process';
|
|
4
|
+
import {writeFile,readFile,readdir} from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import {makeDoctorCliFixture} from './helpers/r58-doctor-fixture.mjs';
|
|
7
|
+
|
|
8
|
+
test('R58 actual doctor CLI is read-only and reports nonzero for a failed installed-state check',async()=>{
|
|
9
|
+
const f=await makeDoctorCliFixture();
|
|
10
|
+
const run=()=>spawnSync(process.execPath,[f.entry,'doctor'],{encoding:'utf8',timeout:30000,env:f.env});
|
|
11
|
+
const healthy=run();assert.equal(healthy.status,0,healthy.stderr);
|
|
12
|
+
const body=JSON.parse(healthy.stdout);assert.equal(body.status,'ok');assert.equal(body.assessment,'PASS');
|
|
13
|
+
assert.equal(body.manifest.verified_entries,f.manifestFiles);assert.deepEqual(await readdir(f.state),[],'empty-state doctor must not bootstrap');
|
|
14
|
+
const manifest='a'.repeat(64),release='v0.15.34-'+manifest.slice(0,16);
|
|
15
|
+
const pointer={schema:'deadbyte.active-release.v1',version:'0.15.34',release_id:release,manifest_sha256:manifest,release_root:path.join(f.state,'releases',release),generation_root:path.join(f.state,'generations','missing'),generation_manifest_sha256:'b'.repeat(64),launcher_sha256:'c'.repeat(64),config_path:path.join(f.state,'generations','missing','controller-config.psd1')};
|
|
16
|
+
const file=path.join(f.state,'active-release.json'),bytes=JSON.stringify(pointer);await writeFile(file,bytes);
|
|
17
|
+
const failed=run();assert.equal(JSON.parse(failed.stdout).assessment,'FAIL',failed.stderr);
|
|
18
|
+
assert.notEqual(failed.status,0,'doctor FAIL must be visible to shell and release gate');
|
|
19
|
+
assert.equal(await readFile(file,'utf8'),bytes);assert.deepEqual(await readdir(f.state),['active-release.json']);
|
|
20
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {mkdir,mkdtemp,writeFile,readFile,readdir} from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import {inspectDoctorForeground} from '../src/doctor-foreground-r58.mjs';
|
|
6
|
+
import {queryForegroundIdentity} from '../src/foreground-process-identity.mjs';
|
|
7
|
+
|
|
8
|
+
const owner={schema:'deadbyte.foreground-process.v1',pid:101,parent_pid:100,creation_utc:'2026-10-01T00:00:00.000Z',executable_path:'C:/Windows/node.exe',command_line_sha256:'a'.repeat(64)};
|
|
9
|
+
const guardian={...owner,pid:102,parent_pid:101,command_line_sha256:'b'.repeat(64)};
|
|
10
|
+
const valid={schema:'deadbyte.remote-session.v2',owner_pid:101,guardian_pid:102,session_nonce:'c'.repeat(64),owner_identity:owner,guardian_identity:guardian};
|
|
11
|
+
async function fixture(){const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});const root=await mkdtemp(path.join(base,'doctor-foreground-'));await mkdir(path.join(root,'runtime'));return {root,file:path.join(root,'runtime','remote-session.json')};}
|
|
12
|
+
const observe=pid=>pid===101?owner:guardian;
|
|
13
|
+
|
|
14
|
+
test('R58 doctor foreground validates bindings and distinguishes stale observations without mutation',async()=>{
|
|
15
|
+
const f=await fixture();
|
|
16
|
+
assert.equal((await inspectDoctorForeground(f.root)).status,'PASS');assert.deepEqual(await readdir(path.join(f.root,'runtime')),[]);
|
|
17
|
+
const cases=[
|
|
18
|
+
[valid,'PASS',observe],
|
|
19
|
+
[{...valid,session_nonce:'INVALID'},'FAIL',()=>{throw new Error('must not query');}],
|
|
20
|
+
[{...valid,owner_identity:{...owner,pid:103}},'FAIL',observe],
|
|
21
|
+
[{...valid,guardian_identity:{...guardian,parent_pid:999}},'FAIL',observe],
|
|
22
|
+
[{...valid,owner_identity:undefined,guardian_identity:undefined},'WARN',()=>{throw new Error('unverified PID must not query');}],
|
|
23
|
+
[{schema:'deadbyte.remote-session.v1',pid:101},'WARN',observe],
|
|
24
|
+
[valid,'WARN',()=>null],
|
|
25
|
+
[valid,'WARN',pid=>({...observe(pid),creation_utc:'2026-10-01T00:00:01.000Z'})],
|
|
26
|
+
[valid,'FAIL',()=>{throw new Error('observation denied');}]
|
|
27
|
+
];
|
|
28
|
+
for(const [marker,expected,queryIdentity]of cases){
|
|
29
|
+
const bytes=JSON.stringify(marker);await writeFile(f.file,bytes);
|
|
30
|
+
const result=await inspectDoctorForeground(f.root,{queryIdentity});assert.equal(result.status,expected,bytes);
|
|
31
|
+
assert.equal(await readFile(f.file,'utf8'),bytes);
|
|
32
|
+
for(const finding of result.findings.filter(f=>f.level!=='PASS'))assert.ok(finding.what&&finding.next_action&&finding.evidence);
|
|
33
|
+
assert.ok(!JSON.stringify(result).includes(valid.session_nonce),'do not expose session nonce');
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('R58 doctor foreground malformed, oversized and unreadable markers fail closed',async()=>{
|
|
38
|
+
const f=await fixture();
|
|
39
|
+
for(const bytes of ['INVALID_JSON','x'.repeat(16385),'null']){
|
|
40
|
+
await writeFile(f.file,bytes);assert.equal((await inspectDoctorForeground(f.root)).status,'FAIL');assert.equal(await readFile(f.file,'utf8'),bytes);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('R58 doctor actual owner observation verifies the current process, not PID alone',async()=>{
|
|
45
|
+
const f=await fixture();const identity=queryForegroundIdentity(process.pid);
|
|
46
|
+
await writeFile(f.file,JSON.stringify({...valid,owner_pid:process.pid,owner_identity:identity,guardian_pid:0,guardian_identity:undefined}));
|
|
47
|
+
const result=await inspectDoctorForeground(f.root);
|
|
48
|
+
assert.equal(result.findings.find(f=>f.id==='foreground_owner').level,'PASS');
|
|
49
|
+
assert.equal(result.status,'WARN','guardian reservation is not a verified healthy guardian');
|
|
50
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdir, mkdtemp, writeFile, readFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { inspectDoctorInstallation } from '../src/doctor-installation-r58.mjs';
|
|
6
|
+
import { sha256Bytes } from '../src/release-slot.mjs';
|
|
7
|
+
|
|
8
|
+
async function fixture(){
|
|
9
|
+
const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});
|
|
10
|
+
const state=await mkdtemp(path.join(base,'doctor-installation-'));
|
|
11
|
+
const packageBytes=Buffer.from(JSON.stringify({name:'deadbyte-mcp',version:'0.15.34'}));
|
|
12
|
+
const manifest=Buffer.from(sha256Bytes(packageBytes)+' package.json\n');
|
|
13
|
+
const manifest_sha256=sha256Bytes(manifest),release_id='v0.15.34-'+manifest_sha256.slice(0,16);
|
|
14
|
+
const release=path.join(state,'releases',release_id),generation=path.join(state,'generations','fixture');
|
|
15
|
+
await mkdir(release,{recursive:true});await mkdir(generation,{recursive:true});await mkdir(path.join(state,'bin'));
|
|
16
|
+
const config=Buffer.from('@{}\r\n'),generationManifest=Buffer.from(sha256Bytes(config)+' controller-config.psd1\n'),launcher=Buffer.from('# isolated launcher\r\n');
|
|
17
|
+
const files=new Map([[path.join(release,'package.json'),packageBytes],[path.join(release,'MANIFEST.SHA256'),manifest],[path.join(generation,'controller-config.psd1'),config],[path.join(generation,'GENERATION.SHA256'),generationManifest],[path.join(state,'bin','DEADBYTE-MCP.ps1'),launcher]]);
|
|
18
|
+
for(const [file,bytes]of files)await writeFile(file,bytes);
|
|
19
|
+
const pointer={schema:'deadbyte.active-release.v1',version:'0.15.34',release_id,manifest_sha256,release_root:release,generation_root:generation,generation_manifest_sha256:sha256Bytes(generationManifest),launcher_sha256:sha256Bytes(launcher),config_path:path.join(generation,'controller-config.psd1')};
|
|
20
|
+
return {state,pointer,files};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
test('R58 doctor independently verifies installed bytes and never repairs fixture files',async()=>{
|
|
24
|
+
const f=await fixture();
|
|
25
|
+
const good=await inspectDoctorInstallation(f.pointer,f.state);
|
|
26
|
+
assert.equal(good.status,'PASS');assert.equal(good.findings.length,4);
|
|
27
|
+
for(const [file,bytes]of f.files){
|
|
28
|
+
await writeFile(file,Buffer.concat([bytes,Buffer.from('CORRUPTION')]));
|
|
29
|
+
const result=await inspectDoctorInstallation(f.pointer,f.state);
|
|
30
|
+
assert.equal(result.status,'FAIL',file);
|
|
31
|
+
const failure=result.findings.find(item=>item.level==='FAIL');assert.ok(failure);
|
|
32
|
+
assert.ok(failure.what&&failure.next_action&&failure.evidence.check);
|
|
33
|
+
assert.deepEqual(await readFile(file),Buffer.concat([bytes,Buffer.from('CORRUPTION')]),'no auto-repair');
|
|
34
|
+
await writeFile(file,bytes);
|
|
35
|
+
}
|
|
36
|
+
assert.equal((await inspectDoctorInstallation(f.pointer,f.state)).status,'PASS');
|
|
37
|
+
for(const [file,bytes]of f.files)assert.deepEqual(await readFile(file),bytes);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('R58 doctor stops before following drifted release, generation or config paths',async()=>{
|
|
41
|
+
const f=await fixture();
|
|
42
|
+
for(const field of ['release_root','generation_root','config_path']){
|
|
43
|
+
const result=await inspectDoctorInstallation({...f.pointer,[field]:'C:/DO_NOT_READ_OUTSIDE_FIXTURE'},f.state);
|
|
44
|
+
assert.equal(result.status,'FAIL');assert.equal(result.findings.length,1);
|
|
45
|
+
assert.equal(result.findings[0].id,'active_paths');
|
|
46
|
+
}
|
|
47
|
+
await assert.rejects(inspectDoctorInstallation({...f.pointer,schema:'invalid'},f.state),/pointer schema/);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('R58 doctor does not accept a valid-schema pointer to an absent installed slot',async()=>{
|
|
51
|
+
const f=await fixture();
|
|
52
|
+
const root=await mkdtemp(path.join(path.dirname(f.state),'doctor-empty-'));
|
|
53
|
+
const result=await inspectDoctorInstallation({...f.pointer,release_root:path.join(root,'releases',f.pointer.release_id),generation_root:path.join(root,'generations','fixture'),config_path:path.join(root,'generations','fixture','controller-config.psd1')},root);
|
|
54
|
+
assert.equal(result.status,'FAIL');assert.equal(result.findings[0].id,'active_paths');
|
|
55
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdir, mkdtemp, writeFile, readFile, readdir } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { readDoctorActivePointer } from '../src/doctor-r45.mjs';
|
|
6
|
+
|
|
7
|
+
test('R58 doctor validates canonical active pointer without repair or production fallback', async () => {
|
|
8
|
+
const base = 'D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';
|
|
9
|
+
await mkdir(base, {recursive:true});
|
|
10
|
+
const root = await mkdtemp(path.join(base, 'doctor-pointer-green-'));
|
|
11
|
+
assert.equal(await readDoctorActivePointer(root), null);
|
|
12
|
+
assert.deepEqual(await readdir(root), []);
|
|
13
|
+
const pointerPath = path.join(root, 'active-release.json');
|
|
14
|
+
const valid = {
|
|
15
|
+
schema:'deadbyte.active-release.v1',version:'0.15.34',
|
|
16
|
+
manifest_sha256:'a'.repeat(64),release_id:'v0.15.34-'+'a'.repeat(16),
|
|
17
|
+
generation_manifest_sha256:'b'.repeat(64),launcher_sha256:'c'.repeat(64),
|
|
18
|
+
release_root:path.join(root,'releases','fixture'),
|
|
19
|
+
generation_root:path.join(root,'generations','fixture'),config_path:path.join(root,'config.psd1')
|
|
20
|
+
};
|
|
21
|
+
for (const [field, value] of [
|
|
22
|
+
['schema','INVALID_FIXTURE'],['release_id','fabricated'],
|
|
23
|
+
['version','invalid'],['manifest_sha256','bad'],
|
|
24
|
+
['generation_manifest_sha256','bad'],['launcher_sha256','bad'],
|
|
25
|
+
['config_path',''],['release_root',''],['generation_root','']
|
|
26
|
+
]) {
|
|
27
|
+
const text = JSON.stringify({...valid,[field]:value});
|
|
28
|
+
await writeFile(pointerPath,text);
|
|
29
|
+
await assert.rejects(readDoctorActivePointer(root), /active pointer/);
|
|
30
|
+
assert.equal(await readFile(pointerPath,'utf8'),text);
|
|
31
|
+
}
|
|
32
|
+
for (const prefix of ['', '\ufeff']) {
|
|
33
|
+
const text = prefix+JSON.stringify(valid);
|
|
34
|
+
await writeFile(pointerPath,text);
|
|
35
|
+
assert.deepEqual(await readDoctorActivePointer(root),valid);
|
|
36
|
+
assert.equal(await readFile(pointerPath,'utf8'),text);
|
|
37
|
+
}
|
|
38
|
+
await writeFile(pointerPath,'BROKEN_JSON');
|
|
39
|
+
await assert.rejects(readDoctorActivePointer(root),/active pointer JSON invalid/);
|
|
40
|
+
assert.deepEqual(await readdir(root),['active-release.json']);
|
|
41
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {classifyDoctorControllerObservation,validateDoctorControllerObservation} from '../src/doctor-runtime-r58.mjs';
|
|
4
|
+
|
|
5
|
+
const coreRoot='D:/Projects/fixture/core';
|
|
6
|
+
const birth='2026-10-01T00:00:00.000Z';
|
|
7
|
+
const absent={alive:false,reason:'no-ledger',pid:null,creation_time_utc:null};
|
|
8
|
+
const authority=()=>Object.fromEntries(['process','coding','autonomous','desktop','host'].map(k=>[k,{configured:false,armed:false,reason:'no-policy'}]));
|
|
9
|
+
const offline=()=>({schema:'deadbyte.controller-observation.v1',observed_at_utc:birth,state:'OFFLINE',core_root:coreRoot,local_ready:false,bridge:{...absent},cloud:{...absent},core:{alive:false,reason:'bridge-unavailable',pid:null,parent_pid:null,creation_time_utc:null,identity_basis:null},supervisor:{configured:false,running:false,reason:'disabled'},authority:authority()});
|
|
10
|
+
const online=()=>({...offline(),state:'ONLINE',local_ready:true,bridge:{alive:true,reason:'verified',pid:101,creation_time_utc:birth},cloud:{alive:true,reason:'verified',pid:103,creation_time_utc:birth},core:{alive:true,reason:'verified',pid:102,parent_pid:101,creation_time_utc:birth,identity_basis:'command-line'}});
|
|
11
|
+
const missingCore=reason=>({alive:false,reason,pid:null,parent_pid:null,creation_time_utc:null,identity_basis:null});
|
|
12
|
+
test('R58 doctor runtime cannot inherit ONLINE when downstream topology contradicts it',()=>{
|
|
13
|
+
assert.equal(classifyDoctorControllerObservation(offline(),coreRoot).status,'PASS');
|
|
14
|
+
const good=classifyDoctorControllerObservation(online(),coreRoot);assert.equal(good.status,'PASS');assert.equal(good.availability.state,'ONLINE');
|
|
15
|
+
for(const reason of ['ambiguous-core','wrong-core-generation','core-image-mismatch','core-observation-failed']){
|
|
16
|
+
const report=classifyDoctorControllerObservation({...online(),core:missingCore(reason)},coreRoot);
|
|
17
|
+
assert.equal(report.status,'FAIL');assert.equal(report.availability.state,'FAILED');assert.ok(report.findings.find(f=>f.id==='runtime_core'&&f.level==='FAIL'));
|
|
18
|
+
}
|
|
19
|
+
const transient=classifyDoctorControllerObservation({...online(),core:missingCore('startup-zero-child')},coreRoot);
|
|
20
|
+
assert.equal(transient.status,'WARN');assert.equal(transient.availability.state,'STARTING');
|
|
21
|
+
});
|
|
22
|
+
test('R58 doctor separates healthy local topology from remote/cloud disconnect',()=>{
|
|
23
|
+
const partial=classifyDoctorControllerObservation({...online(),state:'DEGRADED',cloud:{...absent,reason:'process-missing'}},coreRoot);
|
|
24
|
+
assert.equal(partial.availability.local_healthy,true);assert.equal(partial.availability.remote_connected,false);
|
|
25
|
+
assert.notEqual(partial.availability.state,'ONLINE');assert.equal(partial.status,'WARN');
|
|
26
|
+
const parked=classifyDoctorControllerObservation({...offline(),state:'PARKED',cloud:online().cloud},coreRoot);
|
|
27
|
+
assert.equal(parked.availability.state,'PARKED');assert.equal(parked.status,'WARN');
|
|
28
|
+
});
|
|
29
|
+
test('R58 doctor strict snapshot rejects injection, wrong root and topology/schema drift',()=>{
|
|
30
|
+
for(const changes of [{extra:'injected'},{core_root:'C:/wrong'},{local_ready:'true'},{schema:'invalid'}])assert.throws(()=>validateDoctorControllerObservation({...online(),...changes},coreRoot));
|
|
31
|
+
assert.throws(()=>validateDoctorControllerObservation({...online(),core:{...online().core,parent_pid:999}},coreRoot));
|
|
32
|
+
assert.throws(()=>validateDoctorControllerObservation({...online(),bridge:{...online().bridge,reason:'unverified'}},coreRoot));
|
|
33
|
+
assert.throws(()=>validateDoctorControllerObservation({...offline(),core:{...offline().core,pid:101}},coreRoot));
|
|
34
|
+
assert.throws(()=>validateDoctorControllerObservation({...online(),authority:{...authority(),host:{configured:false,armed:true,reason:'standing-grant'}}},coreRoot));
|
|
35
|
+
});
|
|
36
|
+
test('R58 doctor surfaces corrupt grants and authority dependency loss without silently disarming',()=>{
|
|
37
|
+
const corrupt=online();corrupt.authority.coding={configured:true,armed:false,reason:'policy-digest'};
|
|
38
|
+
const copy=structuredClone(corrupt),result=classifyDoctorControllerObservation(corrupt,coreRoot);
|
|
39
|
+
assert.equal(result.status,'FAIL');assert.deepEqual(corrupt,copy);
|
|
40
|
+
const dependent=online();dependent.authority.autonomous={configured:true,armed:true,reason:'standing-grant'};
|
|
41
|
+
assert.equal(classifyDoctorControllerObservation(dependent,coreRoot).status,'FAIL');
|
|
42
|
+
const host=online();host.authority.host={configured:true,armed:true,reason:'standing-grant'};
|
|
43
|
+
const report=classifyDoctorControllerObservation(host,coreRoot);assert.equal(report.status,'WARN');assert.equal(host.authority.host.armed,true);
|
|
44
|
+
for(const finding of report.findings.filter(f=>f.level!=='PASS'))assert.ok(finding.what&&finding.evidence&&finding.next_action);
|
|
45
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {mkdir,mkdtemp,writeFile,readFile,readdir} from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import {inspectDoctorTransactions} from '../src/doctor-transactions-r58.mjs';
|
|
6
|
+
|
|
7
|
+
test('R58 bounded transaction inventory flags residue without recovering or overwriting it',async()=>{
|
|
8
|
+
const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});
|
|
9
|
+
const root=await mkdtemp(path.join(base,'doctor-transactions-'));
|
|
10
|
+
assert.equal((await inspectDoctorTransactions(root)).status,'PASS');assert.deepEqual(await readdir(root),[]);
|
|
11
|
+
const transactions=path.join(root,'evidence','updates');await mkdir(transactions,{recursive:true});
|
|
12
|
+
const write=async(name,body)=>{const dir=path.join(transactions,name);await mkdir(dir);const file=path.join(dir,'state.json'),bytes=JSON.stringify(body);await writeFile(file,bytes);return {file,bytes};};
|
|
13
|
+
const done=await write('done',{schema:'deadbyte.r27-slot-update-state.v1',phase:'completed'});
|
|
14
|
+
assert.equal((await inspectDoctorTransactions(root)).status,'PASS');
|
|
15
|
+
const pending=await write('pending',{schema:'deadbyte.r31-slot-rollback-state.v1',phase:'prior_pointer_restored',supervisor_pid:process.pid});
|
|
16
|
+
const result=await inspectDoctorTransactions(root);assert.equal(result.status,'WARN');assert.ok(result.findings.some(f=>f.evidence.recorded_phase==='prior_pointer_restored'));
|
|
17
|
+
for(const item of [done,pending])assert.equal(await readFile(item.file,'utf8'),item.bytes);
|
|
18
|
+
const bounded=await inspectDoctorTransactions(root,{maxEntries:1});assert.equal(bounded.status,'WARN');assert.ok(bounded.findings.some(f=>f.evidence.inventory_complete===false));
|
|
19
|
+
const corrupt=await write('corrupt',{schema:'INVALID',phase:'completed'});assert.equal((await inspectDoctorTransactions(root)).status,'FAIL');assert.equal(await readFile(corrupt.file,'utf8'),corrupt.bytes);
|
|
20
|
+
await assert.rejects(inspectDoctorTransactions(root,{maxEntries:257}),/budget invalid/);
|
|
21
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {mkdir,mkdtemp,writeFile,readFile} from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import {fileURLToPath} from 'node:url';
|
|
6
|
+
import {spawn} from 'node:child_process';
|
|
7
|
+
import {setTimeout as delay} from 'node:timers/promises';
|
|
8
|
+
|
|
9
|
+
test('R58 guardian rejects an IPC parent that does not match its declared owner before cleanup', {timeout:10000}, async()=>{
|
|
10
|
+
const base='D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';await mkdir(base,{recursive:true});
|
|
11
|
+
const root=await mkdtemp(path.join(base,'guardian-channel-'));await mkdir(path.join(root,'bin'));await mkdir(path.join(root,'runtime'));
|
|
12
|
+
const trace=path.join(root,'trace.txt'),markerPath=path.join(root,'runtime','remote-session.json');
|
|
13
|
+
const marker={schema:'deadbyte.remote-session.v2',owner_pid:process.pid+100000,session_nonce:'c'.repeat(64)};
|
|
14
|
+
await writeFile(markerPath,JSON.stringify(marker));
|
|
15
|
+
await writeFile(path.join(root,'bin','DEADBYTE-MCP.ps1'),`param([string]$Command)\n[IO.File]::AppendAllText('${trace.replaceAll("'","''")}',$Command+[Environment]::NewLine)\nexit 0\n`);
|
|
16
|
+
const child=spawn(process.execPath,[fileURLToPath(new URL('../src/remote-session-guardian.mjs',import.meta.url)),'--state-root',root,'--owner-pid',String(marker.owner_pid),'--session-nonce',marker.session_nonce,'--owner-channel','ipc'],{env:{...process.env,DEADBYTE_STATE_ROOT:root},windowsHide:true,stdio:['ignore','ignore','ignore','ipc']});
|
|
17
|
+
const closed=new Promise(resolve=>child.once('exit',code=>resolve(code)));
|
|
18
|
+
try{
|
|
19
|
+
await delay(400);if(child.connected)child.disconnect();
|
|
20
|
+
const code=await Promise.race([closed,delay(4000).then(()=>null)]);
|
|
21
|
+
assert.notEqual(code,null,'wrong parent must fail promptly');
|
|
22
|
+
assert.notEqual(code,0,'wrong IPC parent must not be accepted');
|
|
23
|
+
await assert.rejects(readFile(trace),{code:'ENOENT'},'invalid guardian must run no controller commands');
|
|
24
|
+
assert.deepEqual(JSON.parse(await readFile(markerPath,'utf8')),marker);
|
|
25
|
+
}finally{if(child.exitCode===null)child.kill();await closed;}
|
|
26
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdir, mkdtemp, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { renderStableLauncherPs1 } from '../src/release-slot.mjs';
|
|
7
|
+
|
|
8
|
+
test('R58 launcher dispatch uses native Windows PowerShell even when entered from pwsh', async () => {
|
|
9
|
+
const base = 'D:/Projects/deadbyte-mcp/testing/0.15.35/fixtures';
|
|
10
|
+
await mkdir(base, { recursive: true });
|
|
11
|
+
const fixture = await mkdtemp(path.join(base, 'launcher-shell-'));
|
|
12
|
+
const controller = path.join(fixture, 'controller.ps1');
|
|
13
|
+
await writeFile(controller, "param([string]$Action)\nWrite-Output ('FIXTURE:' + $Action)\nexit 7\n");
|
|
14
|
+
const rendered = renderStableLauncherPs1();
|
|
15
|
+
const start = rendered.indexOf('$powershell =');
|
|
16
|
+
assert.ok(start > 0, 'generated launcher has a dispatch boundary');
|
|
17
|
+
const dispatch = path.join(fixture, 'dispatch.ps1');
|
|
18
|
+
// Execute the actual generated dispatch, independently of preceding manifest checks.
|
|
19
|
+
await writeFile(dispatch, "$ErrorActionPreference = 'Stop'\n$controller = '" + controller.replaceAll("'", "''") + "'\n$ControllerArgs = @('status')\n" + rendered.slice(start));
|
|
20
|
+
const native = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
|
|
21
|
+
const modern = path.join(process.env.USERPROFILE, '.cache', 'codex-runtimes', 'codex-primary-runtime', 'dependencies', 'native', 'powershell', 'pwsh.exe');
|
|
22
|
+
for (const executable of [native, modern]) {
|
|
23
|
+
const observed = spawnSync(executable, ['-NoProfile', '-File', dispatch], { encoding: 'utf8', timeout: 20000 });
|
|
24
|
+
assert.ifError(observed.error);
|
|
25
|
+
assert.equal(observed.status, 7, observed.stderr);
|
|
26
|
+
assert.match(observed.stdout, /FIXTURE:status/);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {foregroundIdentityMatches,queryForegroundIdentity} from '../src/foreground-process-identity.mjs';
|
|
4
|
+
|
|
5
|
+
test('R58 owner identity rejects PID reuse and every material identity drift',()=>{
|
|
6
|
+
const expected={schema:'deadbyte.foreground-process.v1',pid:100,parent_pid:50,creation_utc:'2026-10-01T00:00:00.000Z',executable_path:'C:/Windows/node.exe',command_line_sha256:'a'.repeat(64)};
|
|
7
|
+
assert.equal(foregroundIdentityMatches(expected,{...expected}),true);
|
|
8
|
+
assert.equal(foregroundIdentityMatches(expected,null),false);
|
|
9
|
+
for(const changes of [{pid:101},{parent_pid:51},{creation_utc:'2026-10-01T00:00:01.000Z'},{executable_path:'C:/other/node.exe'},{command_line_sha256:'b'.repeat(64)}])assert.equal(foregroundIdentityMatches(expected,{...expected,...changes}),false);
|
|
10
|
+
assert.throws(()=>foregroundIdentityMatches(undefined,expected),/unverified/);
|
|
11
|
+
assert.throws(()=>foregroundIdentityMatches(expected,{}),/incomplete/);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('R58 narrow identity query binds the current live process and rejects injection',()=>{
|
|
15
|
+
const identity=queryForegroundIdentity(process.pid);
|
|
16
|
+
assert.equal(identity.pid,process.pid);assert.equal(identity.parent_pid,process.ppid);
|
|
17
|
+
assert.equal(foregroundIdentityMatches(identity,queryForegroundIdentity(process.pid)),true);
|
|
18
|
+
assert.throws(()=>queryForegroundIdentity('1;anything'),/positive Windows PID/);
|
|
19
|
+
assert.throws(()=>queryForegroundIdentity(0),/positive Windows PID/);
|
|
20
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {readFile} from 'node:fs/promises';
|
|
4
|
+
|
|
5
|
+
const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
|
|
6
|
+
const json=rel=>read(rel).then(JSON.parse);
|
|
7
|
+
|
|
8
|
+
test('R58 identity is coherent and parent is exact production-accepted 0.15.34',async()=>{
|
|
9
|
+
const [pkg,lock,release,prov,matrix,sbom,version,bridgePkg]=await Promise.all([
|
|
10
|
+
json('package.json'),json('package-lock.json'),json('RELEASE.json'),json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),json('bridge/package.json')
|
|
11
|
+
]);
|
|
12
|
+
assert.equal(pkg.version,'0.15.35');
|
|
13
|
+
assert.equal(lock.version,pkg.version);
|
|
14
|
+
assert.equal(lock.packages[''].version,pkg.version);
|
|
15
|
+
assert.match(version,/DEADBYTE_VERSION = '0\.15\.35'/);
|
|
16
|
+
assert.equal(release.version,pkg.version);
|
|
17
|
+
assert.equal(release.train,'R58');
|
|
18
|
+
assert.equal(prov.version,pkg.version);
|
|
19
|
+
assert.equal(matrix.version,pkg.version);
|
|
20
|
+
assert.equal(matrix.train,'R58');
|
|
21
|
+
assert.equal(sbom.metadata.component.version,pkg.version);
|
|
22
|
+
assert.equal(bridgePkg.version,pkg.version);
|
|
23
|
+
assert.deepEqual(release.runtime_predecessor,{
|
|
24
|
+
release_id:'v0.15.34-2199bb59f0e0fc20',
|
|
25
|
+
manifest_sha256:'2199bb59f0e0fc205d470d11f990d3ce3df444be5eba2a7d8dbc60d5f5b790bb',
|
|
26
|
+
generation_manifest_sha256:'1a20a62aaeb324a9b5c03d158952f35092d58fedf2ac7725820ba2b094a4a88f'
|
|
27
|
+
});
|
|
28
|
+
assert.equal(release.parent.tarball_sha256,'a6f7b21faf34793ca17dfb6d0e9ec03320f1468d011e75d8349098df82fc2639');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('R58 consolidation evidence preserves fail-closed and non-final claims',async()=>{
|
|
32
|
+
const [release,prov,matrix]=await Promise.all([json('RELEASE.json'),json('PROVENANCE.json'),json('TEST-MATRIX.json')]);
|
|
33
|
+
assert.equal(release.consolidation.bridge_bundled_inside_release,true);
|
|
34
|
+
assert.equal(release.consolidation.bridge_recursive_local_dependency_binding,true);
|
|
35
|
+
assert.equal(release.consolidation.bridge_dynamic_relative_import_fail_closed,true);
|
|
36
|
+
assert.equal(release.consolidation.bridge_path_escape_fail_closed,true);
|
|
37
|
+
assert.equal(release.consolidation.performance_acceptance,'PASS_BOUNDED_PREPUBLISH');
|
|
38
|
+
assert.equal(release.consolidation.cross_plane_acceptance,'PASS');
|
|
39
|
+
assert.equal(release.consolidation.public_surface_compatibility,'PASS_43_TOOLS_NO_SCHEMA_DRIFT');
|
|
40
|
+
assert.equal(matrix.observed_pre_release_evidence.cross_plane.status,'PASS');
|
|
41
|
+
assert.equal(matrix.observed_pre_release_evidence.public_surface.candidate_tool_count,43);
|
|
42
|
+
assert.equal(matrix.observed_pre_release_evidence.performance.status,'PASS_BOUNDED_PREPUBLISH');
|
|
43
|
+
assert.ok(['PENDING_R58_FRESH','PASS'].includes(matrix.observed_pre_release_evidence.full_regression.status));
|
|
44
|
+
assert.equal(prov.operator_override.four_hour_soak,'NOT_COMPLETED');
|
|
45
|
+
assert.equal(prov.operator_override.clean_machine,'NOT_COMPLETED');
|
|
46
|
+
assert.equal(prov.operator_override.stable_final_claim,false);
|
|
47
|
+
assert.equal(matrix.operator_override.stable_final_claim,false);
|
|
48
|
+
assert.equal(release.stabilization.stable_final_claim,false);
|
|
49
|
+
});
|