mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
TASK-6e4ff870-a386-4a11-a59c-444ebc23732e: correct candidate source boundaries
This commit is contained in:
1 parent
ea36a28d14
commit
0665bb305b
11 files changed
+327
-59
No files matched your search
@@ -2754,3 +2754,44 @@ test_integrity_note:
|
||||
did_relax_any_assertion: false
|
||||
if_true_explain_spec_basis: ""
|
||||
```
|
||||
|
||||
# Candidate source B2 authenticated-attempt spec correction (2026-10-01)
|
||||
|
||||
```yaml
|
||||
test_integrity_note:
|
||||
change_type: spec_correction
|
||||
scenarios:
|
||||
- id: SCN-candidate-bootstrap-one-shot
|
||||
given: "A CheckService-issued opaque registered-plan handle"
|
||||
when: "A foreign, cloned, expired, replayed, or already-closed handle is used"
|
||||
then: "No FD3 admission opens; the only accepted acknowledgement is the exact FD4 binding frame and it closes the original linear handle"
|
||||
- id: SCN-candidate-input-consumption
|
||||
given: "A frozen, bounded product snapshot and a fixed Node E binding"
|
||||
when: "The original product bytes change before execution"
|
||||
then: "An actual spawned child reads the frozen bytes; post-capture drift refuses before spawn"
|
||||
- id: SCN-candidate-execution-boundary
|
||||
given: "An opaque attempt with fixed command, arguments, explicit environment, and output cap"
|
||||
when: "The child exits zero after exceeding the cap"
|
||||
then: "The parent records overflow as non-success without accepting an injected executor or caller-selected limit"
|
||||
- id: SCN-candidate-fence-closure
|
||||
given: "A closed opaque attempt"
|
||||
when: "The backend has not recorded namespace identity, FD closure, and descendant reaping"
|
||||
then: "Terminal proof is UNKNOWN; fabricated observations and cloned handles cannot create proof"
|
||||
observable_outcomes:
|
||||
- "Only the exact FD4 acknowledgement closes a one-shot opaque admission"
|
||||
- "Child stdout proves frozen-byte consumption, not same-process test reads"
|
||||
- "Zero exit plus output overflow is never success"
|
||||
- "Missing backend fence evidence is never TerminalProof"
|
||||
determinism_controls:
|
||||
- "Temporary source trees, fixed absolute Node runtime, explicit empty child environment, bounded streams"
|
||||
- "No injected executor, caller-provided command, root, environment, limit, or terminal observation"
|
||||
anti_cheat_rationale:
|
||||
prevents:
|
||||
- "Arbitrary tuple issuance or a fabricated bootstrap literal"
|
||||
- "Boolean caller observations minting terminal proof"
|
||||
- "Cloned or reused handles reopening an admission"
|
||||
- "Same-process snapshot reads impersonating child consumption"
|
||||
relaxation:
|
||||
did_relax_any_assertion: false
|
||||
if_true_explain_spec_basis: ""
|
||||
```
|
||||
@@ -1,6 +1,33 @@
|
||||
import { TorchError } from '../kernel/errors.mjs';
|
||||
const fail = (message, code, details) => { throw new TorchError(message, { code, details }); };
|
||||
export function createCandidateExecutionFenceV2({ bootstrap, backend = 'private-pid1-namespace' } = {}) { if (!bootstrap?.transport?.closesBeforeCandidateSpawn || backend !== 'private-pid1-namespace') fail('Candidate fence has no supported private bootstrap', 'CANDIDATE_FENCE_UNAVAILABLE'); return Object.freeze({ schema: 'torch.dev/candidate-execution-fence/v2alpha1', backend, nonce: bootstrap.nonce, closed: false }); }
|
||||
/** A direct exit or empty PGID is deliberately insufficient: missing observed PID1/reap proof is UNKNOWN. */
|
||||
export function observeCandidateExecutionFenceV2({ fence, observation = {} } = {}) { if (!fence || fence.closed) fail('Candidate fence is unavailable', 'CANDIDATE_FENCE_UNAVAILABLE'); const closed = observation.privatePid1 === true && observation.namespaceObserved === true && observation.descendantsReaped === true && observation.admissionFdsClosed === true; return Object.freeze({ schema: 'torch.dev/candidate-terminal-proof/v2alpha1', outcome: closed ? 'terminal' : 'unknown', terminalProof: closed, reason: closed ? null : 'descendant-closure-unobserved', observation: Object.freeze({ privatePid1: observation.privatePid1 === true, namespaceObserved: observation.namespaceObserved === true, descendantsReaped: observation.descendantsReaped === true, admissionFdsClosed: observation.admissionFdsClosed === true }) }); }
|
||||
export function closeCandidateExecutionFenceV2(fence) { if (!fence || fence.closed) fail('Candidate fence is already closed', 'CANDIDATE_FENCE_UNAVAILABLE'); return Object.freeze({ ...fence, closed: true }); }
|
||||
|
||||
function fail(message, code, details) {
|
||||
throw new TorchError(message, { code, details });
|
||||
}
|
||||
|
||||
/**
|
||||
* Fence observations are owned by the backend, never submitted by the caller.
|
||||
* Until the backend has recorded a PID1 namespace identity, FD closure, and
|
||||
* namespace-wide reaping, every attempt is UNKNOWN. A process-group exit never
|
||||
* creates TerminalProof.
|
||||
*/
|
||||
export function createCandidateExecutionFenceRuntimeV2({ stateForAttempt, backendObservation } = {}) {
|
||||
if (typeof stateForAttempt !== 'function' || typeof backendObservation !== 'function') throw new TypeError('candidate fence runtime is incomplete');
|
||||
const closed = new WeakSet();
|
||||
function close(attempt) {
|
||||
if (!stateForAttempt(attempt) || closed.has(attempt)) fail('Candidate fence is unavailable', 'CANDIDATE_FENCE_UNAVAILABLE');
|
||||
closed.add(attempt);
|
||||
}
|
||||
function terminal(attempt) {
|
||||
if (!stateForAttempt(attempt) || !closed.has(attempt)) fail('Candidate fence is unavailable', 'CANDIDATE_FENCE_UNAVAILABLE');
|
||||
const observed = backendObservation(attempt);
|
||||
const qualified = observed?.backend === 'private-pid1-namespace'
|
||||
&& Number.isSafeInteger(observed.namespacePid) && observed.namespacePid > 0
|
||||
&& typeof observed.namespaceIdentity === 'string' && observed.namespaceIdentity.length > 0
|
||||
&& observed.admissionFdsClosed === true && observed.descendantsReaped === true && observed.escapedDescendants === false;
|
||||
return Object.freeze({
|
||||
schema: 'torch.dev/candidate-terminal-proof/v2alpha1', outcome: qualified ? 'terminal' : 'unknown', terminalProof: qualified,
|
||||
reason: qualified ? null : 'descendant-closure-unobserved',
|
||||
});
|
||||
}
|
||||
return Object.freeze({ close, terminal });
|
||||
}
|
||||
@@ -49,7 +49,7 @@ function hashRegularFile(path, expected, limits) {
|
||||
} finally { if (fd !== undefined) closeSync(fd); }
|
||||
}
|
||||
/** Private caller seam: callers obtain inputRoot from the returned opaque snapshot, never from a policy selector. */
|
||||
export function captureCandidateInputSnapshotV2({ sourceRoot, destinationRoot, paths, limits: requestedLimits = {}, id = randomUUID() } = {}) {
|
||||
function captureCandidateInputSnapshotV2({ sourceRoot, destinationRoot, paths, limits: requestedLimits = {}, id = randomUUID() } = {}) {
|
||||
const limits = normalizeLimits(requestedLimits); if (typeof sourceRoot !== 'string' || typeof destinationRoot !== 'string' || !Array.isArray(paths)) fail('Candidate snapshot request is invalid', 'CANDIDATE_SNAPSHOT_INPUT_INVALID');
|
||||
const source = resolve(sourceRoot); const destination = resolve(destinationRoot); if (source === destination || !relative(source, destination).startsWith('..')) fail('Candidate snapshot destination must be outside source', 'CANDIDATE_SNAPSHOT_INPUT_INVALID');
|
||||
const listed = files(source, paths, limits); mkdirSync(destination, { recursive: false, mode: 0o700 }); let totalBytes = 0; const records = [];
|
||||
@@ -57,7 +57,7 @@ export function captureCandidateInputSnapshotV2({ sourceRoot, destinationRoot, p
|
||||
const manifest = Object.freeze({ schema: 'torch.dev/candidate-input-manifest/v2alpha1', id, files: Object.freeze(records), totalBytes, digest: createHash('sha256').update(JSON.stringify(records)).digest('hex') });
|
||||
return Object.freeze({ schema: 'torch.dev/candidate-input-snapshot/v2alpha1', inputRoot: destination, manifest, limits });
|
||||
}
|
||||
export function verifyCandidateInputSnapshotV2(snapshot = {}) {
|
||||
function verifyCandidateInputSnapshotV2(snapshot = {}) {
|
||||
if (snapshot?.schema !== 'torch.dev/candidate-input-snapshot/v2alpha1' || !snapshot.manifest?.files || typeof snapshot.inputRoot !== 'string') fail('Candidate snapshot is malformed', 'CANDIDATE_SNAPSHOT_INVALID');
|
||||
const listed = files(snapshot.inputRoot, snapshot.manifest.files.map((file) => file.path), snapshot.limits);
|
||||
const observed = listed.map((file) => hashRegularFile(join(snapshot.inputRoot, file.path), { ...file, bytes: file.size }, snapshot.limits));
|
||||
@@ -67,3 +67,30 @@ export function verifyCandidateInputSnapshotV2(snapshot = {}) {
|
||||
}
|
||||
return Object.freeze({ verified: true, digest: snapshot.manifest.digest, files: observed.length, totalBytes: snapshot.manifest.totalBytes });
|
||||
}
|
||||
|
||||
/**
|
||||
* The public boundary accepts only a service-issued attempt. Source roots,
|
||||
* paths, destinations, and S limits live in the service's private state.
|
||||
*/
|
||||
export function createCandidateInputSnapshotRuntimeV2({ stateForAttempt } = {}) {
|
||||
if (typeof stateForAttempt !== 'function') throw new TypeError('stateForAttempt is required');
|
||||
const snapshots = new WeakMap();
|
||||
function capture(attempt) {
|
||||
const state = stateForAttempt(attempt);
|
||||
if (!state?.input) fail('Candidate attempt has no frozen input authority', 'CANDIDATE_SNAPSHOT_ADMISSION_REQUIRED');
|
||||
const snapshot = captureCandidateInputSnapshotV2(state.input);
|
||||
snapshots.set(attempt, snapshot);
|
||||
return Object.freeze({ digest: snapshot.manifest.digest, files: snapshot.manifest.files.length, totalBytes: snapshot.manifest.totalBytes });
|
||||
}
|
||||
function verify(attempt) {
|
||||
const snapshot = snapshots.get(attempt);
|
||||
if (!snapshot) fail('Candidate snapshot is unavailable', 'CANDIDATE_SNAPSHOT_ADMISSION_REQUIRED');
|
||||
return verifyCandidateInputSnapshotV2(snapshot);
|
||||
}
|
||||
function cwd(attempt) {
|
||||
const snapshot = snapshots.get(attempt);
|
||||
if (!snapshot) fail('Candidate snapshot is unavailable', 'CANDIDATE_SNAPSHOT_ADMISSION_REQUIRED');
|
||||
return snapshot.inputRoot;
|
||||
}
|
||||
return Object.freeze({ capture, verify, cwd });
|
||||
}
|
||||
@@ -1,16 +1,81 @@
|
||||
import { randomBytes } from 'node:crypto';
|
||||
import { createHash, randomBytes } from 'node:crypto';
|
||||
import { TorchError } from '../kernel/errors.mjs';
|
||||
|
||||
const live = new WeakSet(); const used = new Set();
|
||||
const fail = (message, code, details) => { throw new TorchError(message, { code, details }); };
|
||||
/** CheckService-only issuer. The returned object is intentionally not serializable and carries no DB/adapter/writer capability. */
|
||||
export function issueCandidateNativeAdmissionV2({ projectId, areaId, checkId, runId, generation, policyDigest, engineDigest, expiresAt } = {}) {
|
||||
for (const [key, value] of Object.entries({ projectId, areaId, checkId, runId, generation, policyDigest, engineDigest, expiresAt })) if (typeof value !== 'string' || !value) fail('Candidate native admission is incomplete', 'CANDIDATE_NATIVE_ADMISSION_INVALID', { key });
|
||||
const admission = Object.freeze({ schema: 'torch.dev/candidate-native-admission/v2alpha1', projectId, areaId, checkId, runId, generation, policyDigest, engineDigest, expiresAt, nonce: randomBytes(32).toString('base64url') }); live.add(admission); return admission;
|
||||
const ADMISSION_SCHEMA = 'torch.dev/candidate-source-parent-admission/v2alpha1';
|
||||
const ACK_SCHEMA = 'torch.dev/candidate-source-parent-binding/v2alpha1';
|
||||
const SHA256 = /^[a-f0-9]{64}$/;
|
||||
const MAX_FRAME_BYTES = 64 * 1024;
|
||||
|
||||
function fail(message, code, details) {
|
||||
throw new TorchError(message, { code, details });
|
||||
}
|
||||
export function openCandidateSourceBootstrapV2(admission, { now = () => new Date() } = {}) {
|
||||
if (!live.has(admission) || used.has(admission.nonce)) fail('Candidate native admission is unavailable or replayed', 'CANDIDATE_NATIVE_ADMISSION_REPLAY');
|
||||
if (Number.isNaN(Date.parse(admission.expiresAt)) || Date.parse(admission.expiresAt) <= now().getTime()) fail('Candidate native admission expired', 'CANDIDATE_NATIVE_ADMISSION_EXPIRED');
|
||||
used.add(admission.nonce); live.delete(admission);
|
||||
return Object.freeze({ schema: 'torch.dev/candidate-bootstrap/v2alpha1', nonce: admission.nonce, runId: admission.runId, generation: admission.generation, policyDigest: admission.policyDigest, engineDigest: admission.engineDigest, expiresAt: admission.expiresAt, transport: Object.freeze({ inputFd: 3, acknowledgementFd: 4, closesBeforeCandidateSpawn: true }) });
|
||||
|
||||
function digest(bytes) {
|
||||
return createHash('sha256').update(bytes).digest('hex');
|
||||
}
|
||||
|
||||
function validString(value) {
|
||||
return typeof value === 'string' && value.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service-only closure factory. It has no public issuer that accepts caller
|
||||
* project/check/run tuples: CheckService supplies an opaque registered-plan
|
||||
* handle to stateForPlan and this module serializes only that captured state.
|
||||
*/
|
||||
export function createCandidateSourceBootstrapRuntimeV2({ stateForPlan, now = () => new Date() } = {}) {
|
||||
if (typeof stateForPlan !== 'function') throw new TypeError('stateForPlan is required');
|
||||
const attempts = new WeakMap();
|
||||
|
||||
function create(plan) {
|
||||
const state = stateForPlan(plan);
|
||||
if (!state || typeof state !== 'object') fail('Registered candidate plan is unavailable', 'CANDIDATE_NATIVE_ADMISSION_REQUIRED');
|
||||
const required = ['admissionId', 'leaseId', 'checkId', 'policyBytes', 'policyDigest', 'engine', 'subject', 'artifactManifest', 'expiresAt'];
|
||||
for (const key of required) if (!Object.hasOwn(state, key)) fail('Registered candidate plan is incomplete', 'CANDIDATE_NATIVE_ADMISSION_INVALID', { key });
|
||||
if (!Buffer.isBuffer(state.policyBytes) || state.policyBytes.length === 0 || state.policyBytes.length > 1024 * 1024
|
||||
|| !SHA256.test(state.policyDigest) || digest(state.policyBytes) !== state.policyDigest
|
||||
|| !validString(state.admissionId) || !validString(state.leaseId) || !validString(state.checkId)
|
||||
|| !Number.isSafeInteger(state.runGeneration) || !Number.isSafeInteger(state.guardGeneration)
|
||||
|| Number.isNaN(Date.parse(state.expiresAt))) fail('Registered candidate plan is invalid', 'CANDIDATE_NATIVE_ADMISSION_INVALID');
|
||||
const handle = Object.freeze({});
|
||||
attempts.set(handle, { state, used: false, closed: false, nonce: randomBytes(32).toString('base64url') });
|
||||
return handle;
|
||||
}
|
||||
|
||||
function open(handle) {
|
||||
const attempt = attempts.get(handle);
|
||||
if (!attempt || attempt.used || attempt.closed) fail('Candidate admission is unavailable or replayed', 'CANDIDATE_NATIVE_ADMISSION_REPLAY');
|
||||
if (Date.parse(attempt.state.expiresAt) <= now().getTime()) {
|
||||
attempt.closed = true;
|
||||
fail('Candidate admission expired', 'CANDIDATE_NATIVE_ADMISSION_EXPIRED');
|
||||
}
|
||||
attempt.used = true;
|
||||
const { state } = attempt;
|
||||
const frame = Buffer.from(JSON.stringify({
|
||||
schema: ADMISSION_SCHEMA, version: 2, admissionId: state.admissionId, leaseId: state.leaseId,
|
||||
checkId: state.checkId, runGeneration: state.runGeneration, guardGeneration: state.guardGeneration,
|
||||
policyBytesBase64: state.policyBytes.toString('base64'), policyDigest: state.policyDigest,
|
||||
engine: state.engine, subject: state.subject, artifactManifest: state.artifactManifest,
|
||||
receiptAdapterAdmission: null,
|
||||
}), 'utf8');
|
||||
if (frame.length > MAX_FRAME_BYTES) fail('Candidate parent admission frame exceeds its bound', 'CANDIDATE_NATIVE_ADMISSION_INVALID');
|
||||
return Object.freeze({ frame, acknowledgement: Buffer.from(`${ACK_SCHEMA}\n${state.admissionId}\n${state.policyDigest}\n`, 'utf8'), nonce: attempt.nonce });
|
||||
}
|
||||
|
||||
function acknowledgeAndClose(handle, acknowledgement) {
|
||||
const attempt = attempts.get(handle);
|
||||
if (!attempt || !attempt.used || attempt.closed || !Buffer.isBuffer(acknowledgement)) fail('Candidate acknowledgement is unavailable', 'CANDIDATE_NATIVE_ADMISSION_REPLAY');
|
||||
const expected = Buffer.from(`${ACK_SCHEMA}\n${attempt.state.admissionId}\n${attempt.state.policyDigest}\n`, 'utf8');
|
||||
if (!acknowledgement.equals(expected)) fail('Candidate parent acknowledgement mismatches admission', 'CANDIDATE_PARENT_ACK_MISMATCH');
|
||||
attempt.closed = true;
|
||||
return Object.freeze({ admissionFdsClosed: true, receiptEligible: false });
|
||||
}
|
||||
|
||||
function cancel(handle) {
|
||||
const attempt = attempts.get(handle);
|
||||
if (!attempt || attempt.used || attempt.closed) fail('Candidate admission is unavailable', 'CANDIDATE_NATIVE_ADMISSION_REPLAY');
|
||||
attempt.closed = true;
|
||||
}
|
||||
|
||||
return Object.freeze({ create, open, acknowledgeAndClose, cancel });
|
||||
}
|
||||
@@ -1,15 +1,61 @@
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { isAbsolute } from 'node:path';
|
||||
import { TorchError } from '../kernel/errors.mjs';
|
||||
import { verifyCandidateInputSnapshotV2 } from './candidate-input-snapshot.mjs';
|
||||
const fail = (message, code, details) => { throw new TorchError(message, { code, details }); };
|
||||
|
||||
export const CANDIDATE_EXECUTION_LIMITS_V2 = Object.freeze({ timeoutMs: 300000, maxOutputBytes: 1048576, maxArgs: 64, maxArgBytes: 4096 });
|
||||
function bound(value, limit, name) { if (typeof value !== 'string' || Buffer.byteLength(value, 'utf8') > limit) fail('Candidate execution value is invalid', 'CANDIDATE_EXECUTION_INVALID', { name }); return value; }
|
||||
export function runCandidateSourceExecutionV2({ command, args = [], inputSnapshot, environment = {}, executor = spawnSync, limits = CANDIDATE_EXECUTION_LIMITS_V2 } = {}) {
|
||||
if (!isAbsolute(command) || inputSnapshot?.schema !== 'torch.dev/candidate-input-snapshot/v2alpha1' || typeof executor !== 'function' || !Array.isArray(args) || args.length > limits.maxArgs || Object.keys(environment).some((key) => ['PATH', 'HOME', 'NODE_PATH', 'npm_config_cache'].includes(key))) fail('Candidate execution request is invalid', 'CANDIDATE_EXECUTION_INVALID');
|
||||
verifyCandidateInputSnapshotV2(inputSnapshot);
|
||||
const safeArgs = args.map((arg) => bound(arg, limits.maxArgBytes, 'arg')); const env = Object.freeze(Object.fromEntries(Object.entries(environment).sort()));
|
||||
let raw; try { raw = executor(command, safeArgs, { cwd: inputSnapshot.inputRoot, env, encoding: 'buffer', stdio: ['ignore', 'pipe', 'pipe'], timeout: limits.timeoutMs, maxBuffer: limits.maxOutputBytes, killSignal: 'SIGTERM' }); } catch (error) { raw = { status: null, error }; }
|
||||
const stdout = Buffer.from(raw?.stdout ?? ''); const stderr = Buffer.from(raw?.stderr ?? ''); const overflow = stdout.length > limits.maxOutputBytes || stderr.length > limits.maxOutputBytes || raw?.error?.code === 'ENOBUFS'; const timeout = raw?.error?.code === 'ETIMEDOUT' || raw?.timedOut === true;
|
||||
return Object.freeze({ schema: 'torch.dev/candidate-source-execution/v2alpha1', terminal: Object.freeze({ kind: timeout ? 'timeout' : overflow ? 'overflow' : raw?.signal ? 'signal' : raw?.error ? 'error' : 'exit', exitStatus: Number.isInteger(raw?.status) ? raw.status : null, signal: raw?.signal ?? null, overflow, timeout, success: !timeout && !overflow && !raw?.signal && !raw?.error && raw?.status === 0 }), output: Object.freeze({ stdout: stdout.subarray(0, limits.maxOutputBytes), stderr: stderr.subarray(0, limits.maxOutputBytes) }) });
|
||||
|
||||
function fail(message, code, details) {
|
||||
throw new TorchError(message, { code, details });
|
||||
}
|
||||
|
||||
function validRuntime(state) {
|
||||
const runtime = state?.runtime;
|
||||
if (!runtime || typeof runtime.command !== 'string' || !runtime.command.startsWith('/') || !Array.isArray(runtime.args)
|
||||
|| !runtime.args.every((arg) => typeof arg === 'string' && Buffer.byteLength(arg, 'utf8') <= CANDIDATE_EXECUTION_LIMITS_V2.maxArgBytes)
|
||||
|| runtime.args.length > CANDIDATE_EXECUTION_LIMITS_V2.maxArgs
|
||||
|| !runtime.environment || Object.keys(runtime.environment).some((key) => ['PATH', 'HOME', 'NODE_PATH', 'npm_config_cache'].includes(key))) {
|
||||
fail('Candidate fixed runtime is invalid', 'CANDIDATE_EXECUTION_RUNTIME_INVALID');
|
||||
}
|
||||
return runtime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a fixed, CheckService-derived E binding. `run` takes only an opaque
|
||||
* attempt; command, arguments, environment, executor, cwd and limits cannot
|
||||
* be selected by callers. It is raw terminal evidence, never a receipt PASS.
|
||||
*/
|
||||
export function createCandidateSourceExecutionRuntimeV2({ stateForAttempt, snapshotRuntime } = {}) {
|
||||
if (typeof stateForAttempt !== 'function' || !snapshotRuntime) throw new TypeError('candidate execution runtime is incomplete');
|
||||
const results = new WeakMap();
|
||||
function run(attempt) {
|
||||
const state = stateForAttempt(attempt);
|
||||
const runtime = validRuntime(state);
|
||||
snapshotRuntime.verify(attempt);
|
||||
const cwd = snapshotRuntime.cwd(attempt);
|
||||
let raw;
|
||||
try {
|
||||
raw = spawnSync(runtime.command, runtime.args, {
|
||||
cwd, env: Object.freeze({ ...runtime.environment }), encoding: 'buffer',
|
||||
stdio: ['ignore', 'pipe', 'pipe'], timeout: CANDIDATE_EXECUTION_LIMITS_V2.timeoutMs,
|
||||
maxBuffer: CANDIDATE_EXECUTION_LIMITS_V2.maxOutputBytes, killSignal: 'SIGTERM',
|
||||
});
|
||||
} catch (error) { raw = { status: null, error }; }
|
||||
const stdout = Buffer.from(raw?.stdout ?? '');
|
||||
const stderr = Buffer.from(raw?.stderr ?? '');
|
||||
const overflow = stdout.length > CANDIDATE_EXECUTION_LIMITS_V2.maxOutputBytes || stderr.length > CANDIDATE_EXECUTION_LIMITS_V2.maxOutputBytes || raw?.error?.code === 'ENOBUFS';
|
||||
const timeout = raw?.error?.code === 'ETIMEDOUT' || raw?.timedOut === true;
|
||||
const observation = Object.freeze({
|
||||
schema: 'torch.dev/candidate-source-execution/v2alpha1',
|
||||
terminal: Object.freeze({ kind: timeout ? 'timeout' : overflow ? 'overflow' : raw?.signal ? 'signal' : raw?.error ? 'error' : 'exit', exitStatus: Number.isInteger(raw?.status) ? raw.status : null, signal: raw?.signal ?? null, overflow, timeout, success: !timeout && !overflow && !raw?.signal && !raw?.error && raw?.status === 0 }),
|
||||
output: Object.freeze({ stdout: stdout.subarray(0, CANDIDATE_EXECUTION_LIMITS_V2.maxOutputBytes), stderr: stderr.subarray(0, CANDIDATE_EXECUTION_LIMITS_V2.maxOutputBytes) }),
|
||||
});
|
||||
snapshotRuntime.verify(attempt);
|
||||
results.set(attempt, observation);
|
||||
return observation;
|
||||
}
|
||||
function observation(attempt) {
|
||||
const value = results.get(attempt);
|
||||
if (!value) fail('Candidate execution has not run', 'CANDIDATE_EXECUTION_UNAVAILABLE');
|
||||
return value;
|
||||
}
|
||||
return Object.freeze({ run, observation });
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { createCandidateExecutionFenceV2, observeCandidateExecutionFenceV2 } from '../../src/checks/candidate-execution-fence.mjs';
|
||||
const bootstrap = { nonce: 'n', transport: { closesBeforeCandidateSpawn: true } };
|
||||
test('SCN-candidate-fence-closure: double-fork/escaped-descendant uncertainty is UNKNOWN, never terminal proof', () => { const fence = createCandidateExecutionFenceV2({ bootstrap }); const unknown = observeCandidateExecutionFenceV2({ fence, observation: { privatePid1: true, namespaceObserved: true, admissionFdsClosed: true, descendantsReaped: false } }); assert.equal(unknown.outcome, 'unknown'); assert.equal(unknown.terminalProof, false); const terminal = observeCandidateExecutionFenceV2({ fence, observation: { privatePid1: true, namespaceObserved: true, admissionFdsClosed: true, descendantsReaped: true } }); assert.equal(terminal.terminalProof, true); });
|
||||
import { createCandidateExecutionFenceRuntimeV2 } from '../../src/checks/candidate-execution-fence.mjs';
|
||||
|
||||
test('SCN-candidate-fence-closure: a closed opaque attempt without backend namespace/reaping evidence is UNKNOWN and clones cannot be reused', () => {
|
||||
const states = new WeakMap(); const attempt = Object.freeze({}); states.set(attempt, { authenticated: true });
|
||||
const fence = createCandidateExecutionFenceRuntimeV2({ stateForAttempt: (value) => states.get(value), backendObservation: () => null });
|
||||
assert.throws(() => fence.close({}), { code: 'CANDIDATE_FENCE_UNAVAILABLE' });
|
||||
fence.close(attempt); const terminal = fence.terminal(attempt);
|
||||
assert.equal(terminal.outcome, 'unknown'); assert.equal(terminal.terminalProof, false);
|
||||
assert.throws(() => fence.terminal({ ...attempt }), { code: 'CANDIDATE_FENCE_UNAVAILABLE' });
|
||||
assert.throws(() => fence.close(attempt), { code: 'CANDIDATE_FENCE_UNAVAILABLE' });
|
||||
});
|
||||
@@ -1,10 +1,28 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { chmodSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { chmodSync, mkdirSync, mkdtempSync, realpathSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import test from 'node:test';
|
||||
import { captureCandidateInputSnapshotV2, verifyCandidateInputSnapshotV2 } from '../../src/checks/candidate-input-snapshot.mjs';
|
||||
import { runCandidateSourceExecutionV2 } from '../../src/checks/candidate-source-execution.mjs';
|
||||
function roots() { const root = mkdtempSync(join(tmpdir(), 'torch-b2-source-')); mkdirSync(join(root, 'src')); writeFileSync(join(root, 'src', 'input.txt'), 'captured'); return { root, snapshot: `${root}-snapshot` }; }
|
||||
test('SCN-candidate-input-consumption: child execution seam receives frozen cwd bytes after original source mutation', () => { const { root, snapshot: destination } = roots(); const input = captureCandidateInputSnapshotV2({ sourceRoot: root, destinationRoot: destination, paths: ['src'] }); writeFileSync(join(root, 'src', 'input.txt'), 'mutated'); const result = runCandidateSourceExecutionV2({ command: process.execPath, args: [], inputSnapshot: input, executor: (_command, _args, execution) => ({ status: 0, stdout: readFileSync(join(execution.cwd, 'src', 'input.txt')) }) }); assert.equal(result.terminal.success, true); assert.equal(result.output.stdout.toString(), 'captured'); assert.equal(verifyCandidateInputSnapshotV2(input).verified, true); });
|
||||
test('SCN-candidate-input-drift: frozen-input mutation refuses rather than relabeling evidence', () => { const { root, snapshot: destination } = roots(); const input = captureCandidateInputSnapshotV2({ sourceRoot: root, destinationRoot: destination, paths: ['src'] }); const file = join(input.inputRoot, 'src', 'input.txt'); chmodSync(file, 0o600); writeFileSync(file, 'drift'); assert.throws(() => verifyCandidateInputSnapshotV2(input), { code: 'CANDIDATE_SNAPSHOT_DRIFT' }); });
|
||||
import { createCandidateInputSnapshotRuntimeV2 } from '../../src/checks/candidate-input-snapshot.mjs';
|
||||
import { createCandidateSourceExecutionRuntimeV2 } from '../../src/checks/candidate-source-execution.mjs';
|
||||
|
||||
function attemptWithInput() {
|
||||
const root = mkdtempSync(join(tmpdir(), 'torch-b2-source-')); mkdirSync(join(root, 'src')); writeFileSync(join(root, 'src', 'input.txt'), 'captured');
|
||||
const states = new WeakMap(); const attempt = Object.freeze({});
|
||||
states.set(attempt, { input: { sourceRoot: root, destinationRoot: `${root}-snapshot`, paths: ['src'] }, runtime: { command: realpathSync(process.execPath), args: ['-e', 'process.stdout.write(require("node:fs").readFileSync("src/input.txt"))'], environment: {} } });
|
||||
return { root, attempt, states };
|
||||
}
|
||||
|
||||
test('SCN-candidate-input-consumption: an actual fixed Node child reads frozen bytes after the original source mutates', () => {
|
||||
const { root, attempt, states } = attemptWithInput();
|
||||
const snapshots = createCandidateInputSnapshotRuntimeV2({ stateForAttempt: (value) => states.get(value) });
|
||||
snapshots.capture(attempt); writeFileSync(join(root, 'src', 'input.txt'), 'mutated');
|
||||
const execution = createCandidateSourceExecutionRuntimeV2({ stateForAttempt: (value) => states.get(value), snapshotRuntime: snapshots }).run(attempt);
|
||||
assert.equal(execution.terminal.success, true); assert.equal(execution.output.stdout.toString(), 'captured');
|
||||
});
|
||||
|
||||
test('SCN-candidate-input-drift: a post-capture mutation refuses before a real child can be launched', () => {
|
||||
const { attempt, states } = attemptWithInput(); const snapshots = createCandidateInputSnapshotRuntimeV2({ stateForAttempt: (value) => states.get(value) });
|
||||
snapshots.capture(attempt); const file = join(snapshots.cwd(attempt), 'src', 'input.txt'); chmodSync(file, 0o600); writeFileSync(file, 'drift');
|
||||
assert.throws(() => createCandidateSourceExecutionRuntimeV2({ stateForAttempt: (value) => states.get(value), snapshotRuntime: snapshots }).run(attempt), { code: 'CANDIDATE_SNAPSHOT_DRIFT' });
|
||||
});
|
||||
@@ -3,5 +3,12 @@ import { mkdtempSync, symlinkSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import test from 'node:test';
|
||||
import { captureCandidateInputSnapshotV2 } from '../../src/checks/candidate-input-snapshot.mjs';
|
||||
test('SCN-candidate-snapshot-policy: product links and S caps refuse before a snapshot is admitted', () => { const root = mkdtempSync(join(tmpdir(), 'torch-b2-policy-')); writeFileSync(join(root, 'file'), 'x'); symlinkSync('file', join(root, 'link')); assert.throws(() => captureCandidateInputSnapshotV2({ sourceRoot: root, destinationRoot: `${root}-snapshot`, paths: ['link'] }), { code: 'CANDIDATE_SNAPSHOT_LINK_REJECTED' }); });
|
||||
import { createCandidateInputSnapshotRuntimeV2 } from '../../src/checks/candidate-input-snapshot.mjs';
|
||||
|
||||
test('SCN-candidate-snapshot-policy: an opaque service attempt still refuses product links before capture', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'torch-b2-policy-')); writeFileSync(join(root, 'file'), 'x'); symlinkSync('file', join(root, 'link'));
|
||||
const states = new WeakMap(); const attempt = Object.freeze({}); states.set(attempt, { input: { sourceRoot: root, destinationRoot: `${root}-snapshot`, paths: ['link'] } });
|
||||
const snapshots = createCandidateInputSnapshotRuntimeV2({ stateForAttempt: (value) => states.get(value) });
|
||||
assert.throws(() => snapshots.capture(attempt), { code: 'CANDIDATE_SNAPSHOT_LINK_REJECTED' });
|
||||
assert.throws(() => snapshots.capture(Object.freeze({})), { code: 'CANDIDATE_SNAPSHOT_ADMISSION_REQUIRED' });
|
||||
});
|
||||
@@ -1,12 +1,28 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { createHash } from 'node:crypto';
|
||||
import test from 'node:test';
|
||||
import { issueCandidateNativeAdmissionV2, openCandidateSourceBootstrapV2 } from '../../src/checks/candidate-source-bootstrap.mjs';
|
||||
import { createCandidateSourceBootstrapRuntimeV2 } from '../../src/checks/candidate-source-bootstrap.mjs';
|
||||
|
||||
const issued = (expiresAt = '2030-01-01T00:00:00.000Z') => issueCandidateNativeAdmissionV2({ projectId: 'project', areaId: 'work-integration', checkId: 'test', runId: 'run', generation: 'g1', policyDigest: 'a'.repeat(64), engineDigest: 'b'.repeat(64), expiresAt });
|
||||
test('SCN-candidate-bootstrap-one-shot: only issued native admission opens once and supplies no authority handles', () => {
|
||||
assert.throws(() => openCandidateSourceBootstrapV2({}), { code: 'CANDIDATE_NATIVE_ADMISSION_REPLAY' });
|
||||
const admission = issued(); const bootstrap = openCandidateSourceBootstrapV2(admission, { now: () => new Date('2029-01-01T00:00:00.000Z') });
|
||||
assert.equal(bootstrap.transport.closesBeforeCandidateSpawn, true); assert.deepEqual(Object.keys(bootstrap).sort(), ['engineDigest', 'expiresAt', 'generation', 'nonce', 'policyDigest', 'runId', 'schema', 'transport']);
|
||||
assert.equal(Object.hasOwn(bootstrap, 'controlPlane'), false); assert.throws(() => openCandidateSourceBootstrapV2(admission, { now: () => new Date('2029-01-01T00:00:00.000Z') }), { code: 'CANDIDATE_NATIVE_ADMISSION_REPLAY' });
|
||||
function planState(expiresAt = '2030-01-01T00:00:00.000Z') {
|
||||
const policyBytes = Buffer.from('policy\n');
|
||||
return { admissionId: 'admission-1', leaseId: 'lease-1', checkId: 'test', runGeneration: 1, guardGeneration: 1, policyBytes, policyDigest: createHash('sha256').update(policyBytes).digest('hex'), engine: { pre: {}, post: {} }, subject: {}, artifactManifest: { schema: 'torch.dev/artifact-manifest/v1alpha1', manifestSha256: 'a'.repeat(64) }, expiresAt };
|
||||
}
|
||||
|
||||
test('SCN-candidate-bootstrap-one-shot: only a service-issued opaque plan opens once and its observed FD acknowledgement closes it', () => {
|
||||
const states = new WeakMap(); const plan = Object.freeze({}); states.set(plan, planState());
|
||||
const runtime = createCandidateSourceBootstrapRuntimeV2({ stateForPlan: (value) => states.get(value), now: () => new Date('2029-01-01T00:00:00.000Z') });
|
||||
assert.throws(() => runtime.create(Object.freeze({})), { code: 'CANDIDATE_NATIVE_ADMISSION_REQUIRED' });
|
||||
const handle = runtime.create(plan); const clone = { ...handle };
|
||||
assert.throws(() => runtime.open(clone), { code: 'CANDIDATE_NATIVE_ADMISSION_REPLAY' });
|
||||
const channel = runtime.open(handle);
|
||||
assert.equal(JSON.parse(channel.frame).receiptAdapterAdmission, null);
|
||||
runtime.acknowledgeAndClose(handle, channel.acknowledgement);
|
||||
assert.throws(() => runtime.open(handle), { code: 'CANDIDATE_NATIVE_ADMISSION_REPLAY' });
|
||||
assert.throws(() => runtime.acknowledgeAndClose(handle, channel.acknowledgement), { code: 'CANDIDATE_NATIVE_ADMISSION_REPLAY' });
|
||||
});
|
||||
|
||||
test('SCN-candidate-bootstrap-expiry: an expired service plan refuses before a parent frame is made', () => {
|
||||
const states = new WeakMap(); const plan = Object.freeze({}); states.set(plan, planState('2020-01-01T00:00:00.000Z'));
|
||||
const runtime = createCandidateSourceBootstrapRuntimeV2({ stateForPlan: (value) => states.get(value) });
|
||||
assert.throws(() => runtime.open(runtime.create(plan)), { code: 'CANDIDATE_NATIVE_ADMISSION_EXPIRED' });
|
||||
});
|
||||
test('SCN-candidate-bootstrap-expiry: expired admission refuses before any child protocol exists', () => assert.throws(() => openCandidateSourceBootstrapV2(issued('2020-01-01T00:00:00.000Z')), { code: 'CANDIDATE_NATIVE_ADMISSION_EXPIRED' }));
|
||||
@@ -1,9 +1,16 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { mkdtempSync, writeFileSync } from 'node:fs';
|
||||
import { mkdtempSync, realpathSync, writeFileSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
import test from 'node:test';
|
||||
import { captureCandidateInputSnapshotV2 } from '../../src/checks/candidate-input-snapshot.mjs';
|
||||
import { runCandidateSourceExecutionV2 } from '../../src/checks/candidate-source-execution.mjs';
|
||||
function snapshot() { const source = mkdtempSync(join(tmpdir(), 'torch-b2-execution-')); writeFileSync(join(source, 'input'), 'x'); return captureCandidateInputSnapshotV2({ sourceRoot: source, destinationRoot: `${source}-snapshot`, paths: ['input'] }); }
|
||||
test('SCN-candidate-execution-boundary: ambient PATH/HOME fallback and output overflow cannot become success', () => { const frozen = snapshot(); assert.throws(() => runCandidateSourceExecutionV2({ command: process.execPath, inputSnapshot: frozen, environment: { PATH: '/bin' } }), { code: 'CANDIDATE_EXECUTION_INVALID' }); const observed = runCandidateSourceExecutionV2({ command: process.execPath, inputSnapshot: frozen, limits: { timeoutMs: 1000, maxOutputBytes: 4, maxArgs: 64, maxArgBytes: 4096 }, executor: () => ({ status: 0, stdout: Buffer.from('xxxxxxxx') }) }); assert.equal(observed.terminal.overflow, true); assert.equal(observed.terminal.success, false); });
|
||||
import { createCandidateInputSnapshotRuntimeV2 } from '../../src/checks/candidate-input-snapshot.mjs';
|
||||
import { createCandidateSourceExecutionRuntimeV2 } from '../../src/checks/candidate-source-execution.mjs';
|
||||
|
||||
test('SCN-candidate-execution-boundary: only fixed E is run and actual zero-exit output overflow is not success', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'torch-b2-execution-')); writeFileSync(join(root, 'input'), 'x');
|
||||
const states = new WeakMap(); const attempt = Object.freeze({});
|
||||
states.set(attempt, { input: { sourceRoot: root, destinationRoot: `${root}-snapshot`, paths: ['input'] }, runtime: { command: realpathSync(process.execPath), args: ['-e', 'process.stdout.write("x".repeat(1048577))'], environment: {} } });
|
||||
const snapshots = createCandidateInputSnapshotRuntimeV2({ stateForAttempt: (value) => states.get(value) }); snapshots.capture(attempt);
|
||||
const result = createCandidateSourceExecutionRuntimeV2({ stateForAttempt: (value) => states.get(value), snapshotRuntime: snapshots }).run(attempt);
|
||||
assert.equal(result.terminal.overflow, true); assert.equal(result.terminal.success, false);
|
||||
});
|
||||
@@ -1,8 +1,14 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { createHash } from 'node:crypto';
|
||||
import test from 'node:test';
|
||||
import { issueCandidateNativeAdmissionV2, openCandidateSourceBootstrapV2 } from '../../src/checks/candidate-source-bootstrap.mjs';
|
||||
test('SCN-candidate-parent-capability: bootstrap frame carries only a bound tuple, never roots, env, writers, adapters, or receipt authority', () => {
|
||||
const ticket = issueCandidateNativeAdmissionV2({ projectId: 'p', areaId: 'a', checkId: 'c', runId: 'r', generation: 'g', policyDigest: 'a'.repeat(64), engineDigest: 'b'.repeat(64), expiresAt: '2030-01-01T00:00:00.000Z' });
|
||||
const frame = openCandidateSourceBootstrapV2(ticket, { now: () => new Date('2029-01-01T00:00:00.000Z') });
|
||||
for (const forbidden of ['projectId', 'areaId', 'checkId', 'inputRoot', 'cwd', 'environment', 'writer', 'adapter', 'receipt']) assert.equal(Object.hasOwn(frame, forbidden), false);
|
||||
import { createCandidateSourceBootstrapRuntimeV2 } from '../../src/checks/candidate-source-bootstrap.mjs';
|
||||
|
||||
test('SCN-candidate-parent-capability: the private FD3 record carries M only and reserves A as null', () => {
|
||||
const policyBytes = Buffer.from('policy\n'); const states = new WeakMap(); const plan = Object.freeze({});
|
||||
states.set(plan, { admissionId: 'admission-2', leaseId: 'lease-2', checkId: 'test', runGeneration: 1, guardGeneration: 2, policyBytes, policyDigest: createHash('sha256').update(policyBytes).digest('hex'), engine: { pre: {}, post: {} }, subject: {}, artifactManifest: { schema: 'torch.dev/artifact-manifest/v1alpha1', manifestSha256: 'a'.repeat(64) }, expiresAt: '2030-01-01T00:00:00.000Z' });
|
||||
const runtime = createCandidateSourceBootstrapRuntimeV2({ stateForPlan: (value) => states.get(value), now: () => new Date('2029-01-01T00:00:00.000Z') });
|
||||
const frame = JSON.parse(runtime.open(runtime.create(plan)).frame);
|
||||
for (const forbidden of ['root', 'cwd', 'environment', 'writer', 'adapter', 'receipt', 'command', 'executor']) assert.equal(Object.hasOwn(frame, forbidden), false);
|
||||
assert.equal(frame.receiptAdapterAdmission, null);
|
||||
assert.deepEqual(Object.keys(frame.artifactManifest).sort(), ['manifestSha256', 'schema']);
|
||||
});
|
||||
Reference in new issue
Block a user