Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions packages/server/src/api-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,73 @@ import type {

export type WorkspaceStatus = "starting" | "ready" | "stopped" | "error"

export type ExecutionProfileKind = "local" | "wsl" | "docker" | "command" | "ssh"
export type ExecutionProfileCwdMode = "workspace" | "inherit"

export interface ExecutionProfileBase {
id: string
name: string
kind: ExecutionProfileKind
}

export interface LocalExecutionProfile extends ExecutionProfileBase {
kind: "local"
binaryPath: string
}

export interface WslExecutionProfile extends ExecutionProfileBase {
kind: "wsl"
distro: string
binaryPath: string
}

export interface DockerExecutionProfile extends ExecutionProfileBase {
kind: "docker"
image: string
workspaceMountPath: string
configMountPath: string
command?: string[]
extraDockerArgs?: string[]
}

export interface CommandExecutionProfile extends ExecutionProfileBase {
kind: "command"
executable: string
args?: string[]
cwdMode?: ExecutionProfileCwdMode
}

export interface SshExecutionProfile extends ExecutionProfileBase {
kind: "ssh"
host: string
port?: number
username?: string
remotePath: string
binaryPath: string
args?: string[]
}

export type ExecutionProfile = LocalExecutionProfile | WslExecutionProfile | DockerExecutionProfile | CommandExecutionProfile | SshExecutionProfile

export interface ExecutionProfilePreviewRequest {
profile: ExecutionProfile
workspacePath?: string
}

export interface ExecutionProfilePreviewResponse {
command: string
args: string[]
commandLine: string
cwd?: string
environment: Record<string, string>
}

export interface ExecutionProfileTestResponse extends ExecutionProfilePreviewResponse {
valid: boolean
version?: string
error?: string
}

export interface WorkspaceDescriptor {
id: string
/** Absolute path on the server host. */
Expand All @@ -29,6 +96,9 @@ export interface WorkspaceDescriptor {
binaryId: string
binaryLabel: string
binaryVersion?: string
executionProfileId?: string
executionProfileName?: string
executionProfileKind?: ExecutionProfileKind
createdAt: string
updatedAt: string
/** Present when `status` is "error". */
Expand All @@ -38,6 +108,7 @@ export interface WorkspaceDescriptor {
export interface WorkspaceCreateRequest {
path: string
name?: string
executionProfileId?: string
}

export interface WorkspaceCloneRequest {
Expand Down
17 changes: 14 additions & 3 deletions packages/server/src/server/http-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ interface HttpServerStartResult {
displayHost: string
}

function redactSensitivePayload(value: unknown): unknown {
if (!value || typeof value !== "object") return value
if (Array.isArray(value)) return value.map(redactSensitivePayload)
const output: Record<string, unknown> = {}
for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {
output[key] = /(PASSWORD|TOKEN|SECRET|API[_-]?KEY)/i.test(key) ? "[REDACTED]" : redactSensitivePayload(entry)
}
return output
}

export function createHttpServer(deps: HttpServerDeps) {
// Fastify's type-level RawServer inference gets noisy when toggling HTTP vs HTTPS.
// We keep the runtime behavior correct and cast the instance to a generic FastifyInstance.
Expand Down Expand Up @@ -115,7 +125,8 @@ export function createHttpServer(deps: HttpServerDeps) {
}
apiLogger.debug(base, "HTTP request completed")
if (apiLogger.isLevelEnabled("trace")) {
apiLogger.trace({ ...base, params: request.params, query: request.query, body: request.body }, "HTTP request payload")
const body = redactSensitivePayload(request.body)
apiLogger.trace({ ...base, params: request.params, query: request.query, body }, "HTTP request payload")
}
done()
})
Expand Down Expand Up @@ -623,7 +634,7 @@ async function proxyWorkspaceRequest(args: {

logger.debug({ workspaceId, method: request.method, targetUrl }, "Proxying request to instance")
if (logger.isLevelEnabled("trace")) {
logger.trace({ workspaceId, targetUrl, body: request.body }, "Instance proxy payload")
logger.trace({ workspaceId, targetUrl, body: redactSensitivePayload(request.body) }, "Instance proxy payload")
}

return reply.from(targetUrl, {
Expand Down Expand Up @@ -661,7 +672,7 @@ async function proxyWorkspaceRequest(args: {
worktreeSlug,
directory,
contentType: request.headers["content-type"],
body: bodyToJson(request.body),
body: redactSensitivePayload(bodyToJson(request.body)),
headers: outgoing,
},
"Proxy -> OpenCode request",
Expand Down
Loading