# 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//` - 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