mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-11 13:24:55 +01:00
Authenticate Boat initial checkouts with run-scoped Git credentials
Pass the existing workspace credential provider through computer realization separately from durable metadata, and supply its URL-scoped helper only to the clone subprocess. Verify authenticated clone behavior and credential non-retention. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
25c12848a2
commit
03542b0845
9 files changed
+87
-6
No files matched your search
@@ -77,11 +77,12 @@ export function createComputerEnvironmentDriver(db: Db): EnvironmentRuntimeDrive
|
||||
if (!result.retired) throw new Error("computer_owner_retirement_superseded");
|
||||
return { providerLeaseId: lease.providerLeaseId, state: "stopped" };
|
||||
},
|
||||
async realizeWorkspace({ lease, workspace }) {
|
||||
async realizeWorkspace({ lease, workspace, gitAuth }) {
|
||||
const request = workspace.metadata?.workspaceRealizationRequest as { source?: { projectId?: string; repoUrl?: string; repoRef?: string; branchName?: string; strategy?: string }; issueId?: string } | undefined;
|
||||
const result = await computers.realizeWorkspace({ ...scope(lease), owner: computerOwnerFromLease(lease),
|
||||
projectId: request?.source?.projectId ?? undefined, taskId: request?.issueId ?? undefined,
|
||||
repositoryUrl: request?.source?.repoUrl ?? undefined,
|
||||
gitAuth,
|
||||
branch: request?.source?.branchName ?? request?.source?.repoRef ?? undefined,
|
||||
baseRef: request?.source?.repoRef ?? undefined,
|
||||
mode: request?.source?.strategy === "git_worktree" ? "worktree" : "shared" });
|
||||
|
||||
@@ -51,6 +51,7 @@ import { buildWorkspaceRealizationRequest } from "./workspace-realization.js";
|
||||
import { executionWorkspaceService } from "./execution-workspaces.js";
|
||||
import { logActivity } from "./activity-log.js";
|
||||
import { logger } from "../middleware/logger.js";
|
||||
import type { GitRemoteAuthProvider } from "./git-credentials.js";
|
||||
import { parseObject } from "../adapters/utils.js";
|
||||
import type { RealizedExecutionWorkspace } from "./workspace-runtime.js";
|
||||
import type { PluginWorkerManager } from "./plugin-worker-manager.js";
|
||||
@@ -393,6 +394,8 @@ export function environmentRunOrchestrator(
|
||||
* target. Absent keeps the safe no-op default in the bridge.
|
||||
*/
|
||||
duplexObservabilityRecorder?: DuplexObservabilityRecorder | null;
|
||||
/** Run-scoped auth for initial persistent checkouts; never persisted as workspace metadata. */
|
||||
resolveGitAuth?: GitRemoteAuthProvider;
|
||||
}): Promise<EnvironmentRealizationResult> {
|
||||
const {
|
||||
environment,
|
||||
@@ -430,6 +433,9 @@ export function environmentRunOrchestrator(
|
||||
const workspaceRealizationResult = await environmentRuntime.realizeWorkspace({
|
||||
environment,
|
||||
lease,
|
||||
gitAuth: environment.driver === "computer" && workspaceRealizationRequest.source.repoUrl
|
||||
? await input.resolveGitAuth?.(workspaceRealizationRequest.source.repoUrl) ?? undefined
|
||||
: undefined,
|
||||
workspace: {
|
||||
localPath: executionWorkspace.cwd,
|
||||
remotePath: remoteCwd,
|
||||
|
||||
@@ -526,6 +526,8 @@ export interface EnvironmentDriverLeaseInput {
|
||||
}
|
||||
|
||||
export interface EnvironmentDriverRealizeWorkspaceInput extends EnvironmentDriverLeaseInput {
|
||||
/** Ephemeral authentication for the initial checkout, excluded from durable metadata. */
|
||||
gitAuth?: { configArgs: string[]; env: Record<string, string> };
|
||||
workspace: {
|
||||
localPath?: string;
|
||||
remotePath?: string;
|
||||
|
||||
@@ -4529,6 +4529,7 @@ export function heartbeatService(
|
||||
effectiveExecutionWorkspaceMode,
|
||||
persistedExecutionWorkspace,
|
||||
duplexObservabilityRecorder,
|
||||
resolveGitAuth: workspaceGitAuthProvider,
|
||||
});
|
||||
nativeRunnerPreparationSpans.push({
|
||||
name: "environment.workspace.realize",
|
||||
|
||||
Reference in new issue
Block a user