# Config Profiles

## Overview

Config profiles allow users to define reusable configuration sets for tool instances. Profiles can include environment variables, files, mounts, and git repository mounts. They support profile includes for composition and can be scoped to specific projects or tool types.

## Git Mounts

Git mounts allow you to mount files or directories from git repositories into tool instances at startup.

### Git Mount Object

```json
{
  "repo_id": "550e8400-e29b-41d4-a716-446655440000",
  "source_path": ".",
  "target_path": "/app/config",
  "branch": "main"
}
```

**Fields:**

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `repo_id` | string (UUID) | Yes | ID of the git repository to mount from |
| `source_path` | string | No | Path within the repository (default: "."). Supports glob patterns like "*.json" or "configs/**" |
| `target_path` | string | Yes | Absolute path inside the container where files will be mounted |
| `branch` | string | No | Branch or tag to checkout before mounting (default: current branch) |

### Path Validation

- `source_path`: Must be relative (no leading `/`). Cannot contain `..` (path traversal)
- `target_path`: Must be absolute (starts with `/`). Cannot contain `..`

### Glob Patterns

The `source_path` supports standard glob patterns:

- `*.json` - Match all JSON files in root
- `configs/**` - Match all files in configs directory recursively
- `src/*.py` - Match all Python files in src directory
- `.` - Mount entire repository (default)

**Limits:**
- Maximum 100 matches per glob pattern
- Only matches within the repository boundary

### Branch Behavior

When a `branch` is specified:

1. System attempts to checkout the branch in the existing clone
2. If branch doesn't exist locally, attempts to fetch from remote and checkout
3. If checkout fails, logs warning and continues with current branch
4. No branch specified: uses current checked-out branch

**Auto-clone:** If repository is not cloned locally, the system will automatically clone it using the repository's configured SSH key.

## Endpoints

### List Config Profiles

```
GET /config-profiles
```

Query parameters:
- `project_id` (optional): Filter by project compatibility
- `tool_type_id` (optional): Filter by tool type compatibility

Response includes `git_mounts` array in each profile.

### Create Config Profile

```
POST /config-profiles
```

Request body:
```json
{
  "name": "My Profile",
  "git_mounts": [
    {
      "repo_id": "550e8400-e29b-41d4-a716-446655440000",
      "source_path": "configs/*.json",
      "target_path": "/app/config",
      "branch": "main"
    }
  ]
}
```

Validation:
- All referenced repositories must exist
- Repositories must belong to the same project (if profile has project_id)
- source_path and target_path must pass path validation

### Update Config Profile

```
PUT /config-profiles/{id}
```

Same request body as create. Partial updates supported (omit fields to keep current values).

### Preview Resolved Profile

```
GET /config-profiles/{id}/preview
```

Returns the fully resolved profile with all includes merged. Git mounts from included profiles are merged with override rules (later profiles override earlier ones with same repo_id + target_path combo).

Response:
```json
{
  "profile_id": "550e8400-e29b-41d4-a716-446655440000",
  "profile_name": "My Profile",
  "env_vars": {},
  "runtime_hints": {},
  "mounts": [],
  "git_mounts": [
    {
      "repo_id": "550e8400-e29b-41d4-a716-446655440000",
      "source_path": "configs/*.json",
      "target_path": "/app/config",
      "branch": "main"
    }
  ],
  "files": {},
  "overrides": {
    "env_vars": {},
    "runtime_hints": {},
    "files": {},
    "mounts": {}
  },
  "included_profiles": []
}
```

## Error Handling

Git mount errors during instance startup are non-blocking:
- Missing repository: Mount skipped, warning logged
- Clone failure: Mount skipped, warning logged
- Invalid paths: Mount skipped, warning logged
- Branch checkout failure: Falls back to current branch, warning logged

Instance startup continues normally even if some git mounts fail.

## Profile Resolution

When a profile includes other profiles, git mounts are merged:
- Same `repo_id` + `target_path` combo: later profile overrides
- Different combos: both are kept
- Branch conflicts: later profile wins

Example:
```
Base Profile:     git_mounts = [{repo_a, /app, main}]
Included Profile: git_mounts = [{repo_a, /app, develop}, {repo_b, /data}]
Resolved:         git_mounts = [{repo_a, /app, develop}, {repo_b, /data}]
```
