merge: align dev branch with main

This commit is contained in:
Developer
2026-06-03 08:51:02 +00:00
parent 51a399c775
commit b39d6ce5f4
319 changed files with 30221 additions and 9221 deletions
@@ -0,0 +1,113 @@
# Capability: Config Folders
## Overview
Config Folders are reusable collections of configuration files that can be mounted into tool instances as volumes. They enable users to maintain their preferred settings (dotfiles, IDE configs, etc.) and apply them across all their tool instances.
## Functional Requirements
### FR-1: Folder Creation
- Users can create named config folders
- Each folder has: name, description, default mount path, collection of files
- Folder names must be unique per user
- Files are stored with relative paths (e.g., `.zshrc`, `.config/nvim/init.vim`)
### FR-2: File Management
- Users can add, edit, and delete files within a folder
- File paths are relative to the mount path
- File content is stored as text (UTF-8)
- Maximum total folder size: 10MB
- File paths are sanitized to prevent directory traversal attacks
### FR-3: Activation
- Folders can be toggled active/inactive
- Only active folders are mounted into new instances
- Activation state is persisted
- Changing activation does not affect running instances
### FR-4: Project Overrides
- Users can define per-project overrides for any folder
- Overrides can modify: mount path, add/remove/replace files
- When an instance is created for a project, overrides are applied
- Global settings serve as defaults; overrides are merged
- Deleting an override reverts to global settings
### FR-5: Instance Mounting
- When creating an instance, active folders are resolved
- For each folder: global files + project overrides (if any)
- Files are written to `instance_dir/volumes/<folder_name>/`
- Compose file includes volume mounts from these directories
- Mount target is the folder's mount path (or override)
## Data Model
```python
class ConfigFolder:
id: UUID
user_id: UUID
name: str # Unique per user
description: str | None
mount_path: str # e.g., "/home/user"
files: dict[str, str] # {"relative/path": "content", ...}
project_overrides: dict # {"project_id": {"mount_path": "...", "files": {...}}}
is_active: bool
created_at: datetime
updated_at: datetime
```
## API Endpoints
- `GET /config-folders` - List user's folders
- `POST /config-folders` - Create folder
- `PUT /config-folders/{id}` - Update folder
- `DELETE /config-folders/{id}` - Delete folder
- `POST /config-folders/{id}/overrides` - Add override
- `PUT /config-folders/{id}/overrides/{project_id}` - Update override
- `DELETE /config-folders/{id}/overrides/{project_id}` - Remove override
## Validation Rules
1. **Name uniqueness**: `(user_id, name)` must be unique
2. **Path sanitization**: File paths cannot contain `..` or start with `/`
3. **Size limit**: Total folder size (sum of all file contents) ≤ 10MB
4. **Mount path**: Must be absolute path (starts with `/`)
5. **Project existence**: Overrides can only reference existing projects
## Example Usage
### Global Config Folder
```json
{
"name": "my-dotfiles",
"description": "Personal shell and git configuration",
"mount_path": "/home/user",
"files": {
".zshrc": "export ZSH=\"$HOME/.oh-my-zsh\"\n...",
".gitconfig": "[user]\nname = John Doe\n...",
".config/starship.toml": "[character]\n..."
},
"is_active": true
}
```
### Project Override
```json
{
"project_id": "550e8400-e29b-41d4-a716-446655440000",
"mount_path": "/workspace",
"files": {
".gitconfig": "[user]\nname = Work Account\n..."
}
}
```
## Acceptance Criteria
- [ ] User can create a config folder with multiple files
- [ ] Files are correctly mounted into new instances
- [ ] Project overrides apply correctly
- [ ] 10MB size limit is enforced
- [ ] Path traversal attacks are prevented
- [ ] Only active folders are mounted
- [ ] Changing folder contents updates future instances
- [ ] UI shows folder size and file count