mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-06 12:51:54 +00:00
Verify runtime ownership before stop
This commit is contained in:
1 parent
6e79960721
commit
325ed613be
5 files changed
+66
-5
No files matched your search
+24
-3
@@ -1,6 +1,6 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { accessSync, constants, existsSync } from 'node:fs';
|
||||
import { delimiter, join } from 'node:path';
|
||||
import { delimiter, join, resolve } from 'node:path';
|
||||
import { TorchError } from '../kernel/errors.mjs';
|
||||
import { unsupportedCapability, validateRuntimeAdapter } from './runtime.mjs';
|
||||
|
||||
@@ -161,10 +161,31 @@ export class ClaudeRuntimeAdapter {
|
||||
return session ?? { sessionId: id, status: 'offline' };
|
||||
}
|
||||
|
||||
stopSession({ runtimeSessionId } = {}) {
|
||||
stopSession({ runtimeSessionId, worktree } = {}) {
|
||||
const id = text(runtimeSessionId, 'runtimeSessionId');
|
||||
const expectedWorktree = resolve(text(worktree, 'worktree'));
|
||||
const session = this.getStatus({ runtimeSessionId: id });
|
||||
if (session.status === 'offline') {
|
||||
return { runtimeSessionId: id, stopped: true, alreadyOffline: true };
|
||||
}
|
||||
const reportedWorktree = session.cwd ?? session.worktree
|
||||
?? session.workingDirectory ?? session.working_directory;
|
||||
if (typeof reportedWorktree !== 'string' || !reportedWorktree.trim()) {
|
||||
throw new TorchError('Claude session stop refused because its working directory is unavailable', {
|
||||
code: 'RUNTIME_OWNERSHIP_UNVERIFIED', details: { runtimeSessionId: id, expectedWorktree },
|
||||
});
|
||||
}
|
||||
if (resolve(reportedWorktree) !== expectedWorktree) {
|
||||
throw new TorchError('Claude session stop refused because its working directory does not match the managed identity', {
|
||||
code: 'RUNTIME_OWNERSHIP_MISMATCH',
|
||||
details: { runtimeSessionId: id, expectedWorktree, reportedWorktree: resolve(reportedWorktree) },
|
||||
});
|
||||
}
|
||||
const result = this.run(['stop', id]);
|
||||
return { runtimeSessionId: id, stopped: result.status === undefined || result.status === 0 };
|
||||
return {
|
||||
runtimeSessionId: id, stopped: result.status === undefined || result.status === 0,
|
||||
verifiedWorktree: expectedWorktree, alreadyOffline: false,
|
||||
};
|
||||
}
|
||||
|
||||
captureRuntimeId({ areaId, runtimeSessionId } = {}) {
|
||||
|
||||
+3
-1
@@ -221,7 +221,9 @@ function stopThrough(adapters, action) {
|
||||
if (!adapter) throw new TorchError(`No runtime stopper for ${action.runtime}`, {
|
||||
code: 'RUNTIME_ADAPTER_MISSING', details: { runtime: action.runtime },
|
||||
});
|
||||
return adapter.stopSession({ runtimeSessionId: action.runtimeSessionId });
|
||||
return adapter.stopSession({
|
||||
runtimeSessionId: action.runtimeSessionId, worktree: action.worktree?.path,
|
||||
});
|
||||
}
|
||||
|
||||
function runCandidateAcceptance(candidateRoot, spawn) {
|
||||
|
||||
Reference in new issue
Block a user