Skip to content
7 changes: 5 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ RUN useradd -m -s /bin/bash dev
# sshd runtime dir
RUN mkdir -p /run/sshd

# Harden sshd: disable password auth and root login
# sshd: password auth enabled so users can connect without key setup
RUN printf "%s\n" \
"PasswordAuthentication no" \
"PasswordAuthentication yes" \
"PermitRootLogin no" \
"PubkeyAuthentication yes" \
"AllowUsers dev" \
> /etc/ssh/sshd_config.d/dev.conf

# Default password = username (works out of the box; key auth still accepted if authorized_keys provided)
RUN echo "dev:dev" | chpasswd

# Workspace in dev home
RUN mkdir -p /home/dev/app && chown -R dev:dev /home/dev

Expand Down
17 changes: 16 additions & 1 deletion docker-compose.api.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
services:
dind:
image: docker:27-dind
container_name: docker-git-dind
privileged: true
environment:
DOCKER_TLS_CERTDIR: ""
volumes:
- docker-git-dind-storage:/var/lib/docker
restart: unless-stopped

api:
build:
context: .
Expand All @@ -9,9 +19,14 @@ services:
DOCKER_GIT_PROJECTS_ROOT: ${DOCKER_GIT_PROJECTS_ROOT:-/home/dev/.docker-git}
DOCKER_GIT_FEDERATION_PUBLIC_ORIGIN: ${DOCKER_GIT_FEDERATION_PUBLIC_ORIGIN:-}
DOCKER_GIT_FEDERATION_ACTOR: ${DOCKER_GIT_FEDERATION_ACTOR:-docker-git}
DOCKER_HOST: tcp://dind:2375
ports:
- "${DOCKER_GIT_API_BIND_HOST:-127.0.0.1}:${DOCKER_GIT_API_PORT:-3334}:${DOCKER_GIT_API_PORT:-3334}"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${DOCKER_GIT_PROJECTS_ROOT_HOST:-/home/dev/.docker-git}:${DOCKER_GIT_PROJECTS_ROOT:-/home/dev/.docker-git}
depends_on:
- dind
restart: unless-stopped

volumes:
docker-git-dind-storage:
115 changes: 115 additions & 0 deletions packages/api/src/api/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,118 @@ export type ApiEvent = {
readonly at: string
readonly payload: unknown
}

// Auth
export type AuthStatusResponse = { readonly message: string }

export type AuthGithubLoginRequest = {
readonly label?: string | null | undefined
readonly token?: string | null | undefined
readonly scopes?: string | null | undefined
readonly envGlobalPath: string
}

export type AuthGithubStatusRequest = {
readonly envGlobalPath: string
}

export type AuthGithubLogoutRequest = {
readonly label?: string | null | undefined
readonly envGlobalPath: string
}

export type AuthCodexLoginRequest = {
readonly label?: string | null | undefined
readonly codexAuthPath: string
}

export type AuthCodexStatusRequest = {
readonly label?: string | null | undefined
readonly codexAuthPath: string
}

export type AuthCodexLogoutRequest = {
readonly label?: string | null | undefined
readonly codexAuthPath: string
}

export type AuthClaudeLoginRequest = {
readonly label?: string | null | undefined
readonly claudeAuthPath: string
}

export type AuthClaudeStatusRequest = {
readonly label?: string | null | undefined
readonly claudeAuthPath: string
}

export type AuthClaudeLogoutRequest = {
readonly label?: string | null | undefined
readonly claudeAuthPath: string
}

// State
export type StateInitRequest = {
readonly repoUrl: string
readonly repoRef?: string | undefined
}

export type StateCommitRequest = {
readonly message: string
}

export type StateSyncRequest = {
readonly message?: string | null | undefined
}

export type StatePathResponse = { readonly path: string }

export type StateOutputResponse = { readonly output: string }

// Scrap
export type ScrapExportRequest = {
readonly projectDir: string
readonly archivePath?: string | undefined
}

export type ScrapImportRequest = {
readonly projectDir: string
readonly archivePath: string
readonly wipe?: boolean | undefined
}

// Sessions
export type SessionsListRequest = {
readonly projectDir: string
readonly includeDefault?: boolean | undefined
}

export type SessionsKillRequest = {
readonly projectDir: string
readonly pid: number
}

