063a839790
- Add clone_mode and branch fields to tool_instances - Add ssh_key_id to git_repositories for per-repo SSH key assignment - Implement host-side git cloning with branch selection (default: main) - Mount SSH keys into containers for git operations in clone mode - Add dirty state check on clone-mode instance deletion with confirmation - Update SessionsPage with mount/clone selector, branch input, SSH key display - Add SSH key selector to repository creation form - Add dirty delete confirmation modal with changed files list - Update API schemas and endpoints for new fields - Sync delta specs to main specs (git-repo, tool-instances, repo-clone-mode) - Archive completed OpenSpec change: repo-clone-mode-with-ssh - Document git requirement for custom tool types Quality gates: Frontend typecheck and build passed OpenSpec: repo-clone-mode-with-ssh archived with all tasks complete
102 lines
4.3 KiB
Markdown
102 lines
4.3 KiB
Markdown
## Context
|
|
|
|
Currently, all tool instances bind-mount the host repository path via `{{REPO_PATH}}` substitution in compose templates. The repository model (`GitRepository`) has no SSH key association. The instance model (`ToolInstance`) has no concept of repository access mode.
|
|
|
|
Users want two modes:
|
|
1. **Mount** (current): Live sync with working copy on host
|
|
2. **Clone** (new): Fresh isolated copy with full git history inside the container
|
|
|
|
The SSH key system already exists with encrypted private keys in the database. Keys can be project-scoped or user-scoped.
|
|
|
|
## Goals / Non-Goals
|
|
|
|
**Goals:**
|
|
- Allow per-instance choice between mount and clone mode
|
|
- Support branch selection for clone mode (default: main)
|
|
- Enable git operations inside containers via SSH key mounting
|
|
- Protect against accidental data loss with dirty check on clone deletion
|
|
- Allow SSH key assignment at repository creation and later modification
|
|
|
|
**Non-Goals:**
|
|
- Modifying existing tool type compose templates
|
|
- Installing git in containers (assumes tool images have git or install it)
|
|
- Multiple SSH keys per container
|
|
- Automatic push/pull/sync between host and container
|
|
- Shallow clones (full history only)
|
|
|
|
## Decisions
|
|
|
|
### 1. Host-Side Clone (not in-container)
|
|
|
|
**Decision**: Clone happens on the host before container start, not inside the container.
|
|
|
|
**Rationale**:
|
|
- No changes to compose templates required
|
|
- Works with all existing tool types immediately
|
|
- No need for git/SSH inside every container image
|
|
- Host has direct filesystem access to the clone
|
|
- Easier error handling and rollback
|
|
|
|
**Alternative considered**: In-container clone via command override. Rejected because it requires git in every image, SSH auth setup inside containers, and makes error handling fragile.
|
|
|
|
### 2. SSH Key Mounting via `_modify_compose_file`
|
|
|
|
**Decision**: Inject SSH key volume dynamically at container start time using the existing `_modify_compose_file` helper.
|
|
|
|
**Rationale**:
|
|
- Zero changes to tool type definitions
|
|
- Consistent with how other runtime overrides work (port, command, working_dir, extra_volumes)
|
|
- Mounts the `.ssh/` directory with key + config into container
|
|
|
|
**Implementation**:
|
|
```
|
|
instance_dir/.ssh/
|
|
id_ed25519 (decrypted private key, mode 600)
|
|
id_ed25519.pub (public key)
|
|
config (StrictHostKeyChecking no)
|
|
```
|
|
|
|
Mounted as: `instance_dir/.ssh:/root/.ssh:ro` (or appropriate home dir)
|
|
|
|
### 3. Single SSH Key per Repository
|
|
|
|
**Decision**: The SSH key is stored on `GitRepository` and used for both clone and container access.
|
|
|
|
**Rationale**:
|
|
- Natural association: a repository's clone URL determines which SSH key is needed
|
|
- Simpler UX: one key per repo, not per session
|
|
- Session creation can override (future enhancement) but defaults to repo key
|
|
|
|
### 4. Dirty Check via `git status --short`
|
|
|
|
**Decision**: Check for uncommitted changes using `git status --short` before allowing deletion of clone-mode instances.
|
|
|
|
**Rationale**:
|
|
- Simple and reliable
|
|
- Catches staged, unstaged, and untracked files
|
|
- Fast (local filesystem operation)
|
|
|
|
## Risks / Trade-offs
|
|
|
|
**[Risk] Disk space usage** → Each clone-mode instance duplicates the full repository. Mitigation: Instance deletion removes the clone directory.
|
|
|
|
**[Risk] Clone time for large repos** → Synchronous clone during instance creation may timeout. Mitigation: No timeout on clone operation; consider async clone in future.
|
|
|
|
**[Risk] SSH key permissions in containers** → Some containers run as non-root users. The `.ssh` directory mount needs correct ownership. Mitigation: Mount as read-only; container's entrypoint may need to copy to writable location if needed.
|
|
|
|
**[Risk] Git not installed in custom tool images** → User-defined tool types may not have git. Mitigation: Document requirement; built-in types already have or install git.
|
|
|
|
**[Risk] SSH host key checking** → Cloning from new hosts may fail. Mitigation: SSH config sets `StrictHostKeyChecking no` for clone operations.
|
|
|
|
## Migration Plan
|
|
|
|
1. Run Alembic migrations to add new columns
|
|
2. Existing instances default to `clone_mode='mount'` (no behavior change)
|
|
3. Existing repositories have `ssh_key_id=null` (no behavior change until assigned)
|
|
4. No data migration needed
|
|
|
|
## Open Questions
|
|
|
|
- Should the `.ssh` mount be read-only or writable? (Writable needed if container generates new keys, but we don't support that)
|
|
- Should we support submodules in cloned repos?
|