deadbyte-mcp 0.15.44 → 0.15.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MANIFEST.SHA256 +86 -138
- package/PROVENANCE.json +35 -18
- package/README.txt +22 -21
- package/RELEASE.json +369 -334
- package/SBOM.cdx.json +2 -2
- package/TEST-MATRIX.json +27 -17
- package/bridge/package.json +1 -1
- package/controller/deadbyte-controller.ps1 +1871 -1769
- package/controller/deadbyte-desktop-policy.json +6 -6
- package/controller/deadbyte-process-policy.json +4 -4
- package/docs/R68-COMPAT-HOST-EXEC-CANDIDATE.md +63 -0
- package/docs/R69-LIVE-OUTCOME-R70-POLICY-TRANSFER.md +136 -0
- package/docs/R70-CODING-DIGEST-SUPERVISOR-CHECKPOINT-20261013.md +42 -0
- package/docs/R70-FINITE-GRANT-OWNER-BOUNDARY-20261013.md +80 -0
- package/docs/R70-OWNER-BOOTSTRAP-CHECKPOINT-20261013.md +60 -0
- package/docs/R70-REFERENCE-MECHANISMS.json +95 -0
- package/docs/R70-TRUST-GUARD-EXPIRY-CHECKPOINT-20261013.md +47 -0
- package/package.json +2 -2
- package/scripts/benchmark-l0-r71.mjs +76 -0
- package/scripts/gate-windows-r71.ps1 +64 -0
- package/scripts/gate-windows-r72.ps1 +76 -0
- package/scripts/npm-release-r48.mjs +4 -0
- package/scripts/npm-release-readiness-r71.mjs +21 -0
- package/scripts/npm-release-readiness-r72.mjs +76 -0
- package/scripts/verify-r70-full-regression.ps1 +72 -0
- package/src/authority-continuity-r65.mjs +28 -8
- package/src/autonomous-mcp-tools.mjs +1 -1
- package/src/autonomous-output-contracts.mjs +4 -1
- package/src/autonomous-policy.mjs +54 -7
- package/src/capability-ledger.mjs +1 -1
- package/src/capability-resolver.mjs +2 -1
- package/src/commander-compat-runtime.mjs +30 -2
- package/src/deadbyte-cli.mjs +722 -719
- package/src/launcher-isolation.mjs +58 -0
- package/src/native-diff-v2.mjs +18 -5
- package/src/native-diff.mjs +21 -5
- package/src/r70-owner-approval.mjs +78 -0
- package/src/remote-authority.mjs +75 -75
- package/src/remote-live-log.mjs +48 -14
- package/src/remote-mcp-machine-smoke-client.mjs +84 -84
- package/src/remote-result-journal.mjs +1 -1
- package/src/runtime-update.mjs +232 -24
- package/src/staging-input-isolation.mjs +79 -0
- package/src/tool-audit.mjs +2 -0
- package/src/version.mjs +1 -1
- package/test/autonomous-local-supervisor.test.mjs +2 -1
- package/test/autonomous-output-contract.test.mjs +17 -1
- package/test/autonomous-supervisor-integration.test.mjs +2 -1
- package/test/capability-resolver.test.mjs +17 -0
- package/test/codex-autonomous-r44.test.mjs +1 -1
- package/test/commander-compat-runtime.test.mjs +42 -0
- package/test/controller-policy-preflight-r59.test.mjs +1 -0
- package/test/deferred-slot-operation-behavior.test.mjs +2 -2
- package/test/native-diff-topology-r36.test.mjs +35 -2
- package/test/native-diff.test.mjs +83 -3
- package/test/r58-cleanup-retention.test.mjs +3 -3
- package/test/r58-concurrent-recovery.test.mjs +3 -3
- package/test/r58-stale-owner.test.mjs +1 -1
- package/test/r59-tool-surface-compat.test.mjs +9 -5
- package/test/r60-authority-coherence.test.mjs +10 -2
- package/test/r65-authority-runtime-epoch.test.mjs +9 -1
- package/test/r67-isolated-slot-rollback-restore.test.mjs +2 -1
- package/test/r67-npm-publish-gate.test.mjs +4 -2
- package/test/r67-release-contract.test.mjs +8 -7
- package/test/r69-live-outcome.test.mjs +137 -0
- package/test/r70-autonomous-grant-expiry.test.mjs +89 -0
- package/test/r70-autonomous-policy-bootstrap.test.mjs +166 -0
- package/test/r70-controller-autonomous-root.test.mjs +104 -0
- package/test/r70-controller-grant-subset.test.mjs +28 -0
- package/test/r70-controller-owner-issue-boundary.test.mjs +80 -0
- package/test/r70-controller-policy-snapshot.test.mjs +66 -0
- package/test/r70-owner-approval.test.mjs +67 -0
- package/test/r71-full-verifier-artifact.test.mjs +28 -0
- package/test/r71-isolated-slot-rollback-restore.test.mjs +62 -0
- package/test/r71-native-diff-mcp-wire.test.mjs +75 -0
- package/test/r71-publish-fence.test.mjs +38 -0
- package/test/r71-release-identity.test.mjs +33 -0
- package/test/r72-launcher-isolation.test.mjs +99 -0
- package/test/r72-publication-fence.test.mjs +56 -0
- package/test/r72-publication-output-integrity.test.mjs +110 -0
- package/test/r72-remote-safe-contract.test.mjs +101 -0
- package/test/r72-staging-input-isolation.test.mjs +87 -0
- package/test/r72-staging-workspace-isolation.test.mjs +114 -0
- package/test/remote-result-journal.test.mjs +12 -0
- package/test/remote-session-cli.test.mjs +112 -65
- package/test/standing-grants.test.mjs +2 -2
- package/test/tool-audit.test.mjs +14 -0
- package/bin/appcontainer-stage.obj +0 -0
- package/bin/bootstrap-advapi32.obj +0 -0
- package/bin/bootstrap-exitcode.obj +0 -0
- package/bin/bootstrap-kernel32.obj +0 -0
- package/bin/child-control-probe.obj +0 -0
- package/bin/child-control-stage.obj +0 -0
- package/bin/contained-reverse-worker.obj +0 -0
- package/bin/contained-transform-worker.obj +0 -0
- package/bin/containment-probe.obj +0 -0
- package/bin/deadbyte-contain.obj +0 -0
- package/bin/deadbyte-desktop-input-r40.obj +0 -0
- package/bin/deadbyte-desktop-observer-r40.obj +0 -0
- package/bin/deadbyte-desktop-uia-r40.obj +0 -0
- package/bin/deadbyte-exec.obj +0 -0
- package/bin/deadbyte-hardware-observer-r45.obj +0 -0
- package/bin/deadbyte-native-inspect-r67.obj +0 -0
- package/bin/deadbyte-process-host.obj +0 -0
- package/bin/deadbyte-tunnel-host.obj +0 -0
- package/conpty-input-observer.obj +0 -0
- package/miniconpty.obj +0 -0
- package/proof/CONTAINMENT-BUILD.txt +0 -163
- package/proof/MCP-SMOKE-STATUS.txt +0 -9
- package/proof/NODE-SYNTAX.txt +0 -4
- package/proof/PROOF.txt +0 -6
- package/proof/R34-TASK8-SUPERVISOR-CHECKPOINT.json +0 -29
- package/proof/R34-TASK9-MCP-SURFACE-CHECKPOINT.json +0 -28
- package/proof/SECRET-SCAN.txt +0 -4
- package/proof/SOURCE-GATES.txt +0 -16
- package/proof/STATUS.txt +0 -11
- package/proof/TARGET-V0313-CONTAINMENT-PASS.sha256 +0 -1
- package/proof/TARGET-V0313-CONTAINMENT-PASS.txt +0 -215
- package/proof/TARGET-V040-CONTAINED-IPC-FAIL.sha256 +0 -1
- package/proof/TARGET-V040-CONTAINED-IPC-FAIL.txt +0 -299
- package/proof/TARGET-V041-CONTAINED-CREATEPROCESS-203.sha256 +0 -1
- package/proof/TARGET-V041-CONTAINED-CREATEPROCESS-203.txt +0 -311
- package/proof/TARGET-V042-CONTAINED-CREATEPROCESS-203.sha256 +0 -1
- package/proof/TARGET-V042-CONTAINED-CREATEPROCESS-203.txt +0 -313
- package/proof/TARGET-V043-CONTAINED-CREATEPROCESS-203.sha256 +0 -1
- package/proof/TARGET-V043-CONTAINED-CREATEPROCESS-203.txt +0 -308
- package/proof/TARGET-V044-CONTAINED-PASS.sha256 +0 -1
- package/proof/TARGET-V044-CONTAINED-PASS.txt +0 -432
- package/proof/TARGET-V045-DUAL-OPERATION-PASS.sha256 +0 -1
- package/proof/TARGET-V045-DUAL-OPERATION-PASS.txt +0 -481
- package/proof/TARGET-V046-FIXED-EXECUTABLE-REGISTRY-PASS.sha256 +0 -1
- package/proof/TARGET-V046-FIXED-EXECUTABLE-REGISTRY-PASS.txt +0 -610
- package/proof/TARGET-V047-RUNTIME-MANIFEST-PASS.sha256 +0 -1
- package/proof/TARGET-V047-RUNTIME-MANIFEST-PASS.txt +0 -642
- package/proof/TARGET-V050-BATCH-GATE-PASS.sha256 +0 -1
- package/proof/TARGET-V050-BATCH-GATE-PASS.txt +0 -713
- package/proof/TESTS.txt +0 -686
- package/proof/TRUST-EPHEMERAL.txt +0 -4
- package/proof/V03-FREEZE.txt +0 -27
- package/proof/V041-IPC-HOTFIX.txt +0 -16
- package/proof/V042-ENV-HOTFIX.txt +0 -15
- package/proof/V043-DRIVE-CWD-HOTFIX.txt +0 -14
- package/proof/V044-LOCALAPPDATA-HOTFIX.txt +0 -18
- package/proof/V045-OPERATION-REGISTRY.txt +0 -7
- package/proof/V046-WORKER-REGISTRY.txt +0 -12
- package/proof/V047-WORKER-MANIFEST.txt +0 -18
- package/proof/V050-BATCH-TRUST-CLOSURE.txt +0 -21
- package/proof/V060-ACTIVE-NETWORK-AUTHORITY.txt +0 -29
- package/proof/V070-NODE-SYNTAX.txt +0 -36
- package/proof/V070-NODE-TESTS.txt +0 -752
- package/proof/V070-PACK-DRY-RUN.txt +0 -126
- package/proof/V070-SOURCE-GATE.txt +0 -30
- package/proof/V070-STATIC-SCAN.txt +0 -4
- package/proof/V070-WINDOWS-GATE-PENDING.txt +0 -25
- package/proof/V071-NODE-SYNTAX.txt +0 -1
- package/proof/V071-NODE-TESTS.txt +0 -796
- package/proof/V071-PACK-DRY-RUN.json +0 -656
- package/proof/V071-SOURCE-GATE.txt +0 -16
- package/proof/V071-WINDOWS-GATE-PENDING.txt +0 -24
- package/proof/V073-NODE-SYNTAX.txt +0 -4
- package/proof/V073-SOURCE-GATE.txt +0 -21
- package/proof/V073-STATIC-SCAN.txt +0 -10
- package/proof/V073-WINDOWS-GATE-PENDING.txt +0 -5
- package/proof/VERIFY.txt +0 -7
- package/proof/WINDOWS-CONTAINED-STATUS.txt +0 -5
- package/proof/WINDOWS-CONTAINMENT-STATUS.txt +0 -3
- package/proof/commander-closure-20260927/CONTINUATION.json +0 -43
- package/proof/commander-closure-20260927/RESULT.json +0 -30
- package/proof/commander-closure-20260927/SEARCH-CONTINUATION.json +0 -30
- package/proof/commander-closure-20260927/XLS-REFERENCE-PROBE.json +0 -13
- package/proof/commander-closure-20260928/DIFFERENTIAL-CHECKPOINT.json +0 -122
- package/proof/r59-full-regression-current.json +0 -13
- package/proof/r59-full-regression-current.stderr.log +0 -0
- package/proof/r59-full-regression-current.stdout.log +0 -1268
|
@@ -80,11 +80,11 @@ function normalizePlanner(raw,codingPolicy,rootIds) {
|
|
|
80
80
|
}
|
|
81
81
|
return provider;
|
|
82
82
|
}
|
|
83
|
-
function normalizeProfile(id, raw, codingPolicy) {
|
|
83
|
+
function normalizeProfile(id, raw, codingPolicy, rootIds) {
|
|
84
84
|
if (!ID_RE.test(id)) throw new Error(`invalid autonomous profile '${id}'`);
|
|
85
85
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error(`autonomous profile '${id}' malformed`);
|
|
86
86
|
if (!['command','benchmark'].includes(raw.kind)) throw new Error(`autonomous profile '${id}' kind invalid`);
|
|
87
|
-
if (!ID_RE.test(raw.root_id ?? '') || !codingPolicy.roots[raw.root_id]) throw new Error(`autonomous profile '${id}' root invalid`);
|
|
87
|
+
if (!ID_RE.test(raw.root_id ?? '') || !codingPolicy.roots[raw.root_id] || !rootIds.includes(raw.root_id)) throw new Error(`autonomous profile '${id}' root invalid`);
|
|
88
88
|
if (!ID_RE.test(raw.command_id ?? '') || !codingPolicy.commands[raw.command_id]) throw new Error(`autonomous profile '${id}' command invalid`);
|
|
89
89
|
validatePortableRelativePath(raw.script_path);
|
|
90
90
|
if (!SHA256_RE.test(raw.script_sha256 ?? '')) throw new Error(`autonomous profile '${id}' script hash invalid`);
|
|
@@ -130,7 +130,7 @@ export async function loadAutonomousPolicy(policyPath, codingPolicy) {
|
|
|
130
130
|
const rootIds = Array.isArray(raw.root_ids) ? [...new Set(raw.root_ids)] : [];
|
|
131
131
|
if (rootIds.length < 1 || rootIds.some(id => !ID_RE.test(id) || !codingPolicy.roots[id])) throw new Error('autonomous root_ids invalid');
|
|
132
132
|
const profiles = {};
|
|
133
|
-
for (const [id, value] of Object.entries(raw.profiles ?? {})) profiles[id] = normalizeProfile(id, value, codingPolicy);
|
|
133
|
+
for (const [id, value] of Object.entries(raw.profiles ?? {})) profiles[id] = normalizeProfile(id, value, codingPolicy, rootIds);
|
|
134
134
|
const limits = raw.limits ?? {};
|
|
135
135
|
const policy = {
|
|
136
136
|
schema: AUTONOMOUS_POLICY_SCHEMA, enabled: true, policy_path: absolute,
|
|
@@ -154,6 +154,43 @@ export async function loadAutonomousPolicy(policyPath, codingPolicy) {
|
|
|
154
154
|
return Object.freeze(policy);
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
export function inspectAutonomousStandingWindow(lease,now=new Date()){
|
|
158
|
+
// v2 legacy standing grants have no expiry. New bounded grants must be
|
|
159
|
+
// checked on every authority observation, including after a runtime restart.
|
|
160
|
+
if(!lease||typeof lease!=='object'||Array.isArray(lease)){
|
|
161
|
+
return {ok:false,reason:'expiry-invalid',expires_at_utc:null,remaining_ms:null};
|
|
162
|
+
}
|
|
163
|
+
if(!Object.hasOwn(lease,'expires_at_utc')){
|
|
164
|
+
return {ok:true,reason:null,expires_at_utc:null,remaining_ms:null};
|
|
165
|
+
}
|
|
166
|
+
const canonical=value=>typeof value==='string'&&
|
|
167
|
+
/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3,7}Z$/.test(value);
|
|
168
|
+
const expiry=lease.expires_at_utc;
|
|
169
|
+
const issued=lease.granted_at_utc;
|
|
170
|
+
if(!canonical(expiry)||!canonical(issued)){
|
|
171
|
+
return {ok:false,reason:'expiry-invalid',expires_at_utc:null,remaining_ms:null};
|
|
172
|
+
}
|
|
173
|
+
const end=Date.parse(expiry),start=Date.parse(issued);
|
|
174
|
+
if(!Number.isFinite(end)||!Number.isFinite(start)){
|
|
175
|
+
return {ok:false,reason:'expiry-invalid',expires_at_utc:null,remaining_ms:null};
|
|
176
|
+
}
|
|
177
|
+
const duration=end-start;
|
|
178
|
+
if(duration<=0||duration>3_600_000){
|
|
179
|
+
return {ok:false,reason:'expiry-window-invalid',expires_at_utc:expiry,remaining_ms:null};
|
|
180
|
+
}
|
|
181
|
+
const observed=now instanceof Date?now.getTime():NaN;
|
|
182
|
+
if(!Number.isFinite(observed)){
|
|
183
|
+
return {ok:false,reason:'clock-invalid',expires_at_utc:expiry,remaining_ms:null};
|
|
184
|
+
}
|
|
185
|
+
if(observed<start){
|
|
186
|
+
return {ok:false,reason:'not-yet-valid',expires_at_utc:expiry,remaining_ms:null};
|
|
187
|
+
}
|
|
188
|
+
if(observed>=end){
|
|
189
|
+
return {ok:false,reason:'expired',expires_at_utc:expiry,remaining_ms:0};
|
|
190
|
+
}
|
|
191
|
+
return {ok:true,reason:null,expires_at_utc:expiry,remaining_ms:end-observed};
|
|
192
|
+
}
|
|
193
|
+
|
|
157
194
|
export async function autonomousSessionStatus(policy, now = new Date()) {
|
|
158
195
|
let lease,leaseBytes;
|
|
159
196
|
try { leaseBytes=await readFile(policy.lease_file); lease = JSON.parse(decodeUtf8Strict(leaseBytes)); }
|
|
@@ -164,15 +201,25 @@ export async function autonomousSessionStatus(policy, now = new Date()) {
|
|
|
164
201
|
return { configured:true, armed:false, reason:'lease-schema', expires_at_utc:null };
|
|
165
202
|
}
|
|
166
203
|
if (lease.policy_sha256 !== policy.policy_sha256) return { configured:true, armed:false, reason:'policy-digest', expires_at_utc:null };
|
|
204
|
+
// Controller and runtime must agree on the exact Coding authority policy
|
|
205
|
+
// for every signed v2 Autonomous grant, including after generation changes.
|
|
206
|
+
if (lease.schema === AUTONOMOUS_GRANT_SCHEMA &&
|
|
207
|
+
lease.coding_policy_sha256 !== policy.coding_policy_sha256) {
|
|
208
|
+
return { configured:true, armed:false, reason:'coding-policy-digest', expires_at_utc:null };
|
|
209
|
+
}
|
|
167
210
|
if (typeof lease.instance_nonce !== 'string' || !SHA256_RE.test(lease.instance_nonce)) return { configured:true, armed:false, reason:'nonce-invalid', expires_at_utc:null };
|
|
168
211
|
const roots = Array.isArray(lease.root_ids) ? [...new Set(lease.root_ids)] : [];
|
|
169
212
|
if (roots.length < 1 || roots.some(id => !policy.root_ids.includes(id))) return { configured:true, armed:false, reason:'roots-invalid', expires_at_utc:null };
|
|
170
213
|
if (lease.schema === AUTONOMOUS_GRANT_SCHEMA) {
|
|
214
|
+
const window=inspectAutonomousStandingWindow(lease,now);
|
|
215
|
+
if(!window.ok) return {configured:true,armed:false,reason:window.reason,
|
|
216
|
+
expires_at_utc:window.expires_at_utc,remaining_ms:window.remaining_ms,
|
|
217
|
+
standing:false,instance_nonce:lease.instance_nonce,root_ids:roots};
|
|
171
218
|
const epoch=await verifyStandingGrantEpoch({plane:'autonomous',grantFile:policy.lease_file,grantBytes:leaseBytes,grantInstanceNonce:lease.instance_nonce,policyPath:policy.policy_path});
|
|
172
|
-
if(!epoch.trusted)return { configured:true,armed:false,reason:epoch.reason,expires_at_utc:
|
|
173
|
-
remaining_ms:
|
|
174
|
-
return { configured:true, armed:true, reason:'standing-grant', expires_at_utc:
|
|
175
|
-
remaining_ms:
|
|
219
|
+
if(!epoch.trusted)return { configured:true,armed:false,reason:epoch.reason,expires_at_utc:window.expires_at_utc,
|
|
220
|
+
remaining_ms:window.remaining_ms,standing:false,instance_nonce:lease.instance_nonce,root_ids:roots };
|
|
221
|
+
return { configured:true, armed:true, reason:'standing-grant', expires_at_utc:window.expires_at_utc,
|
|
222
|
+
remaining_ms:window.remaining_ms, standing:true, instance_nonce:lease.instance_nonce, root_ids:roots, authority_epoch:epoch };
|
|
176
223
|
}
|
|
177
224
|
const expires = Date.parse(lease.expires_at_utc);
|
|
178
225
|
if (!Number.isFinite(expires)) return { configured:true, armed:false, reason:'expiry-invalid', expires_at_utc:null };
|
|
@@ -152,7 +152,7 @@ export const R36_CAPABILITY_ENTRIES=Object.freeze([
|
|
|
152
152
|
gateway('desktop.action','desktop_action','desktop_control','action','DEADBYTE_DESKTOP_RUNTIME','desktop',{mutating:true,receipt_class:'desktop'}),
|
|
153
153
|
|
|
154
154
|
direct('autonomous.session_status','autonomous_session_status','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'autonomous'}),
|
|
155
|
-
direct('native_diff.preview','native_diff_preview','DEADBYTE_AUTONOMOUS_RUNTIME','
|
|
155
|
+
direct('native_diff.preview','native_diff_preview','DEADBYTE_AUTONOMOUS_RUNTIME','coding',{receipt_class:'native_diff'}),
|
|
156
156
|
direct('native_diff.apply','native_diff_apply','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'native_diff'}),
|
|
157
157
|
direct('native_diff.verify','native_diff_verify','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'verification'}),
|
|
158
158
|
direct('autonomous.goal_submit','autonomous_goal_submit','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'autonomous'}),
|
|
@@ -3,7 +3,8 @@ import { assertHostArmed } from './host-plane.mjs';
|
|
|
3
3
|
|
|
4
4
|
const CODING_ARMED_READ_CAPABILITIES = new Set([
|
|
5
5
|
'coding.tree','coding.stat','coding.search','coding.files_read','coding.file_read',
|
|
6
|
-
'semantic.outline','semantic.definition','semantic.references','semantic.diagnostics','semantic.implementations','semantic.rename_preview'
|
|
6
|
+
'semantic.outline','semantic.definition','semantic.references','semantic.diagnostics','semantic.implementations','semantic.rename_preview',
|
|
7
|
+
'native_diff.preview'
|
|
7
8
|
]);
|
|
8
9
|
|
|
9
10
|
export const CAPABILITY_STATES = Object.freeze({
|
|
@@ -20,7 +20,7 @@ const CONTRACTS = Object.freeze({
|
|
|
20
20
|
get_recent_tool_calls:{native:'operation_history.recent',required:[],mutation:false},
|
|
21
21
|
get_usage_stats:{native:'operation_history.stats',required:[],mutation:false},
|
|
22
22
|
give_feedback_to_desktop_commander:{native:'commander.feedback',required:['message'],mutation:true},
|
|
23
|
-
host_exec:{native:'host.exec',required:['
|
|
23
|
+
host_exec:{native:'host.exec',required:['root_id'],mutation:true},
|
|
24
24
|
host_file_read:{native:'host.file_read',required:['path'],mutation:false},
|
|
25
25
|
host_file_write:{native:'host.file_write',required:['path','content','expected_sha256'],mutation:true},
|
|
26
26
|
interact_with_process:{native:'process.input',required:['session_id','input'],mutation:true},
|
|
@@ -53,13 +53,41 @@ export function commanderCompatibilityContract(name) {
|
|
|
53
53
|
return CONTRACTS[name] ?? {native:DEADBYTE_NATIVE_TOOLS[name] ?? null,required:[],mutation:false};
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
function validateHostExecRequest(args) {
|
|
57
|
+
const mode=args.mode??'script';
|
|
58
|
+
const common=['mode','root_id','cwd','timeout_ms'];
|
|
59
|
+
let required, allowed;
|
|
60
|
+
if(mode==='script'){
|
|
61
|
+
required=['root_id','command_id','script_path','script_sha256'];
|
|
62
|
+
allowed=[...common,'command_id','script_path','script_sha256','args'];
|
|
63
|
+
}else if(mode==='inline'){
|
|
64
|
+
required=['root_id','command_id','command'];
|
|
65
|
+
allowed=[...common,'command_id','command'];
|
|
66
|
+
}else if(mode==='native'){
|
|
67
|
+
required=['root_id','executable','executable_sha256'];
|
|
68
|
+
allowed=[...common,'executable','executable_sha256','args'];
|
|
69
|
+
}else{
|
|
70
|
+
throw new Error('host_exec mode must be script, inline, or native');
|
|
71
|
+
}
|
|
72
|
+
const missing=required.filter(k=>!own(args,k)||args[k]===undefined||args[k]===null||args[k]==='');
|
|
73
|
+
if(missing.length) throw new Error(`missing required fields: ${missing.join(', ')}`);
|
|
74
|
+
const unknown=Object.keys(args).filter(k=>!allowed.includes(k));
|
|
75
|
+
if(unknown.length) throw new Error(`host_exec ${mode} unexpected fields: ${unknown.join(', ')}`);
|
|
76
|
+
const id=/^[A-Za-z0-9._-]{1,64}$/;
|
|
77
|
+
if(typeof args.root_id!=='string'||!id.test(args.root_id)) throw new Error('host_exec root_id invalid');
|
|
78
|
+
if(mode!=='native'&&(typeof args.command_id!=='string'||!id.test(args.command_id))) throw new Error('host_exec command_id invalid');
|
|
79
|
+
if(mode==='inline'&&(typeof args.command!=='string'||args.command.length>262144||args.command.includes(String.fromCharCode(0)))) throw new Error('host_exec inline command invalid');
|
|
80
|
+
if(mode==='script'&&!/^[0-9a-f]{64}$/.test(args.script_sha256)) throw new Error('host_exec script_sha256 invalid');
|
|
81
|
+
if(mode==='native'&&!/^[0-9a-f]{64}$/.test(args.executable_sha256)) throw new Error('host_exec executable_sha256 invalid');
|
|
82
|
+
}
|
|
83
|
+
|
|
56
84
|
export function validateCommanderRequest(name,args={}) {
|
|
57
85
|
const c=commanderCompatibilityContract(name);
|
|
58
86
|
if (!args || typeof args!=='object' || Array.isArray(args)) throw new Error('request arguments must be an object');
|
|
59
87
|
const missing=c.required.filter(k=>!own(args,k)||args[k]===undefined||args[k]===null||args[k]==='');
|
|
60
88
|
if(missing.length) throw new Error(`missing required fields: ${missing.join(', ')}`);
|
|
61
89
|
if(c.mutation && !['create_directory','start_process','force_terminate','kill_process','interact_with_process','host_exec'].includes(name) && !('expected_sha256' in args) && !('expected_source_identity' in args)) throw new Error('mutation requires an explicit precondition');
|
|
62
|
-
if(
|
|
90
|
+
if(name==='host_exec') validateHostExecRequest(args);
|
|
63
91
|
return Object.freeze({commander_tool:name,native_tool:c.native,mutation:c.mutation,args});
|
|
64
92
|
}
|
|
65
93
|
|