export type SessionsLogsRequest = {
readonly projectDir: string
readonly pid: number
readonly lines?: number | undefined
}

export type SessionsOutput = { readonly output: string }

// MCP Playwright
export type McpPlaywrightUpRequest = {
readonly projectDir: string
readonly runUp?: boolean | undefined
}

// Apply (project config)
export type ApplyRequest = {
readonly runUp?: boolean | undefined
readonly gitTokenLabel?: string | undefined
readonly codexTokenLabel?: string | undefined
readonly claudeTokenLabel?: string | undefined
readonly cpuLimit?: string | undefined
readonly ramLimit?: string | undefined
readonly enableMcpPlaywright?: boolean | undefined
}
101 changes: 101 additions & 0 deletions packages/api/src/api/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,104 @@ export const AgentLogLineSchema = Schema.Struct({
export type CreateProjectRequestInput = Schema.Schema.Type<typeof CreateProjectRequestSchema>
export type CreateAgentRequestInput = Schema.Schema.Type<typeof CreateAgentRequestSchema>
export type CreateFollowRequestInput = Schema.Schema.Type<typeof CreateFollowRequestSchema>

export const AuthGithubLoginRequestSchema = Schema.Struct({
label: Schema.optional(Schema.NullOr(Schema.String)),
token: Schema.optional(Schema.NullOr(Schema.String)),
scopes: Schema.optional(Schema.NullOr(Schema.String)),
envGlobalPath: Schema.String
})

export const AuthGithubStatusRequestSchema = Schema.Struct({
envGlobalPath: Schema.String
})

export const AuthGithubLogoutRequestSchema = Schema.Struct({
label: Schema.optional(Schema.NullOr(Schema.String)),
envGlobalPath: Schema.String
})

export const AuthCodexLoginRequestSchema = Schema.Struct({
label: Schema.optional(Schema.NullOr(Schema.String)),
codexAuthPath: Schema.String
})

export const AuthCodexStatusRequestSchema = Schema.Struct({
label: Schema.optional(Schema.NullOr(Schema.String)),
codexAuthPath: Schema.String
})

export const AuthCodexLogoutRequestSchema = Schema.Struct({
label: Schema.optional(Schema.NullOr(Schema.String)),
codexAuthPath: Schema.String
})

export const AuthClaudeLoginRequestSchema = Schema.Struct({
label: Schema.optional(Schema.NullOr(Schema.String)),
claudeAuthPath: Schema.String
})

export const AuthClaudeStatusRequestSchema = Schema.Struct({
label: Schema.optional(Schema.NullOr(Schema.String)),
claudeAuthPath: Schema.String
})

export const AuthClaudeLogoutRequestSchema = Schema.Struct({
label: Schema.optional(Schema.NullOr(Schema.String)),
claudeAuthPath: Schema.String
})

export const StateInitRequestSchema = Schema.Struct({
repoUrl: Schema.String,
repoRef: OptionalString
})

export const StateCommitRequestSchema = Schema.Struct({
message: Schema.String
})

export const StateSyncRequestSchema = Schema.Struct({
message: Schema.optional(Schema.NullOr(Schema.String))
})

export const ScrapExportRequestSchema = Schema.Struct({
projectDir: Schema.String,
archivePath: OptionalString
})

export const ScrapImportRequestSchema = Schema.Struct({
projectDir: Schema.String,
archivePath: Schema.String,
wipe: OptionalBoolean
})

export const SessionsListRequestSchema = Schema.Struct({
projectDir: Schema.String,
includeDefault: OptionalBoolean
})

export const SessionsKillRequestSchema = Schema.Struct({
projectDir: Schema.String,
pid: Schema.Number
})

export const SessionsLogsRequestSchema = Schema.Struct({
projectDir: Schema.String,
pid: Schema.Number,
lines: Schema.optional(Schema.Number)
})

export const McpPlaywrightUpRequestSchema = Schema.Struct({
projectDir: Schema.String,
runUp: OptionalBoolean
})

export const ApplyRequestSchema = Schema.Struct({
runUp: OptionalBoolean,
gitTokenLabel: OptionalString,
codexTokenLabel: OptionalString,
claudeTokenLabel: OptionalString,
cpuLimit: OptionalString,
ramLimit: OptionalString,
enableMcpPlaywright: OptionalBoolean
})
Loading
Loading