deadbyte-mcp 0.15.1 → 0.15.2
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 +54 -44
- package/PROVENANCE.json +6 -5
- package/README.txt +36 -20
- package/RELEASE.json +24 -8
- package/SBOM.cdx.json +3 -3
- package/controller/README.TXT +2 -2
- package/controller/deadbyte-controller.ps1 +50 -2
- package/controller/deadbyte-process-policy.json +63 -1
- package/docs/ARCHITECTURE.md +3 -4
- package/package.json +9 -7
- package/scripts/deferred-slot-operation-r46.mjs +126 -0
- package/scripts/final-closure-r46.mjs +98 -0
- package/scripts/final-closure-verify-r46.mjs +119 -0
- package/scripts/full-regression-r46.mjs +20 -0
- package/scripts/gate-windows-r46.ps1 +56 -0
- package/scripts/refresh-process-policy.mjs +64 -7
- package/scripts/release-parity-r46.mjs +187 -0
- package/scripts/windows-gate-evidence-r46.mjs +110 -0
- package/src/capability-ledger.mjs +1 -0
- package/src/compact-gateway-mcp-tools.mjs +7 -5
- package/src/deadbyte-cli.mjs +7 -3
- package/src/machine-fs-mcp-tools.mjs +3 -3
- package/src/machine-fs-output-contracts.mjs +1 -1
- package/src/machine-fs-read-worker.mjs +46 -0
- package/src/machine-fs.mjs +63 -10
- package/src/mcp-server.mjs +4 -0
- package/src/mcp-smoke-client.mjs +4 -1
- package/src/observation-runtime.mjs +25 -4
- package/src/process-mcp-tools.mjs +18 -5
- package/src/process-output-contracts.mjs +20 -3
- package/src/process-policy.mjs +3 -1
- package/src/process-runtime.mjs +99 -19
- package/src/process-smoke-client.mjs +67 -22
- package/src/release-generation.mjs +22 -3
- package/src/remote-device-r44.mjs +53 -15
- package/src/remote-mcp-smoke-client.mjs +1 -1
- package/src/stdio-console-guard.mjs +24 -0
- package/src/version.mjs +1 -1
- package/test/cli-entrypoint.test.mjs +3 -3
- package/test/compact-gateway-r36.test.mjs +28 -0
- package/test/core.test.mjs +1 -1
- package/test/full-max-catalog-r46.test.mjs +92 -0
- package/test/machine-fs-mcp-tools.test.mjs +4 -1
- package/test/machine-fs-runtime.test.mjs +18 -2
- package/test/observation-runtime.test.mjs +29 -2
- package/test/process-mcp-tools.test.mjs +23 -5
- package/test/process-policy-refresh.test.mjs +87 -10
- package/test/process-runtime.test.mjs +111 -1
- package/test/process-supervision.test.mjs +4 -2
- package/test/production-docs.test.mjs +3 -3
- package/test/r33-finalization.test.mjs +3 -3
- package/test/release-generation.test.mjs +25 -11
- package/test/release-version.test.mjs +99 -44
- package/test/remote-device-r44.test.mjs +75 -0
- package/test/remote-r24-catalog.test.mjs +2 -2
|
@@ -13,18 +13,58 @@ async function fixture() {
|
|
|
13
13
|
const root = await mkdtemp(path.join(os.tmpdir(), 'deadbyte-process-refresh-'));
|
|
14
14
|
const bin = path.join(root, 'bin');
|
|
15
15
|
const controller = path.join(root, 'controller');
|
|
16
|
+
const systemRoot = path.join(root, 'Windows');
|
|
17
|
+
const system32 = path.join(systemRoot, 'System32');
|
|
18
|
+
const powershellDir = path.join(system32, 'WindowsPowerShell', 'v1.0');
|
|
16
19
|
await mkdir(bin, { recursive: true });
|
|
17
20
|
await mkdir(controller, { recursive: true });
|
|
21
|
+
await mkdir(powershellDir, { recursive: true });
|
|
22
|
+
|
|
18
23
|
const hostPath = path.join(bin, 'deadbyte-process-host.exe');
|
|
19
24
|
const hostBytes = Buffer.from('fresh-native-host\n');
|
|
25
|
+
const cmdPath = path.join(system32, 'cmd.exe');
|
|
26
|
+
const cmdBytes = Buffer.from('target-cmd\n');
|
|
27
|
+
const powershellPath = path.join(powershellDir, 'powershell.exe');
|
|
28
|
+
const powershellBytes = Buffer.from('target-powershell\n');
|
|
20
29
|
await writeFile(hostPath, hostBytes);
|
|
30
|
+
await writeFile(cmdPath, cmdBytes);
|
|
31
|
+
await writeFile(powershellPath, powershellBytes);
|
|
32
|
+
|
|
21
33
|
const policyPath = path.join(controller, 'deadbyte-process-policy.json');
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
const profile = executable => ({
|
|
35
|
+
executable,
|
|
36
|
+
executable_sha256:'1'.repeat(64),
|
|
37
|
+
root_ids:['core'],
|
|
38
|
+
prefix_args:[],
|
|
39
|
+
transport:'pipe',
|
|
40
|
+
max_args:1,
|
|
41
|
+
max_arg_bytes:8192,
|
|
42
|
+
max_sessions:1,
|
|
43
|
+
max_input_bytes:4096,
|
|
44
|
+
max_retained_output_bytes:4096,
|
|
45
|
+
env_allow:[],
|
|
46
|
+
input_actions:{}
|
|
47
|
+
});
|
|
48
|
+
const policy = {
|
|
49
|
+
schema:'deadbyte.process-policy.v1',
|
|
50
|
+
enabled:true,
|
|
51
|
+
grant_file:path.join(root,'runtime','grant.json'),
|
|
52
|
+
state_dir:path.join(root,'state'),
|
|
53
|
+
native_host:{ path:hostPath, sha256:'0'.repeat(64) },
|
|
54
|
+
roots:{core:{path:root,deny_paths:[]}},
|
|
55
|
+
profiles:{
|
|
56
|
+
ping_hold:profile(cmdPath),
|
|
57
|
+
powershell:profile(powershellPath),
|
|
58
|
+
powershell_repl:profile(powershellPath)
|
|
59
|
+
}
|
|
60
|
+
};
|
|
25
61
|
await writeFile(policyPath, `${JSON.stringify(policy,null,2)}\n`);
|
|
26
|
-
return {
|
|
62
|
+
return {
|
|
63
|
+
root, policyPath, hostPath, hostBytes, systemRoot,
|
|
64
|
+
cmdPath, cmdBytes, powershellPath, powershellBytes, policy
|
|
65
|
+
};
|
|
27
66
|
}
|
|
67
|
+
|
|
28
68
|
test('R33 candidate process policy self-binds to the current repository root', async () => {
|
|
29
69
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
30
70
|
const policyPath = path.join(repoRoot, 'controller', 'deadbyte-process-policy.json');
|
|
@@ -33,32 +73,69 @@ test('R33 candidate process policy self-binds to the current repository root', a
|
|
|
33
73
|
assert.equal(policy.state_dir, path.join(repoRoot, 'controller', 'runtime', 'process-state'));
|
|
34
74
|
assert.equal(policy.native_host.path, path.join(repoRoot, 'bin', 'deadbyte-process-host.exe'));
|
|
35
75
|
assert.equal(policy.roots.core.path, repoRoot);
|
|
76
|
+
assert.ok(policy.profiles.ping_hold);
|
|
77
|
+
assert.ok(policy.profiles.powershell);
|
|
78
|
+
assert.ok(policy.profiles.powershell_repl);
|
|
79
|
+
assert.equal(policy.profiles.powershell_repl.allow_raw_input,true);
|
|
80
|
+
assert.deepEqual(policy.profiles.powershell.prefix_args, ['-NoLogo','-NoProfile','-NonInteractive','-Command']);
|
|
81
|
+
assert.equal(policy.profiles.powershell.max_args, 1);
|
|
82
|
+
assert.equal(policy.profiles.powershell.max_arg_bytes, 8192);
|
|
36
83
|
});
|
|
37
84
|
|
|
38
|
-
test('
|
|
85
|
+
test('process policy refresh repins native host and Windows system executables', async () => {
|
|
39
86
|
const f = await fixture();
|
|
40
|
-
const result = await refreshProcessPolicy({ repoRoot:f.root, policyPath:f.policyPath });
|
|
87
|
+
const result = await refreshProcessPolicy({ repoRoot:f.root, policyPath:f.policyPath, systemRoot:f.systemRoot });
|
|
41
88
|
const after = JSON.parse(await readFile(f.policyPath,'utf8'));
|
|
42
89
|
assert.equal(after.native_host.path, f.hostPath);
|
|
43
90
|
assert.equal(after.native_host.sha256, sha256(f.hostBytes));
|
|
91
|
+
assert.equal(after.profiles.ping_hold.executable, f.cmdPath);
|
|
92
|
+
assert.equal(after.profiles.ping_hold.executable_sha256, sha256(f.cmdBytes));
|
|
93
|
+
assert.equal(after.profiles.powershell.executable, f.powershellPath);
|
|
94
|
+
assert.equal(after.profiles.powershell.executable_sha256, sha256(f.powershellBytes));
|
|
95
|
+
assert.equal(after.profiles.powershell_repl.executable, f.powershellPath);
|
|
96
|
+
assert.equal(after.profiles.powershell_repl.executable_sha256, sha256(f.powershellBytes));
|
|
44
97
|
assert.equal(result.native_host_sha256, sha256(f.hostBytes));
|
|
98
|
+
assert.equal(result.cmd_executable_sha256, sha256(f.cmdBytes));
|
|
99
|
+
assert.equal(result.powershell_executable_sha256, sha256(f.powershellBytes));
|
|
100
|
+
assert.equal(result.powershell_repl_executable_sha256, sha256(f.powershellBytes));
|
|
101
|
+
|
|
45
102
|
const expected = structuredClone(f.policy);
|
|
46
103
|
expected.native_host.sha256 = sha256(f.hostBytes);
|
|
104
|
+
expected.profiles.ping_hold.executable_sha256 = sha256(f.cmdBytes);
|
|
105
|
+
expected.profiles.powershell.executable_sha256 = sha256(f.powershellBytes);
|
|
106
|
+
expected.profiles.powershell_repl.executable_sha256 = sha256(f.powershellBytes);
|
|
47
107
|
assert.deepEqual(after, expected);
|
|
48
108
|
});
|
|
49
109
|
|
|
50
|
-
test('
|
|
110
|
+
test('process policy refresh fails closed when native-host path is not the candidate bin path', async () => {
|
|
51
111
|
const f = await fixture();
|
|
52
112
|
const raw = JSON.parse(await readFile(f.policyPath,'utf8'));
|
|
53
113
|
raw.native_host.path = process.execPath;
|
|
54
114
|
await writeFile(f.policyPath, `${JSON.stringify(raw,null,2)}\n`);
|
|
55
|
-
await assert.rejects(
|
|
115
|
+
await assert.rejects(
|
|
116
|
+
() => refreshProcessPolicy({ repoRoot:f.root, policyPath:f.policyPath, systemRoot:f.systemRoot }),
|
|
117
|
+
/native_host path must equal candidate bin/
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('process policy refresh fails closed when a system profile path is not target-bound', async () => {
|
|
122
|
+
const f = await fixture();
|
|
123
|
+
const raw = JSON.parse(await readFile(f.policyPath,'utf8'));
|
|
124
|
+
raw.profiles.powershell.executable = process.execPath;
|
|
125
|
+
await writeFile(f.policyPath, `${JSON.stringify(raw,null,2)}\n`);
|
|
126
|
+
await assert.rejects(
|
|
127
|
+
() => refreshProcessPolicy({ repoRoot:f.root, policyPath:f.policyPath, systemRoot:f.systemRoot }),
|
|
128
|
+
/profile 'powershell' executable path mismatch/
|
|
129
|
+
);
|
|
56
130
|
});
|
|
57
131
|
|
|
58
|
-
test('
|
|
132
|
+
test('process policy refresh refuses a malformed or disabled process policy', async () => {
|
|
59
133
|
const f = await fixture();
|
|
60
134
|
const raw = JSON.parse(await readFile(f.policyPath,'utf8'));
|
|
61
135
|
raw.enabled = false;
|
|
62
136
|
await writeFile(f.policyPath, `${JSON.stringify(raw,null,2)}\n`);
|
|
63
|
-
await assert.rejects(
|
|
137
|
+
await assert.rejects(
|
|
138
|
+
() => refreshProcessPolicy({ repoRoot:f.root, policyPath:f.policyPath, systemRoot:f.systemRoot }),
|
|
139
|
+
/schema\/enabled mismatch/
|
|
140
|
+
);
|
|
64
141
|
});
|
|
@@ -12,6 +12,7 @@ import { generateTrustKeypair } from '../src/trust.mjs';
|
|
|
12
12
|
const repo = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
13
13
|
const host = path.join(repo, 'bin', 'deadbyte-process-host.exe');
|
|
14
14
|
const cmd = 'C:\\Windows\\System32\\cmd.exe';
|
|
15
|
+
const powershell = 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe';
|
|
15
16
|
const sha = bytes => createHash('sha256').update(bytes).digest('hex');
|
|
16
17
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
17
18
|
|
|
@@ -25,6 +26,7 @@ async function fixture() {
|
|
|
25
26
|
const policyPath = path.join(root, 'process-policy.json');
|
|
26
27
|
const hostSha = sha(await readFile(host));
|
|
27
28
|
const cmdSha = sha(await readFile(cmd));
|
|
29
|
+
const powershellSha = sha(await readFile(powershell));
|
|
28
30
|
const raw = {
|
|
29
31
|
schema: PROCESS_POLICY_SCHEMA, enabled: true, grant_file: grantFile, state_dir: stateDir,
|
|
30
32
|
native_host: { path: host, sha256: hostSha },
|
|
@@ -47,6 +49,18 @@ async function fixture() {
|
|
|
47
49
|
prefix_args: ['/d', '/q'], max_args: 0, max_arg_bytes: 256,
|
|
48
50
|
max_sessions: 1, max_input_bytes: 4096, max_retained_output_bytes: 65536,
|
|
49
51
|
env_allow: ['PATH', 'TEMP', 'TMP'], input_actions: { ping: 'echo mustnotrun\r\n' }
|
|
52
|
+
},
|
|
53
|
+
powershell: {
|
|
54
|
+
executable: powershell, executable_sha256: powershellSha, root_ids: ['core'], transport: 'pipe',
|
|
55
|
+
prefix_args: ['-NoLogo','-NoProfile','-NonInteractive','-Command'], max_args: 1, max_arg_bytes: 8192,
|
|
56
|
+
max_sessions: 2, max_input_bytes: 65536, max_retained_output_bytes: 1048576,
|
|
57
|
+
env_allow: ['PATH','TEMP','TMP','SystemRoot','WINDIR','USERPROFILE','PSModulePath','COMSPEC','PATHEXT'], input_actions: {}
|
|
58
|
+
},
|
|
59
|
+
powershell_repl: {
|
|
60
|
+
executable: powershell, executable_sha256: powershellSha, root_ids: ['core'], transport: 'pipe', allow_raw_input: true,
|
|
61
|
+
prefix_args: ['-NoLogo','-NoProfile','-NonInteractive'], max_args: 0, max_arg_bytes: 256,
|
|
62
|
+
max_sessions: 2, max_input_bytes: 65536, max_retained_output_bytes: 4 * 1024 * 1024,
|
|
63
|
+
env_allow: ['PATH','TEMP','TMP','SystemRoot','WINDIR','USERPROFILE','PSModulePath','COMSPEC','PATHEXT'], input_actions: {}
|
|
50
64
|
}
|
|
51
65
|
}
|
|
52
66
|
};
|
|
@@ -54,7 +68,7 @@ async function fixture() {
|
|
|
54
68
|
const policy = await loadProcessPolicy(policyPath);
|
|
55
69
|
await writeFile(grantFile, JSON.stringify({
|
|
56
70
|
schema: PROCESS_GRANT_SCHEMA, policy_sha256: policy.policy_sha256,
|
|
57
|
-
instance_nonce: 'a'.repeat(64), profile_ids: ['echo', 'hold', 'conptyhold'], root_ids: ['core'],
|
|
71
|
+
instance_nonce: 'a'.repeat(64), profile_ids: ['echo', 'hold', 'conptyhold', 'powershell', 'powershell_repl'], root_ids: ['core'],
|
|
58
72
|
granted_at_utc: '2026-09-14T00:00:00Z'
|
|
59
73
|
}));
|
|
60
74
|
const keys = await generateTrustKeypair({
|
|
@@ -90,6 +104,102 @@ test('R31 runtime starts one approved profile and exposes ordered bounded output
|
|
|
90
104
|
assert.equal(observed.page.truncated, false);
|
|
91
105
|
});
|
|
92
106
|
|
|
107
|
+
test('R46 runtime executes fileless PowerShell source without ps1 materialization', { skip: process.platform !== 'win32' }, async () => {
|
|
108
|
+
const f = await fixture();
|
|
109
|
+
const source = "$ErrorActionPreference='Stop';$before=@(Get-ChildItem -LiteralPath $env:TEMP -Filter '*.ps1' -File -ErrorAction SilentlyContinue|ForEach-Object{$_.FullName});[Console]::WriteLine('DB_FILELESS_PS_TEST');[Console]::WriteLine('PSCommandPath=' + [string]$PSCommandPath);[Console]::WriteLine('InvocationPath=' + [string]$MyInvocation.MyCommand.Path);$after=@(Get-ChildItem -LiteralPath $env:TEMP -Filter '*.ps1' -File -ErrorAction SilentlyContinue|ForEach-Object{$_.FullName});$new=@($after|Where-Object{$_ -notin $before});[Console]::WriteLine('NEW_TEMP_PS1_COUNT=' + $new.Count)";
|
|
110
|
+
const started = await f.runtime.start({ profileId: 'powershell', rootId: 'core', cwd: '.', args: [source] });
|
|
111
|
+
const observed = await waitFor(f.runtime, started.session_id, text => text.includes('NEW_TEMP_PS1_COUNT=0'));
|
|
112
|
+
assert.match(observed.text, /DB_FILELESS_PS_TEST/);
|
|
113
|
+
assert.match(observed.text, /PSCommandPath=\r?\n/);
|
|
114
|
+
assert.match(observed.text, /InvocationPath=\r?\n/);
|
|
115
|
+
assert.match(observed.text, /NEW_TEMP_PS1_COUNT=0/);
|
|
116
|
+
const deadline = Date.now() + 5000;
|
|
117
|
+
let status = await f.runtime.status({ sessionId: started.session_id });
|
|
118
|
+
while (status.state === 'running' && Date.now() < deadline) {
|
|
119
|
+
await sleep(25);
|
|
120
|
+
status = await f.runtime.status({ sessionId: started.session_id });
|
|
121
|
+
}
|
|
122
|
+
assert.equal(status.state, 'exited');
|
|
123
|
+
assert.equal(status.exit_code, 0);
|
|
124
|
+
const verified = await f.runtime.verifyEventJournal({ sessionId: started.session_id });
|
|
125
|
+
assert.equal(verified.ok, true);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('R46 process output retention evicts oldest bytes without losing tail identity under multi-megabyte output', { skip: process.platform !== 'win32' }, async () => {
|
|
129
|
+
const f = await fixture();
|
|
130
|
+
const source = "[Console]::Write(('A'*2097152));[Console]::WriteLine('DB_RING_TAIL_MARK')";
|
|
131
|
+
const started = await f.runtime.start({ profileId: 'powershell', rootId: 'core', cwd: '.', args: [source] });
|
|
132
|
+
const deadline = Date.now() + 10000;
|
|
133
|
+
let status = await f.runtime.status({ sessionId: started.session_id });
|
|
134
|
+
while (status.state === 'running' && Date.now() < deadline) {
|
|
135
|
+
await sleep(25);
|
|
136
|
+
status = await f.runtime.status({ sessionId: started.session_id });
|
|
137
|
+
}
|
|
138
|
+
assert.equal(status.state, 'exited');
|
|
139
|
+
assert.equal(status.exit_code, 0);
|
|
140
|
+
assert.ok(status.stream_head > 2 * 1024 * 1024);
|
|
141
|
+
assert.ok(status.earliest_offset > 0);
|
|
142
|
+
assert.ok(status.stream_head - status.earliest_offset <= 1024 * 1024);
|
|
143
|
+
const fromStart = await f.runtime.read({ sessionId: started.session_id, offset: 0, maxBytes: 4096 });
|
|
144
|
+
assert.equal(fromStart.truncated, true);
|
|
145
|
+
assert.equal(fromStart.offset, status.earliest_offset);
|
|
146
|
+
const tail = await f.runtime.read({ sessionId: started.session_id, offset: -4096, maxBytes: 4096 });
|
|
147
|
+
const tailText = Buffer.from(tail.data_base64, 'base64').toString('utf8');
|
|
148
|
+
assert.match(tailText, /DB_RING_TAIL_MARK/);
|
|
149
|
+
const verified = await f.runtime.verifyEventJournal({ sessionId: started.session_id });
|
|
150
|
+
assert.equal(verified.ok, true);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('R46 process raw input keeps persistent PowerShell state with bounded wait and tail reads', { skip: process.platform !== 'win32' }, async () => {
|
|
154
|
+
const f = await fixture();
|
|
155
|
+
const started = await f.runtime.start({ profileId: 'powershell_repl', rootId: 'core', cwd: '.', args: [] });
|
|
156
|
+
try {
|
|
157
|
+
const first = await f.runtime.write({ sessionId: started.session_id, input: "$x=41;[Console]::WriteLine('DB_REPL_SET')", appendNewline: true });
|
|
158
|
+
assert.equal(first.session.state, 'running');
|
|
159
|
+
assert.match(first.logical_sha256, /^[0-9a-f]{64}$/);
|
|
160
|
+
const page1 = await f.runtime.read({ sessionId: started.session_id, offset: 0, maxBytes: 65536, waitMs: 3000, waitFor: 'DB_REPL_SET' });
|
|
161
|
+
const text1 = Buffer.from(page1.data_base64, 'base64').toString('utf8');
|
|
162
|
+
assert.match(text1, /DB_REPL_SET/);
|
|
163
|
+
|
|
164
|
+
const beforeSecond = (await f.runtime.status({ sessionId: started.session_id })).stream_head;
|
|
165
|
+
await f.runtime.write({ sessionId: started.session_id, input: "[Console]::WriteLine('DB_REPL_VALUE=' + ($x+1))", appendNewline: true });
|
|
166
|
+
const waited = await f.runtime.read({ sessionId: started.session_id, offset: beforeSecond, maxBytes: 65536, waitMs: 3000, waitFor: 'DB_REPL_VALUE=42' });
|
|
167
|
+
const waitedText = Buffer.from(waited.data_base64, 'base64').toString('utf8');
|
|
168
|
+
assert.equal(waited.wait_satisfied, true);
|
|
169
|
+
assert.match(waitedText, /DB_REPL_VALUE=42/);
|
|
170
|
+
const tail = await f.runtime.read({ sessionId: started.session_id, offset: -4096, maxBytes: 4096, waitMs: 0 });
|
|
171
|
+
const tailText = Buffer.from(tail.data_base64, 'base64').toString('utf8');
|
|
172
|
+
assert.match(tailText, /DB_REPL_VALUE=42/);
|
|
173
|
+
|
|
174
|
+
const journal = await readFile(path.join(f.stateDir, `${started.session_id}.jsonl`), 'utf8');
|
|
175
|
+
assert.doesNotMatch(journal, /DB_REPL_SET|DB_REPL_VALUE|\$x=41/);
|
|
176
|
+
const verified = await f.runtime.verifyEventJournal({ sessionId: started.session_id });
|
|
177
|
+
assert.equal(verified.ok, true);
|
|
178
|
+
assert.ok(verified.event_count >= 3);
|
|
179
|
+
} finally {
|
|
180
|
+
await f.runtime.terminate({ sessionId: started.session_id }).catch(() => {});
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('R46 raw process input is profile-opt-in, bounded, and rechecks standing authority', { skip: process.platform !== 'win32' }, async () => {
|
|
185
|
+
const f = await fixture();
|
|
186
|
+
const hold = await f.runtime.start({ profileId: 'hold', rootId: 'core', cwd: '.', args: [] });
|
|
187
|
+
try {
|
|
188
|
+
await assert.rejects(() => f.runtime.write({ sessionId: hold.session_id, input: 'echo forbidden', appendNewline: true }), /does not allow raw input/);
|
|
189
|
+
} finally {
|
|
190
|
+
await f.runtime.terminate({ sessionId: hold.session_id }).catch(() => {});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const repl = await f.runtime.start({ profileId: 'powershell_repl', rootId: 'core', cwd: '.', args: [] });
|
|
194
|
+
try {
|
|
195
|
+
await assert.rejects(() => f.runtime.write({ sessionId: repl.session_id, input: 'x'.repeat(65536), appendNewline: true }), /exceeds profile input bound/);
|
|
196
|
+
await rm(f.grantFile);
|
|
197
|
+
await assert.rejects(() => f.runtime.write({ sessionId: repl.session_id, input: 'Write-Output denied', appendNewline: true }), /process plane is disarmed/);
|
|
198
|
+
} finally {
|
|
199
|
+
await f.runtime.terminate({ sessionId: repl.session_id }).catch(() => {});
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
93
203
|
test('R31 runtime lists, reports and terminates only its owned session', { skip: process.platform !== 'win32' }, async () => {
|
|
94
204
|
const f = await fixture();
|
|
95
205
|
const started = await f.runtime.start({ profileId: 'hold', rootId: 'core', cwd: '.', args: [] });
|
|
@@ -7,7 +7,7 @@ const runtimePath = fileURLToPath(new URL('../src/process-runtime.mjs', import.m
|
|
|
7
7
|
const serverPath = fileURLToPath(new URL('../src/mcp-server.mjs', import.meta.url));
|
|
8
8
|
const toolsPath = fileURLToPath(new URL('../src/process-mcp-tools.mjs', import.meta.url));
|
|
9
9
|
|
|
10
|
-
test('
|
|
10
|
+
test('R46 process supervision is policy-gated and exposes bounded action plus opt-in raw input', async () => {
|
|
11
11
|
const runtimeSource = await readFile(runtimePath, 'utf8');
|
|
12
12
|
const serverSource = await readFile(serverPath, 'utf8');
|
|
13
13
|
const toolsSource = await readFile(toolsPath, 'utf8');
|
|
@@ -20,5 +20,7 @@ test('R32 process supervision is policy-gated and registers the bounded named-ac
|
|
|
20
20
|
assert.match(serverSource, /processRuntime/);
|
|
21
21
|
assert.match(toolsSource, /process_session_action/);
|
|
22
22
|
assert.match(toolsSource, /action_id/);
|
|
23
|
-
assert.
|
|
23
|
+
assert.match(toolsSource, /process_session_write/);
|
|
24
|
+
assert.match(toolsSource, /append_newline/);
|
|
25
|
+
assert.doesNotMatch(toolsSource, /caller-selected executable|raw_stdin/);
|
|
24
26
|
});
|
|
@@ -9,9 +9,9 @@ const readme=()=>readFile(path.join(root,'README.txt'),'utf8');
|
|
|
9
9
|
|
|
10
10
|
test('production README documents one-command stdio configs for major MCP clients',async()=>{
|
|
11
11
|
const text=await readme();
|
|
12
|
-
assert.match(text,/npx -y deadbyte-mcp@0\.15\.
|
|
12
|
+
assert.match(text,/npx -y deadbyte-mcp@0\.15\.2 mcp/);
|
|
13
13
|
assert.match(text,/CLAUDE DESKTOP/);
|
|
14
|
-
assert.match(text,/"mcpServers"[\s\S]*?"command"\s*:\s*"npx"[\s\S]*?"-y"[\s\S]*?"deadbyte-mcp@0\.15\.
|
|
14
|
+
assert.match(text,/"mcpServers"[\s\S]*?"command"\s*:\s*"npx"[\s\S]*?"-y"[\s\S]*?"deadbyte-mcp@0\.15\.2"[\s\S]*?"mcp"/);
|
|
15
15
|
assert.match(text,/CURSOR/);
|
|
16
16
|
assert.match(text,/\.cursor\/mcp\.json/);
|
|
17
17
|
assert.match(text,/VS CODE/);
|
|
@@ -20,7 +20,7 @@ test('production README documents one-command stdio configs for major MCP client
|
|
|
20
20
|
assert.match(text,/CODEX/);
|
|
21
21
|
assert.match(text,/\[mcp_servers\.deadbyte\]/);
|
|
22
22
|
assert.match(text,/command\s*=\s*"npx"/);
|
|
23
|
-
assert.match(text,/args\s*=\s*\["-y",\s*"deadbyte-mcp@0\.15\.
|
|
23
|
+
assert.match(text,/args\s*=\s*\["-y",\s*"deadbyte-mcp@0\.15\.2",\s*"mcp"\]/);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
test('production README records tracer bullet, semantic scope, remote UX, safety and document extension',async()=>{
|
|
@@ -19,9 +19,9 @@ test('R34 public parity catalog is exact, unique, and includes production coding
|
|
|
19
19
|
|
|
20
20
|
test('release parity and final verifier are package entry points', async () => {
|
|
21
21
|
const pkg = JSON.parse(await text('package.json'));
|
|
22
|
-
assert.equal(pkg.scripts['release:parity'], 'node scripts/release-parity-
|
|
23
|
-
assert.equal(pkg.scripts['release:final:write'], 'node scripts/final-closure-
|
|
24
|
-
assert.equal(pkg.scripts['release:final:verify'], 'node scripts/final-closure-verify-
|
|
22
|
+
assert.equal(pkg.scripts['release:parity'], 'node scripts/release-parity-r46.mjs');
|
|
23
|
+
assert.equal(pkg.scripts['release:final:write'], 'node scripts/final-closure-r46.mjs');
|
|
24
|
+
assert.equal(pkg.scripts['release:final:verify'], 'node scripts/final-closure-verify-r46.mjs');
|
|
25
25
|
assert.equal(typeof validateParityEvidence, 'function');
|
|
26
26
|
assert.equal(typeof verifyFinalClosureObject, 'function');
|
|
27
27
|
});
|
|
@@ -16,7 +16,12 @@ function command(executable='C:/Windows/System32/cmd.exe'){
|
|
|
16
16
|
test('R27 generation bundle rebinds authority and mutable state outside the release slot', async () => {
|
|
17
17
|
const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r27-generation-'));
|
|
18
18
|
const state=path.join(base,'state'),release=path.join(base,'release'),workspace=path.join(base,'workspace');
|
|
19
|
-
|
|
19
|
+
const systemRoot=path.join(base,'Windows'),system32=path.join(systemRoot,'System32');
|
|
20
|
+
const powershellDir=path.join(system32,'WindowsPowerShell','v1.0');
|
|
21
|
+
await mkdir(path.join(release,'scripts'),{recursive:true}); await mkdir(path.join(release,'bin'),{recursive:true}); await mkdir(workspace,{recursive:true}); await mkdir(powershellDir,{recursive:true});
|
|
22
|
+
const cmdPath=path.join(system32,'cmd.exe'),cmdBytes=Buffer.from('target-cmd-bytes\\n');
|
|
23
|
+
const powershellPath=path.join(powershellDir,'powershell.exe'),powershellBytes=Buffer.from('target-powershell-bytes\\n');
|
|
24
|
+
await writeFile(cmdPath,cmdBytes); await writeFile(powershellPath,powershellBytes);
|
|
20
25
|
await writeFile(path.join(release,'scripts','gate.ps1'),'Write-Output gate\n');
|
|
21
26
|
await writeFile(path.join(release,'bin','deadbyte-process-host.exe'),'process-host-bytes\n');
|
|
22
27
|
const desktopObserver=Buffer.from('desktop-observer-bytes\n');
|
|
@@ -47,7 +52,10 @@ test('R27 generation bundle rebinds authority and mutable state outside the rele
|
|
|
47
52
|
const processPolicy={schema:'deadbyte.process-policy.v1',enabled:true,grant_file:'C:/old/process-grant.json',state_dir:'C:/old/process-state',
|
|
48
53
|
native_host:{path:'C:/old/deadbyte-process-host.exe',sha256:'0'.repeat(64)},
|
|
49
54
|
roots:{core:{path:'C:/old/core',deny_paths:['node_modules']}},
|
|
50
|
-
profiles:{
|
|
55
|
+
profiles:{
|
|
56
|
+
ping_hold:{executable:'C:/stale/cmd.exe',executable_sha256:EXE,root_ids:['core'],prefix_args:['/d','/q'],transport:'pipe',max_args:0,max_arg_bytes:256,max_sessions:1,max_input_bytes:4096,max_retained_output_bytes:65536,env_allow:['PATH','TEMP','TMP'],input_actions:{ping:'echo DEADBYTE_ACTION_PING\\r\\n'}},
|
|
57
|
+
powershell:{executable:'C:/stale/powershell.exe',executable_sha256:EXE,root_ids:['core'],prefix_args:['-NoLogo','-NoProfile','-NonInteractive','-Command'],transport:'pipe',max_args:1,max_arg_bytes:8192,max_sessions:4,max_input_bytes:65536,max_retained_output_bytes:1048576,env_allow:['PATH','TEMP','TMP','SystemRoot','WINDIR','USERPROFILE','PSModulePath','COMSPEC','PATHEXT'],input_actions:{}}
|
|
58
|
+
}};
|
|
51
59
|
const desktopPolicy={schema:'deadbyte.desktop-policy.v1',enabled:true,grant_file:'C:/old/desktop-grant.json',evidence_dir:'C:/old/desktop-evidence',
|
|
52
60
|
allowed_input_desktops:['Default'],allowed_actions:['click_primary','key_chord'],
|
|
53
61
|
limits:{max_frame_age_ms:2000,max_frame_bytes:8388608,capture_timeout_ms:5000,input_timeout_ms:2000,ground_timeout_ms:5000,post_observe_timeout_ms:5000,max_preview_bytes:1048576,max_text_bytes:4096},
|
|
@@ -59,7 +67,8 @@ test('R27 generation bundle rebinds authority and mutable state outside the rele
|
|
|
59
67
|
await writeFile(path.join(development,'scripts','gate-windows-old.ps1'),'Write-Output old-gate\n');
|
|
60
68
|
await writeFile(path.join(development,'scripts','gate-windows-current.ps1'),'Write-Output current-gate\n');
|
|
61
69
|
await writeFile(path.join(development,'package.json'),JSON.stringify({scripts:{'gate:windows':'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-current.ps1'}}));
|
|
62
|
-
const
|
|
70
|
+
const build=args=>createGenerationBundle({...args,systemRoot});
|
|
71
|
+
const result=await build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy});
|
|
63
72
|
const verified=await verifyGenerationBundle(result.generation_root,result.generation_manifest_sha256);
|
|
64
73
|
assert.equal(verified.files,7);
|
|
65
74
|
const generatedProcess=JSON.parse(await readFile(result.process_policy_path,'utf8'));
|
|
@@ -68,6 +77,11 @@ test('R27 generation bundle rebinds authority and mutable state outside the rele
|
|
|
68
77
|
assert.equal(generatedProcess.roots.core.path,path.resolve(development));
|
|
69
78
|
assert.equal(generatedProcess.native_host.path,path.join(path.resolve(release),'bin','deadbyte-process-host.exe'));
|
|
70
79
|
assert.equal(generatedProcess.native_host.sha256,sha(Buffer.from('process-host-bytes\n')));
|
|
80
|
+
assert.equal(generatedProcess.profiles.ping_hold.executable,cmdPath);
|
|
81
|
+
assert.equal(generatedProcess.profiles.ping_hold.executable_sha256,sha(cmdBytes));
|
|
82
|
+
assert.equal(generatedProcess.profiles.powershell.executable,powershellPath);
|
|
83
|
+
assert.equal(generatedProcess.profiles.powershell.executable_sha256,sha(powershellBytes));
|
|
84
|
+
assert.deepEqual(generatedProcess.profiles.powershell.prefix_args,['-NoLogo','-NoProfile','-NonInteractive','-Command']);
|
|
71
85
|
const generatedDesktop=JSON.parse(await readFile(result.desktop_policy_path,'utf8'));
|
|
72
86
|
assert.equal(generatedDesktop.grant_file,path.join(path.resolve(state),'runtime','desktop-grant.json'));
|
|
73
87
|
assert.equal(generatedDesktop.evidence_dir,path.join(path.resolve(state),'runtime','desktop-evidence'));
|
|
@@ -129,44 +143,44 @@ test('R27 generation bundle rebinds authority and mutable state outside the rele
|
|
|
129
143
|
assert.match(path.basename(result.generation_root),/^v0\.8\.3-aaaaaaaaaaaaaaaa-g[0-9a-f]{16}$/);
|
|
130
144
|
const changedConfig=structuredClone(currentConfig);
|
|
131
145
|
changedConfig.Bridge.Arguments='bridge-v2.mjs';
|
|
132
|
-
const second=await
|
|
146
|
+
const second=await build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig:changedConfig,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy});
|
|
133
147
|
assert.notEqual(second.generation_root,result.generation_root);
|
|
134
148
|
assert.notEqual(second.generation_seed_sha256,result.generation_seed_sha256);
|
|
135
149
|
const endpointChanged=structuredClone(currentConfig);
|
|
136
150
|
endpointChanged.McpUrlFileSha256='2'.repeat(64);
|
|
137
|
-
const third=await
|
|
151
|
+
const third=await build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig:endpointChanged,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy});
|
|
138
152
|
assert.notEqual(third.generation_root,result.generation_root);
|
|
139
153
|
assert.notEqual(third.generation_seed_sha256,result.generation_seed_sha256);
|
|
140
154
|
const machineDisabled=structuredClone(currentConfig);
|
|
141
155
|
machineDisabled.MachineRuntimeEnabled=false;
|
|
142
|
-
const fourth=await
|
|
156
|
+
const fourth=await build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig:machineDisabled,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy});
|
|
143
157
|
assert.notEqual(fourth.generation_root,result.generation_root);
|
|
144
158
|
assert.notEqual(fourth.generation_seed_sha256,result.generation_seed_sha256);
|
|
145
159
|
const machineFsDisabled=structuredClone(currentConfig);
|
|
146
160
|
machineFsDisabled.MachineFsRuntimeEnabled=false;
|
|
147
|
-
const fifth=await
|
|
161
|
+
const fifth=await build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig:machineFsDisabled,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy});
|
|
148
162
|
assert.notEqual(fifth.generation_root,result.generation_root);
|
|
149
163
|
assert.notEqual(fifth.generation_seed_sha256,result.generation_seed_sha256);
|
|
150
164
|
const observationDisabled=structuredClone(currentConfig);
|
|
151
165
|
observationDisabled.ObservationRuntimeEnabled=false;
|
|
152
|
-
const sixth=await
|
|
166
|
+
const sixth=await build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig:observationDisabled,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy});
|
|
153
167
|
assert.notEqual(sixth.generation_root,result.generation_root);
|
|
154
168
|
assert.notEqual(sixth.generation_seed_sha256,result.generation_seed_sha256);
|
|
155
169
|
const desktopDisabled=structuredClone(currentConfig);
|
|
156
170
|
desktopDisabled.DesktopRuntimeEnabled=false;
|
|
157
|
-
const desktopVariant=await
|
|
171
|
+
const desktopVariant=await build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig:desktopDisabled,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy});
|
|
158
172
|
assert.notEqual(desktopVariant.generation_root,result.generation_root);
|
|
159
173
|
assert.notEqual(desktopVariant.generation_seed_sha256,result.generation_seed_sha256);
|
|
160
174
|
const desktopTampered=structuredClone(desktopPolicy);
|
|
161
175
|
desktopTampered.input.sha256='f'.repeat(64);
|
|
162
|
-
await assert.rejects(
|
|
176
|
+
await assert.rejects(build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy:desktopTampered}),/desktop input helper SHA-256 mismatch/);
|
|
163
177
|
const semanticConfig2Path=path.join(base,'semantic-lsp-v2.json');
|
|
164
178
|
const semanticConfig2Bytes=Buffer.from(JSON.stringify({schema:'deadbyte.semantic-lsp-config.v1',servers:[{id:'changed'}]})+'\n','utf8');
|
|
165
179
|
await writeFile(semanticConfig2Path,semanticConfig2Bytes);
|
|
166
180
|
const semanticChanged=structuredClone(currentConfig);
|
|
167
181
|
semanticChanged.SemanticLspConfigFile=semanticConfig2Path;
|
|
168
182
|
semanticChanged.SemanticLspConfigSha256=sha(semanticConfig2Bytes);
|
|
169
|
-
const seventh=await
|
|
183
|
+
const seventh=await build({stateRoot:state,releaseRoot:release,developmentRoot:development,workspaceRoot:workspace,releaseId:'v0.8.3-aaaaaaaaaaaaaaaa',currentConfig:semanticChanged,codingPolicy:coding,autonomousPolicy:autonomous,hostPolicy:host,processPolicy,desktopPolicy});
|
|
170
184
|
assert.notEqual(seventh.generation_root,result.generation_root);
|
|
171
185
|
assert.notEqual(seventh.generation_seed_sha256,result.generation_seed_sha256);
|
|
172
186
|
await verifyGenerationBundle(result.generation_root,result.generation_manifest_sha256);
|
|
@@ -5,54 +5,113 @@ import { createHash } from 'node:crypto';
|
|
|
5
5
|
|
|
6
6
|
const root=new URL('../',import.meta.url);
|
|
7
7
|
const text=rel=>readFile(new URL(rel,root),'utf8');
|
|
8
|
-
const PARENT_RELEASE='v0.15.
|
|
9
|
-
const PARENT_MANIFEST='
|
|
10
|
-
const PARENT_GENERATION='
|
|
11
|
-
const PARENT_CLOSURE='533b7e0ff9ded04086dd90ed34e3b87bc427acc3c55c25bb9f4ec66cb448e667';
|
|
8
|
+
const PARENT_RELEASE='v0.15.1-d55f00b5144dc31a';
|
|
9
|
+
const PARENT_MANIFEST='d55f00b5144dc31a7fe39e4dc60d640a94780da6aaeca0918e87636b816d7854';
|
|
10
|
+
const PARENT_GENERATION='00cde7bf540cc2804d679a39040d5b07193c5f8a0d49cac3b882402f8f4e6ad8';
|
|
12
11
|
|
|
13
|
-
test('
|
|
12
|
+
test('R46 current authority agrees on V0.15.2 and preserves exact R45 parent identity',async()=>{
|
|
14
13
|
const pkg=JSON.parse(await text('package.json'));
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
text('
|
|
18
|
-
text('
|
|
19
|
-
text('scripts/
|
|
20
|
-
text('
|
|
14
|
+
const release=JSON.parse(await text('RELEASE.json'));
|
|
15
|
+
const [version,controller,gate,readme,architecture,controllerReadme,deferred,parity,closure,closureVerify,windowsGate,processPolicy]=await Promise.all([
|
|
16
|
+
text('src/version.mjs'),
|
|
17
|
+
text('controller/deadbyte-controller.ps1'),
|
|
18
|
+
text('scripts/gate-windows-r46.ps1'),
|
|
19
|
+
text('README.txt'),
|
|
20
|
+
text('docs/ARCHITECTURE.md'),
|
|
21
|
+
text('controller/README.TXT'),
|
|
22
|
+
text('scripts/deferred-slot-operation-r46.mjs'),
|
|
23
|
+
text('scripts/release-parity-r46.mjs'),
|
|
24
|
+
text('scripts/final-closure-r46.mjs'),
|
|
25
|
+
text('scripts/final-closure-verify-r46.mjs'),
|
|
26
|
+
text('scripts/windows-gate-evidence-r46.mjs'),
|
|
27
|
+
text('controller/deadbyte-process-policy.json')
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
assert.equal(pkg.version,'0.15.2');
|
|
31
|
+
assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r46.ps1');
|
|
32
|
+
assert.equal(pkg.scripts['self-update:deferred'],'node scripts/deferred-slot-operation-r46.mjs');
|
|
33
|
+
assert.equal(pkg.scripts['release:parity'],'node scripts/release-parity-r46.mjs');
|
|
34
|
+
assert.equal(pkg.scripts['release:final:write'],'node scripts/final-closure-r46.mjs');
|
|
35
|
+
assert.equal(pkg.scripts['release:final:verify'],'node scripts/final-closure-verify-r46.mjs');
|
|
36
|
+
assert.equal(pkg.scripts['r46:fileless:test'],"node --test --test-concurrency=1 test/process-policy.test.mjs test/process-policy-refresh.test.mjs test/release-generation.test.mjs test/process-runtime.test.mjs test/process-mcp-tools.test.mjs test/compact-gateway-r36.test.mjs test/capability-ledger-r36.test.mjs test/remote-device-r44.test.mjs test/observation-runtime.test.mjs test/observation-mcp-tools.test.mjs");
|
|
37
|
+
assert.equal(pkg.scripts['r46:full:test'],'node scripts/full-regression-r46.mjs');
|
|
38
|
+
|
|
39
|
+
assert.match(version,/DEADBYTE_VERSION = '0\.15\.2'/);
|
|
40
|
+
assert.match(controller,/CONTROLLER V0\.15\.2 \/ R46/);
|
|
41
|
+
assert.match(gate,/DEADBYTE V0\.15\.2 \/ R46 FILELESS POWERSHELL WINDOWS BATCH GATE: PASS/);
|
|
42
|
+
assert.match(readme,/^DEADBYTE MCP V0\.15\.2 \/ R46 FILELESS POWERSHELL PRODUCT BASELINE$/m);
|
|
43
|
+
assert.match(readme,/powershell\.exe -Command <source>/);
|
|
44
|
+
assert.match(architecture,/^# DEADBYTE MCP V0\.15\.2 \/ R46 ARCHITECTURE$/m);
|
|
45
|
+
assert.match(controllerReadme,/^DEADBYTE MCP V0\.15\.2 \/ R46 CONTROLLER$/m);
|
|
46
|
+
assert.match(deferred,/--expected-version','0\.15\.2'/);
|
|
47
|
+
assert.match(parity,/deadbyte\.r46-parity\.v1/);
|
|
48
|
+
assert.match(parity,/DB_R46_FILELESS_PARITY/);
|
|
49
|
+
assert.match(parity,/target_repin_verified:true/);
|
|
50
|
+
assert.match(parity,/DB_R46_REPL_VALUE=42/);
|
|
51
|
+
assert.match(parity,/raw_input_not_journaled:true/);
|
|
52
|
+
assert.match(parity,/eviction_verified:true/);
|
|
53
|
+
assert.match(windowsGate,/full_tool_count:83/);
|
|
54
|
+
assert.match(windowsGate,/remote_reachability_ttl:true/);
|
|
55
|
+
assert.match(windowsGate,/observation_search_terminal_ttl:true/);
|
|
56
|
+
assert.match(windowsGate,/observation_search_hard_cap:128/);
|
|
57
|
+
assert.match(closure,/deadbyte\.r46-final-closure\.v1/);
|
|
58
|
+
assert.match(closure,/DEADBYTE-R46-FINAL-CLOSURE-V1/);
|
|
59
|
+
assert.match(closureVerify,/DEADBYTE-R46-FINAL-CLOSURE-V1/);
|
|
60
|
+
assert.match(windowsGate,/deadbyte\.r46-windows-gate\.v1/);
|
|
61
|
+
|
|
62
|
+
assert.equal(release.version,'0.15.2');
|
|
63
|
+
assert.equal(release.train,'R46');
|
|
64
|
+
assert.equal(release.label,'FILELESS POWERSHELL PRODUCT BASELINE');
|
|
65
|
+
assert.equal(release.parent.release_id,PARENT_RELEASE);
|
|
66
|
+
assert.equal(release.parent.manifest_sha256,PARENT_MANIFEST);
|
|
67
|
+
assert.equal(release.parent.generation_manifest_sha256,PARENT_GENERATION);
|
|
68
|
+
assert.deepEqual(release.capabilities.process_profiles,['ping_hold','powershell','powershell_repl']);
|
|
69
|
+
assert.equal(release.capabilities.full_tool_count,83);
|
|
70
|
+
assert.equal(release.capabilities.compact_tool_count,43);
|
|
71
|
+
assert.equal(release.capabilities.powershell_persistent_repl,true);
|
|
72
|
+
assert.equal(release.capabilities.process_raw_input_profile_opt_in,true);
|
|
73
|
+
assert.equal(release.capabilities.powershell_fileless,true);
|
|
74
|
+
assert.equal(release.capabilities.powershell_source_max_arg_bytes,8192);
|
|
75
|
+
|
|
76
|
+
const policy=JSON.parse(processPolicy);
|
|
77
|
+
assert.ok(policy.profiles.ping_hold);
|
|
78
|
+
assert.ok(policy.profiles.powershell);
|
|
79
|
+
assert.ok(policy.profiles.powershell_repl);
|
|
80
|
+
assert.equal(policy.profiles.powershell_repl.allow_raw_input,true);
|
|
81
|
+
assert.deepEqual(policy.profiles.powershell_repl.prefix_args,['-NoLogo','-NoProfile','-NonInteractive']);
|
|
82
|
+
assert.deepEqual(policy.profiles.powershell.prefix_args,['-NoLogo','-NoProfile','-NonInteractive','-Command']);
|
|
83
|
+
assert.equal(policy.profiles.powershell.max_args,1);
|
|
84
|
+
assert.equal(policy.profiles.powershell.max_arg_bytes,8192);
|
|
85
|
+
assert.equal(policy.profiles.powershell.transport,'pipe');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('R46 leaves sealed R45 release artifacts historical and unchanged in identity',async()=>{
|
|
89
|
+
const [gate,deferred,parity,closure,closureVerify,finalizer,parent]=await Promise.all([
|
|
90
|
+
text('scripts/gate-windows-r45.ps1'),
|
|
91
|
+
text('scripts/deferred-slot-operation-r45.mjs'),
|
|
92
|
+
text('scripts/release-parity-r45.mjs'),
|
|
93
|
+
text('scripts/final-closure-r45.mjs'),
|
|
94
|
+
text('scripts/final-closure-verify-r45.mjs'),
|
|
95
|
+
text('scripts/finalize-r45.mjs'),
|
|
96
|
+
text('R45-PARENT.json')
|
|
21
97
|
]);
|
|
22
|
-
assert.equal(pkg.version,'0.15.1');
|
|
23
|
-
assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r45.ps1');
|
|
24
|
-
assert.equal(pkg.scripts['r45:parent:verify'],'node scripts/verify-r45-parent.mjs');
|
|
25
|
-
assert.equal(pkg.scripts['r45:full:test'],'node scripts/full-regression-r45.mjs');
|
|
26
|
-
assert.equal(pkg.scripts['self-update:deferred'],'node scripts/deferred-slot-operation-r45.mjs');
|
|
27
|
-
assert.equal(pkg.scripts['release:parity'],'node scripts/release-parity-r45.mjs');
|
|
28
|
-
assert.equal(pkg.scripts['release:final:write'],'node scripts/final-closure-r45.mjs');
|
|
29
|
-
assert.equal(pkg.scripts['release:final:verify'],'node scripts/final-closure-verify-r45.mjs');
|
|
30
|
-
assert.equal(pkg.scripts['finalize:r45'],'node scripts/finalize-r45.mjs');
|
|
31
|
-
assert.match(version,/DEADBYTE_VERSION = '0\.15\.1'/);
|
|
32
|
-
assert.match(controller,/CONTROLLER V0\.15\.1 \/ R45/);
|
|
33
98
|
assert.match(gate,/DEADBYTE V0\.15\.1 \/ R45 MACHINE FREEDOM WINDOWS BATCH GATE: PASS/);
|
|
34
|
-
assert.match(readme,/^DEADBYTE MCP V0\.15\.1 \/ R45 MACHINE FREEDOM FINAL BASELINE$/m);
|
|
35
|
-
assert.match(architecture,/^# DEADBYTE MCP V0\.15\.1 \/ R45 ARCHITECTURE$/m);
|
|
36
|
-
assert.match(controllerReadme,/^DEADBYTE MCP V0\.15\.1 \/ R45 CONTROLLER$/m);
|
|
37
99
|
assert.match(deferred,/--expected-version','0\.15\.1'/);
|
|
38
|
-
assert.match(parity,/
|
|
39
|
-
assert.match(
|
|
40
|
-
assert.match(
|
|
41
|
-
assert.match(
|
|
42
|
-
assert.match(
|
|
43
|
-
assert.match(windowsGate,/deadbyte\.r45-windows-gate\.v1/);
|
|
100
|
+
assert.match(parity,/deadbyte\.r45-parity\.v1/);
|
|
101
|
+
assert.match(closure,/version:'0\.15\.1'/);
|
|
102
|
+
assert.match(closure,/DEADBYTE-R45-FINAL-CLOSURE-V1/);
|
|
103
|
+
assert.match(closureVerify,/R45_FULL_TOOL_COUNT=82/);
|
|
104
|
+
assert.match(finalizer,/EXPECTED_VERSION='0\.15\.1'/);
|
|
44
105
|
const parentRecord=JSON.parse(parent);
|
|
45
|
-
assert.equal(parentRecord.parent_release_id,
|
|
46
|
-
assert.equal(parentRecord.parent_manifest_sha256,PARENT_MANIFEST);
|
|
47
|
-
assert.equal(parentRecord.parent_generation_manifest_sha256,PARENT_GENERATION);
|
|
48
|
-
assert.equal(parentRecord.parent_final_closure_sha256,PARENT_CLOSURE);
|
|
49
|
-
assert.match(r44Gate,/DEADBYTE V0\.15\.0 \/ R44 REMOTE AGENT SKILL WINDOWS BATCH GATE: PASS/);
|
|
50
|
-
assert.match(r44Parity,/deadbyte\.r44-parity\.v1/);
|
|
51
|
-
assert.match(r44Closure,/version:'0\.15\.0'/);
|
|
106
|
+
assert.equal(parentRecord.parent_release_id,'v0.15.0-c15fa41719be61b3');
|
|
52
107
|
});
|
|
53
108
|
|
|
54
|
-
test('
|
|
55
|
-
const [cli,controller]=await Promise.all([
|
|
109
|
+
test('R46 keeps ONLINE reuse, explicit Desktop authority, and semantic config pin',async()=>{
|
|
110
|
+
const [cli,controller,semantic]=await Promise.all([
|
|
111
|
+
text('src/deadbyte-cli.mjs'),
|
|
112
|
+
text('controller/deadbyte-controller.ps1'),
|
|
113
|
+
text('controller/deadbyte-semantic-lsp-config.json')
|
|
114
|
+
]);
|
|
56
115
|
assert.match(cli,/controllerRuntimeReady/);
|
|
57
116
|
assert.match(cli,/Runtime already ONLINE; reusing verified bridge\/cloud\/supervisor/);
|
|
58
117
|
const start=controller.indexOf('function Recover-AutonomousSupervisor'),end=controller.indexOf('function Show-State',start);
|
|
@@ -62,9 +121,5 @@ test('R45 keeps ONLINE reuse and explicit Desktop authority',async()=>{
|
|
|
62
121
|
assert.match(block,/\$hostStatus\s*=\s*Get-HostArmStatus/);
|
|
63
122
|
assert.match(controller,/armdesktop/);
|
|
64
123
|
assert.match(controller,/disarmdesktop/);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('semantic config remains byte-pinned across R45 machine-freedom work',async()=>{
|
|
68
|
-
const semantic=await text('controller/deadbyte-semantic-lsp-config.json');
|
|
69
124
|
assert.equal(createHash('sha256').update(Buffer.from(semantic,'utf8')).digest('hex'),'d274b099a298c1033fea8f1e8849751693bbc0448778d619400acb82d4f53a3b');
|
|
70
125
|
});
|