Skip to content

Latest commit

 

History

History
97 lines (72 loc) · 3.75 KB

File metadata and controls

97 lines (72 loc) · 3.75 KB

Project Management

Overview

In cloud mode, projects represent git repositories cloned on the runner. Each project goes through a lifecycle from cloning to ready, and serves as the parent for terminal sessions that execute in Docker containers with the project's code.

State Machine

POST /api/v1/projects
       │
       ▼
   ┌────────┐     clone success     ┌───────┐
   │Cloning │ ──────────────────── ▶│ Ready │
   └────────┘                       └───────┘
       │                                │
       │ clone failure                  │ DELETE
       ▼                                ▼
   ┌────────┐     POST /retry       (removed)
   │ Failed │ ──────────────┐
   └────────┘               │
       ▲                    │
       │   clone failure    │
       └────────────────────┘

States:

  • Cloninggit clone is in progress
  • Ready — clone complete, sessions can be created
  • Failed — clone failed; clone_error field contains the error message. Can be retried.

REST API

See REST API for full endpoint documentation. Summary:

Endpoint Method Description
/api/v1/projects POST Create project (starts clone)
/api/v1/projects GET List all projects
/api/v1/projects/{id} GET Get project by ID
/api/v1/projects/{id} DELETE Delete project
/api/v1/projects/{id}/retry POST Retry failed clone

Git Operations

All git operations use tokio::process::Command for async execution (see ADR-004).

Clone

  • Runs git clone with progress reporting via the event bus
  • Timeout configurable via git.clone_timeout_secs (default: 300s)
  • Clone progress emitted as CloneProgress events via SSE

Worktrees

Each session gets its own git worktree created from the project's clone. This provides isolation — multiple sessions can work on different branches of the same repository without interference.

SSRF Validation

Every git URL is validated before any network activity:

  1. Scheme check — only https:// is accepted
  2. Host parsing — extracts hostname, handles IPv4, IPv6, and bracketed literals
  3. Private IP rejection — blocks:
    • 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
    • IPv6 loopback (::1), link-local, unique-local
    • localhost, 0.0.0.0
  4. DNS resolution check — resolves hostname and verifies all resolved IPs are public
  5. Allowlist — if git.allowed_hosts is non-empty, only listed hosts are permitted

Source: runner/src/project_manager.rs

Persistence

Projects are stored in SQLite via the Store layer. Fields:

Field Type Description
id UUID Primary key
name String Human-readable name
git_url String Repository URL
local_path String Path to local clone
state Enum Cloning / Ready / Failed
clone_error String? Error message when Failed
created_at DateTime Creation timestamp
updated_at DateTime Last state change
deleted_at DateTime? Soft-delete timestamp

Source: runner/src/store.rs

Event Bus Integration

State changes emit RelayEvent::ProjectStateChanged events, which are:

  • Broadcast to all SSE subscribers
  • Buffered in the ring buffer for reconnect replay

Clone progress emits RelayEvent::CloneProgress with percentage and status message.