feat: add config profiles data model and migrations
- Add ConfigProfile model with user ownership, name, description - Add ConfigInclude model for ordered profile self-references - Add ConfigMount model for mount/file definitions - Add selected_profile_id to ToolInstance for per-instance profile selection - Add default profile properties to UserConfig JSONB config - Create Alembic migration 0013 for new tables and columns - Register new models in models/__init__.py - Mark config_folders.is_active as deprecated - Add migration metadata test Quality gates: syntax check passed (all files parse successfully) OpenSpec: add-config-profiles task 1.1
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-24
|
||||
@@ -0,0 +1,45 @@
|
||||
## Context
|
||||
|
||||
The current system uses `config_folders` with a flat `files` JSONB and an `is_active` flag for auto-mounting at tool launch time. This design is inflexible: only one folder can be active, there's no ordering of includes, no explicit per-tool-instance selection, and mount definitions are mixed with file contents in a single blob.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Provide structured config profiles with named collections of mounts and includes
|
||||
- Support ordered include lists so profiles can reference other profiles in sequence
|
||||
- Allow per-tool-instance profile selection with fallback to user/tool-type defaults
|
||||
- Remove implicit auto-mounting behavior at launch time
|
||||
- Maintain backward compatibility for existing `config_folders` data during migration
|
||||
|
||||
**Non-Goals:**
|
||||
- Frontend UI for profile management (separate change)
|
||||
- Real-time profile switching on running instances
|
||||
- Profile versioning or history
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. New `config_profiles` table replaces the semantic role of `config_folders`
|
||||
- Rationale: A profile is a higher-level concept than a folder; it includes mounts, includes, and metadata
|
||||
- `config_folders` remains for data migration but is no longer used for auto-mounting
|
||||
|
||||
### 2. `config_includes` provides ordered many-to-many self-reference on `config_profiles`
|
||||
- Rationale: Profiles need to include other profiles (e.g., a "base" profile included by "project-specific")
|
||||
- `order_index` column controls application order
|
||||
|
||||
### 3. `config_mounts` stores individual mount/file entries
|
||||
- Rationale: Normalizing mounts allows querying, ordering, and validation per mount
|
||||
- Each mount has a `mount_path`, optional `content` text, and optional `source_profile_id` for transitive includes
|
||||
|
||||
### 4. Default profile stored on `user_configs.config` JSONB
|
||||
- Rationale: Avoids schema changes to `users`; the existing `user_configs` table already stores per-user JSON
|
||||
- Key: `default_profile_id` (global default) and `default_profiles` map for per-tool-type defaults
|
||||
|
||||
### 5. `tool_instances.selected_profile_id` for explicit selection
|
||||
- Rationale: Clear, direct foreign key; nullable to allow fallback to defaults
|
||||
- Null means "use default resolution"
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [Risk] Existing `config_folders` data becomes orphaned if not migrated → Mitigation: keep table, stop auto-mount behavior only
|
||||
- [Risk] Profile include cycles could cause infinite loops → Mitigation: validate at write time, detect cycles in include graph
|
||||
- [Risk] Multiple includes with overlapping mount paths → Mitigation: last-include-wins based on order_index
|
||||
@@ -0,0 +1,30 @@
|
||||
## Why
|
||||
|
||||
The current `config_folders` table provides basic file mounting but lacks structured profile management, ordering, and per-tool-instance selection. We need a proper config profile system that supports ordered includes, mount/file definitions, default selection, and explicit profile assignment per tool instance.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add `ConfigProfile` model to replace the legacy `config_folders` concept with structured profiles
|
||||
- Add `ConfigInclude` model for ordered include lists within profiles
|
||||
- Add `ConfigMount` model for mount/file definitions (replacing the flat `files` JSONB on `config_folders`)
|
||||
- Add default profile selection per user and tool type
|
||||
- Add `selected_profile_id` to `ToolInstance` for per-instance profile selection
|
||||
- Remove launch-time reliance on legacy active config folder auto-mounting (mark `config_folders.is_active` as deprecated, stop auto-mounting at launch)
|
||||
- Create database migrations for all new tables
|
||||
- **BREAKING**: Legacy `config_folders` auto-mounting behavior will be removed; tool instances must explicitly select a profile
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `config-profile-management`: CRUD operations for config profiles, includes, and mounts
|
||||
- `tool-instance-profile-selection`: Assign and switch config profiles per tool instance
|
||||
|
||||
### Modified Capabilities
|
||||
- `tool-instance-launch`: Change launch behavior to use explicit profile selection instead of auto-mounting active config folder
|
||||
|
||||
## Impact
|
||||
|
||||
- New database tables: `config_profiles`, `config_includes`, `config_mounts`
|
||||
- Modified tables: `tool_instances` (add `selected_profile_id`), `users` or `user_configs` (add default profile selection)
|
||||
- API endpoints for profile management and instance profile assignment
|
||||
- Tool launch logic changes (remove auto-mount, use explicit profile)
|
||||
@@ -0,0 +1,29 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: User can create config profiles
|
||||
The system SHALL allow users to create named config profiles containing mounts and includes.
|
||||
|
||||
#### Scenario: Successful profile creation
|
||||
- **WHEN** user creates a profile with name, description, and mount list
|
||||
- **THEN** the profile is stored with a unique ID and associated mounts
|
||||
|
||||
### Requirement: Profile includes are ordered
|
||||
The system SHALL support ordered includes where profiles can reference other profiles with a defined application sequence.
|
||||
|
||||
#### Scenario: Include with order
|
||||
- **WHEN** user adds an include to a profile with order_index 1
|
||||
- **THEN** the included profile's mounts are applied after order_index 0 includes
|
||||
|
||||
### Requirement: Config mounts define files and paths
|
||||
The system SHALL store individual mount entries with mount_path, optional content, and optional source profile reference.
|
||||
|
||||
#### Scenario: Add mount to profile
|
||||
- **WHEN** user adds a mount with mount_path "/app/config.json" and content "{}"
|
||||
- **THEN** the mount is stored and linked to the profile
|
||||
|
||||
### Requirement: Cycle detection in includes
|
||||
The system SHALL prevent creation of include cycles.
|
||||
|
||||
#### Scenario: Attempt cyclic include
|
||||
- **WHEN** user tries to include profile B in profile A where A is already included in B
|
||||
- **THEN** the system rejects the request with an error
|
||||
@@ -0,0 +1,22 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Tool instance can have selected profile
|
||||
The system SHALL allow setting an explicit config profile on a tool instance.
|
||||
|
||||
#### Scenario: Assign profile to instance
|
||||
- **WHEN** user sets selected_profile_id on a tool instance
|
||||
- **THEN** the instance stores the profile ID and uses it at launch time
|
||||
|
||||
### Requirement: Tool instance uses default profile when none selected
|
||||
The system SHALL resolve a default profile for a tool instance when no explicit profile is selected.
|
||||
|
||||
#### Scenario: Fallback to user default
|
||||
- **WHEN** a tool instance has no selected_profile_id
|
||||
- **THEN** the system uses the user's default profile for that tool type, or the global default
|
||||
|
||||
### Requirement: Remove legacy auto-mount behavior
|
||||
The system SHALL no longer auto-mount the active config folder at tool launch time.
|
||||
|
||||
#### Scenario: Launch without active folder
|
||||
- **WHEN** a tool instance launches with no selected profile and no default
|
||||
- **THEN** the instance starts without mounting any config folder
|
||||
@@ -5,11 +5,11 @@
|
||||
- [x] 1.3 Create ConfigMount model for mount/file definitions
|
||||
- [x] 1.4 Add selected_profile_id to ToolInstance model
|
||||
- [x] 1.5 Add default profile fields to UserConfig model
|
||||
- [ ] 1.6 Create Alembic migration for new tables and columns
|
||||
- [x] 1.6 Create Alembic migration for new tables and columns
|
||||
- [x] 1.7 Register new models in models/__init__.py
|
||||
- [ ] 1.8 Add migration metadata and test
|
||||
- [x] 1.8 Add migration metadata and test
|
||||
|
||||
## 2. Legacy Deprecation
|
||||
|
||||
- [ ] 2.1 Mark config_folders.is_active as deprecated in model
|
||||
- [x] 2.1 Mark config_folders.is_active as deprecated in model
|
||||
- [ ] 2.2 Remove auto-mounting logic from tool launch (separate change)
|
||||
|
||||
Reference in New Issue
Block a user