diff --git a/packages/cli/src/serve/routes/workspace-git-branches.ts b/packages/cli/src/serve/routes/workspace-git-branches.ts index bdd78a81cbf..4d4a3f35bb5 100644 --- a/packages/cli/src/serve/routes/workspace-git-branches.ts +++ b/packages/cli/src/serve/routes/workspace-git-branches.ts @@ -18,31 +18,17 @@ import { } from '@qwen-code/qwen-code-core'; import type { SendBridgeError } from '../server/error-response.js'; import { safeBody } from '../server/request-helpers.js'; -import type { - WorkspaceRegistry, - WorkspaceRuntime, -} from '../workspace-registry.js'; +import type { WorkspaceRegistry } from '../workspace-registry.js'; import { - requireTrustedWorkspaceRuntime, resolveContainedCwd, resolveContainedCwdOrFail, - resolveWorkspaceRuntimeFromParam, + resolveTrustedRuntime, sendGenerationClosedError, sendUntrustedWorkspaceResponse, } from '../workspace-route-runtime.js'; const GIT_ERROR_MESSAGE_MAX = 512; -function resolveTrustedRuntime( - registry: WorkspaceRegistry, - req: Request, - res: Response, -): WorkspaceRuntime | null { - const runtime = resolveWorkspaceRuntimeFromParam(registry, req, res); - if (!runtime) return null; - return requireTrustedWorkspaceRuntime(runtime, res) ? runtime : null; -} - function sendGitError( res: Response, err: unknown, diff --git a/packages/cli/src/serve/routes/workspace-git-diff.ts b/packages/cli/src/serve/routes/workspace-git-diff.ts index 2956d51468b..8d2ad624922 100644 --- a/packages/cli/src/serve/routes/workspace-git-diff.ts +++ b/packages/cli/src/serve/routes/workspace-git-diff.ts @@ -12,14 +12,10 @@ import { type GitDiffResult, } from '@qwen-code/qwen-code-core'; import type { SendBridgeError } from '../server/error-response.js'; -import type { - WorkspaceRegistry, - WorkspaceRuntime, -} from '../workspace-registry.js'; +import type { WorkspaceRegistry } from '../workspace-registry.js'; import { - requireTrustedWorkspaceRuntime, resolveContainedCwd, - resolveWorkspaceRuntimeFromParam, + resolveTrustedRuntime, sendUntrustedWorkspaceResponse, } from '../workspace-route-runtime.js'; import { applyReadHeaders } from './workspace-file-read.js'; @@ -200,16 +196,6 @@ export function registerWorkspaceGitDiffRoutes( }); } -function resolveTrustedRuntime( - registry: WorkspaceRegistry, - req: Request, - res: Response, -): WorkspaceRuntime | null { - const runtime = resolveWorkspaceRuntimeFromParam(registry, req, res); - if (!runtime) return null; - return requireTrustedWorkspaceRuntime(runtime, res) ? runtime : null; -} - export function registerWorkspaceQualifiedGitDiffRoutes( app: Application, deps: { diff --git a/packages/cli/src/serve/routes/workspace-git-log.ts b/packages/cli/src/serve/routes/workspace-git-log.ts index 0160130cd61..99b0ebbe110 100644 --- a/packages/cli/src/serve/routes/workspace-git-log.ts +++ b/packages/cli/src/serve/routes/workspace-git-log.ts @@ -14,14 +14,10 @@ import { type GitCommitDetail, } from '@qwen-code/qwen-code-core'; import type { SendBridgeError } from '../server/error-response.js'; -import type { - WorkspaceRegistry, - WorkspaceRuntime, -} from '../workspace-registry.js'; +import type { WorkspaceRegistry } from '../workspace-registry.js'; import { - requireTrustedWorkspaceRuntime, resolveContainedCwd, - resolveWorkspaceRuntimeFromParam, + resolveTrustedRuntime, } from '../workspace-route-runtime.js'; import { applyReadHeaders } from './workspace-file-read.js'; @@ -179,16 +175,6 @@ export function registerWorkspaceGitLogRoutes( }); } -function resolveTrustedRuntime( - registry: WorkspaceRegistry, - req: Request, - res: Response, -): WorkspaceRuntime | null { - const runtime = resolveWorkspaceRuntimeFromParam(registry, req, res); - if (!runtime) return null; - return requireTrustedWorkspaceRuntime(runtime, res) ? runtime : null; -} - export function registerWorkspaceQualifiedGitLogRoutes( app: Application, deps: { diff --git a/packages/cli/src/serve/routes/workspace-git.ts b/packages/cli/src/serve/routes/workspace-git.ts index c658134350d..d4f4b18bfbc 100644 --- a/packages/cli/src/serve/routes/workspace-git.ts +++ b/packages/cli/src/serve/routes/workspace-git.ts @@ -4,19 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { Application, Request, Response } from 'express'; +import type { Application } from 'express'; import { getGitWorkingTreeStatus } from '@qwen-code/qwen-code-core'; import type { AcpSessionBridge } from '../acp-session-bridge.js'; import type { SendBridgeError } from '../server/error-response.js'; import type { WorkspaceGitState } from '../workspace-git-state.js'; -import type { - WorkspaceRegistry, - WorkspaceRuntime, -} from '../workspace-registry.js'; +import type { WorkspaceRegistry } from '../workspace-registry.js'; import { - requireTrustedWorkspaceRuntime, resolveContainedCwd, - resolveWorkspaceRuntimeFromParam, + resolveTrustedRuntime, sendUntrustedWorkspaceResponse, } from '../workspace-route-runtime.js'; @@ -60,16 +56,6 @@ export function registerWorkspaceGitRoutes( }); } -function resolveTrustedRuntime( - registry: WorkspaceRegistry, - req: Request, - res: Response, -): WorkspaceRuntime | null { - const runtime = resolveWorkspaceRuntimeFromParam(registry, req, res); - if (!runtime) return null; - return requireTrustedWorkspaceRuntime(runtime, res) ? runtime : null; -} - export function registerWorkspaceQualifiedGitRoutes( app: Application, deps: { diff --git a/packages/cli/src/serve/routes/workspace-status.ts b/packages/cli/src/serve/routes/workspace-status.ts index f4e968f2123..9cb18ff16a7 100644 --- a/packages/cli/src/serve/routes/workspace-status.ts +++ b/packages/cli/src/serve/routes/workspace-status.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { Application, Request, RequestHandler, Response } from 'express'; +import type { Application, RequestHandler } from 'express'; import type { AcpSessionBridge } from '../acp-session-bridge.js'; import type { SendBridgeError } from '../server/error-response.js'; import { @@ -12,10 +12,7 @@ import { MAX_SERVER_NAME_LENGTH, } from '../server/request-helpers.js'; import type { DaemonWorkspaceService } from '../workspace-service/index.js'; -import { - requireTrustedWorkspaceRuntime, - resolveWorkspaceRuntimeFromParam, -} from '../workspace-route-runtime.js'; +import { resolveTrustedRuntime } from '../workspace-route-runtime.js'; import type { WorkspaceRegistry, WorkspaceRuntime, @@ -229,16 +226,6 @@ export function registerWorkspaceStatusRoutes( }); } -function resolveTrustedRuntime( - registry: WorkspaceRegistry, - req: Request, - res: Response, -): WorkspaceRuntime | null { - const runtime = resolveWorkspaceRuntimeFromParam(registry, req, res); - if (!runtime) return null; - return requireTrustedWorkspaceRuntime(runtime, res) ? runtime : null; -} - export function registerWorkspaceQualifiedStatusRoutes( app: Application, deps: Pick & { diff --git a/packages/cli/src/serve/workspace-route-runtime.test.ts b/packages/cli/src/serve/workspace-route-runtime.test.ts index cbbe2fab2e3..14337c630b6 100644 --- a/packages/cli/src/serve/workspace-route-runtime.test.ts +++ b/packages/cli/src/serve/workspace-route-runtime.test.ts @@ -18,6 +18,7 @@ import { resolveContainedCwd, resolveContainedCwdOrFail, resolveRegisteredWorkspaceRuntimeByPathSelector, + resolveTrustedRuntime, resolveWorkspaceRuntimeFromParam, resolveWorkspaceRuntimeWithLiveCompatibilityFromParam, } from './workspace-route-runtime.js'; @@ -244,6 +245,44 @@ describe('resolveWorkspaceRuntimeFromParam', () => { }); }); +describe('resolveTrustedRuntime', () => { + it('returns an active trusted runtime', () => { + const runtime = makeRuntime(); + const registry = createSingleWorkspaceRegistry(runtime); + + expect( + resolveTrustedRuntime( + registry, + { + params: { workspace: runtime.workspaceId }, + } as unknown as Request, + makeResponse(), + ), + ).toBe(runtime); + }); + + it('rejects an active untrusted runtime', () => { + const runtime = { ...makeRuntime(), trusted: false }; + const registry = createSingleWorkspaceRegistry(runtime); + const response = makeResponse(); + + expect( + resolveTrustedRuntime( + registry, + { + params: { workspace: runtime.workspaceId }, + } as unknown as Request, + response, + ), + ).toBeNull(); + expect(response.status).toHaveBeenCalledWith(403); + expect(response.json).toHaveBeenCalledWith({ + error: 'Workspace is not trusted.', + code: 'untrusted_workspace', + }); + }); +}); + describe('resolveWorkspaceRuntimeWithLiveCompatibilityFromParam', () => { function setup() { const primary = makeRuntime(); diff --git a/packages/cli/src/serve/workspace-route-runtime.ts b/packages/cli/src/serve/workspace-route-runtime.ts index 2cd5577c442..eee319039a3 100644 --- a/packages/cli/src/serve/workspace-route-runtime.ts +++ b/packages/cli/src/serve/workspace-route-runtime.ts @@ -176,6 +176,22 @@ export function resolveWorkspaceRuntimeFromParam( return runtime; } +export function resolveTrustedRuntime( + registry: WorkspaceRegistry, + req: Request, + res: Response, + paramName = 'workspace', +): WorkspaceRuntime | null { + const runtime = resolveWorkspaceRuntimeFromParam( + registry, + req, + res, + paramName, + ); + if (!runtime) return null; + return requireTrustedWorkspaceRuntime(runtime, res) ? runtime : null; +} + export function resolveWorkspaceRuntimeWithLiveCompatibilityFromParam( registry: WorkspaceRegistry, req: Request,