docs(openspec): add OpenSpec changes for FN-005, FN-006, FN-008, FN-009, FN-010
- Add frontend-foundation change (FN-005) with 46 tasks - Add deployment-config change (FN-006) with 27 tasks - Add runfusion-poc/opencode-poc change (FN-008) with 25 tasks - Add config-secrets change (FN-009) with 31 tasks - Add codeserver-spawn change (FN-010) with 38 tasks - Include project specsheet and configuration - Archive completed deployment-config change
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-14
|
||||
@@ -0,0 +1,63 @@
|
||||
## Context
|
||||
|
||||
The backend has Config and Secret models (FN-004) with scope fields, but no frontend UI or runtime injection. SSH keys already use Fernet encryption (FN-011), so the encryption pattern is established. This design completes the config/secrets lifecycle.
|
||||
|
||||
Current state:
|
||||
- Config model: key, value, scope (global/user/project/instance), scope_id
|
||||
- Secret model: key, encrypted_value, scope, scope_id
|
||||
- Fernet encryption utilities exist in app/encryption.py
|
||||
- No UI for management
|
||||
- No runtime injection into containers
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Allow users to manage configs and secrets via UI
|
||||
- Inject configs/secrets into tool containers at spawn time
|
||||
- Support scope-based inheritance (instance overrides project overrides user overrides global)
|
||||
- Maintain encryption for all secret values
|
||||
|
||||
**Non-Goals:**
|
||||
- Secret versioning or history
|
||||
- Automatic secret rotation
|
||||
- Integration with external secret managers (Vault, AWS Secrets Manager)
|
||||
- Config/secrets for non-tool resources
|
||||
|
||||
## Decisions
|
||||
|
||||
**1. Mount configs as files, secrets as env vars**
|
||||
- Rationale: Configs (JSON) are often files (e.g., settings.json). Secrets are typically env vars.
|
||||
- Config mount: `/app/config/<key>.json`
|
||||
- Secret env: `<KEY>=<decrypted_value>`
|
||||
|
||||
**2. Scope resolution: closest match wins**
|
||||
- Rationale: Instance-specific values should override project defaults
|
||||
- Resolution order: instance → project → user → global
|
||||
|
||||
**3. Secret values never sent to frontend decrypted**
|
||||
- Rationale: Security. Frontend only sees masked values (e.g., `••••••`).
|
||||
- Decryption happens only in backend during runtime injection
|
||||
|
||||
**4. Config values are plaintext (not encrypted)**
|
||||
- Rationale: Configs are not sensitive. Encrypting them adds complexity without security benefit.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
**[Risk] Secret injection at spawn time could fail silently**
|
||||
→ Mitigation: Validate all referenced secrets exist before spawning. Return error if missing.
|
||||
|
||||
**[Risk] Config files in containers could be read by other processes**
|
||||
→ Mitigation: Mount config files with restrictive permissions (0400). Run containers as non-root.
|
||||
|
||||
**[Risk] Large configs could exceed container env var limits**
|
||||
→ Mitigation: Document size limits. Consider config file mounting for large values.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
No migration needed. This extends existing models.
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. Should configs support JSON schema validation?
|
||||
2. Do we need bulk import/export for configs/secrets?
|
||||
3. Should secret keys be validated against a naming convention?
|
||||
@@ -0,0 +1,29 @@
|
||||
## Why
|
||||
|
||||
Tool instances need runtime configuration and secrets (API keys, database passwords, etc.). The backend has Config and Secret models (FN-004), but there's no UI for users to manage these values, and no runtime injection mechanism to pass them into spawned containers.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Config management UI**: Frontend pages for creating, updating, and deleting config values at global/user/project/instance scopes
|
||||
- **Secret management UI**: Frontend pages for encrypted secret storage with masked value display
|
||||
- **Runtime injection**: Backend service that mounts configs and secrets into tool containers at spawn time
|
||||
- **Scope-based access control**: Configs/secrets respect scope hierarchy (global → user → project → instance)
|
||||
- **Encryption verification**: Ensure Fernet encryption is properly applied to all secret values
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `config-management`: CRUD operations for configuration values with scope support
|
||||
- `secret-management`: Encrypted storage and retrieval of sensitive values
|
||||
- `runtime-injection`: Mount configs and secrets into tool containers at spawn
|
||||
|
||||
### Modified Capabilities
|
||||
- None (extends existing Config/Secret models)
|
||||
|
||||
## Impact
|
||||
|
||||
- **apps/web/src/**: New config and secret management pages
|
||||
- **apps/api/app/routers/configs.py**: Enhanced with scope filtering
|
||||
- **apps/api/app/routers/secrets.py**: Enhanced with scope filtering
|
||||
- **apps/api/app/services/**: New runtime injection service
|
||||
- **apps/api/app/models/**: Potential Config/Secret model updates for scope validation
|
||||
@@ -0,0 +1,37 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: User can create config values
|
||||
The system SHALL allow users to create configuration values at various scopes.
|
||||
|
||||
#### Scenario: Create project config
|
||||
- **WHEN** the user navigates to project settings
|
||||
- **AND** clicks "Add Config"
|
||||
- **THEN** a form appears with key, value, and scope fields
|
||||
- **AND** submitting creates a config at the selected scope
|
||||
|
||||
#### Scenario: Config scope validation
|
||||
- **WHEN** the user creates a config
|
||||
- **THEN** the scope must be one of: global, user, project, instance
|
||||
- **AND** the scope_id must match the selected scope type
|
||||
|
||||
### Requirement: User can view and update configs
|
||||
The system SHALL display configs with scope-based filtering.
|
||||
|
||||
#### Scenario: List configs
|
||||
- **WHEN** the user views configs for a project
|
||||
- **THEN** all configs visible at project scope or above are displayed
|
||||
- **AND** values are shown as formatted JSON
|
||||
|
||||
#### Scenario: Update config
|
||||
- **WHEN** the user edits a config value
|
||||
- **THEN** the updated value is saved
|
||||
- **AND** the change takes effect on next tool spawn
|
||||
|
||||
### Requirement: User can delete configs
|
||||
The system SHALL allow deletion of config values.
|
||||
|
||||
#### Scenario: Delete config
|
||||
- **WHEN** the user clicks delete on a config
|
||||
- **THEN** a confirmation dialog appears
|
||||
- **AND** confirming removes the config
|
||||
- **AND** the config is no longer injected into containers
|
||||
@@ -0,0 +1,40 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Configs are mounted into tool containers
|
||||
The system SHALL mount configuration values as files into spawned tool containers.
|
||||
|
||||
#### Scenario: Config file mount
|
||||
- **WHEN** a tool instance is spawned
|
||||
- **THEN** all applicable configs are written to /app/config/
|
||||
- **AND** each config is a separate JSON file named by key
|
||||
- **AND** files have restrictive permissions (0400)
|
||||
|
||||
#### Scenario: Config scope resolution
|
||||
- **WHEN** configs are resolved for a tool instance
|
||||
- **THEN** the system collects configs from all applicable scopes
|
||||
- **AND** instance scope overrides project scope
|
||||
- **AND** project scope overrides user scope
|
||||
- **AND** user scope overrides global scope
|
||||
|
||||
### Requirement: Secrets are injected as environment variables
|
||||
The system SHALL inject secret values as environment variables into tool containers.
|
||||
|
||||
#### Scenario: Secret env var injection
|
||||
- **WHEN** a tool instance is spawned
|
||||
- **THEN** all applicable secrets are decrypted
|
||||
- **AND** injected as environment variables with uppercase keys
|
||||
- **AND** the container process can access them
|
||||
|
||||
#### Scenario: Secret scope resolution
|
||||
- **WHEN** secrets are resolved for a tool instance
|
||||
- **THEN** the same scope hierarchy applies as configs
|
||||
- **AND** closest scope wins on key collision
|
||||
|
||||
### Requirement: Missing secrets fail spawn
|
||||
The system SHALL prevent spawning if referenced secrets are missing.
|
||||
|
||||
#### Scenario: Validate secrets before spawn
|
||||
- **WHEN** a spawn request references a secret by key
|
||||
- **AND** the secret does not exist in any applicable scope
|
||||
- **THEN** the spawn fails with a clear error message
|
||||
- **AND** no container is created
|
||||
@@ -0,0 +1,37 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: User can create secrets
|
||||
The system SHALL allow users to store encrypted secret values.
|
||||
|
||||
#### Scenario: Create secret
|
||||
- **WHEN** the user navigates to project secrets
|
||||
- **AND** clicks "Add Secret"
|
||||
- **THEN** a form appears with key and value fields
|
||||
- **AND** the value is encrypted with Fernet before storage
|
||||
- **AND** the user sees a masked value (e.g., ••••••) after creation
|
||||
|
||||
#### Scenario: Secret scope
|
||||
- **WHEN** the user creates a secret
|
||||
- **THEN** the scope can be user, project, or instance
|
||||
- **AND** the secret is only visible within that scope hierarchy
|
||||
|
||||
### Requirement: Secrets are never exposed decrypted
|
||||
The system SHALL prevent decrypted secret values from being sent to the frontend.
|
||||
|
||||
#### Scenario: Secret list display
|
||||
- **WHEN** the user views the secrets list
|
||||
- **THEN** only secret keys and scopes are visible
|
||||
- **AND** values are always masked
|
||||
|
||||
#### Scenario: Secret update
|
||||
- **WHEN** the user updates a secret
|
||||
- **THEN** only the new value is sent to the backend
|
||||
- **AND** the old value is replaced (not displayed)
|
||||
|
||||
### Requirement: User can delete secrets
|
||||
The system SHALL allow deletion of secret values.
|
||||
|
||||
#### Scenario: Delete secret
|
||||
- **WHEN** the user deletes a secret
|
||||
- **THEN** the encrypted value is permanently removed
|
||||
- **AND** the secret is no longer injected into containers
|
||||
@@ -0,0 +1,48 @@
|
||||
## 1. Backend Enhancements
|
||||
|
||||
- [ ] 1.1 Update Config model with scope validation methods
|
||||
- [ ] 1.2 Update Secret model with encryption verification
|
||||
- [ ] 1.3 Enhance configs router with scope filtering and hierarchy resolution
|
||||
- [ ] 1.4 Enhance secrets router with scope filtering and hierarchy resolution
|
||||
- [ ] 1.5 Create apps/api/app/services/runtime_injection.py for config/secret resolution
|
||||
- [ ] 1.6 Implement config file generation for container mounts
|
||||
- [ ] 1.7 Implement secret env var generation for container injection
|
||||
- [ ] 1.8 Add validation to fail spawn when referenced secrets are missing
|
||||
|
||||
## 2. Frontend - Config Management
|
||||
|
||||
- [ ] 2.1 Create ConfigList component at /projects/:id/configs
|
||||
- [ ] 2.2 Implement ConfigForm for creating/updating configs
|
||||
- [ ] 2.3 Add scope selector (project/instance/global) to config form
|
||||
- [ ] 2.4 Implement config delete with confirmation
|
||||
- [ ] 2.5 Add JSON formatting for config values
|
||||
|
||||
## 3. Frontend - Secret Management
|
||||
|
||||
- [ ] 3.1 Create SecretList component at /projects/:id/secrets
|
||||
- [ ] 3.2 Implement SecretForm for creating/updating secrets
|
||||
- [ ] 3.3 Add masked value display (never show decrypted)
|
||||
- [ ] 3.4 Implement secret delete with confirmation
|
||||
- [ ] 3.5 Add scope selector to secret form
|
||||
|
||||
## 4. Runtime Integration
|
||||
|
||||
- [ ] 4.1 Integrate runtime injection into tool instance spawn endpoint
|
||||
- [ ] 4.2 Update Docker Compose generation to include config mounts
|
||||
- [ ] 4.3 Update Docker Compose generation to include secret env vars
|
||||
- [ ] 4.4 Test config/secret injection in local Docker environment
|
||||
|
||||
## 5. Testing & Verification
|
||||
|
||||
- [ ] 5.1 Write backend tests for config scope resolution
|
||||
- [ ] 5.2 Write backend tests for secret encryption/decryption
|
||||
- [ ] 5.3 Write backend tests for runtime injection
|
||||
- [ ] 5.4 Write frontend tests for ConfigList and SecretList
|
||||
- [ ] 5.5 Run full test suite: `make test`
|
||||
- [ ] 5.6 Run linters: `make lint`
|
||||
|
||||
## 6. Documentation
|
||||
|
||||
- [ ] 6.1 Update docs/development.md with config/secrets workflow
|
||||
- [ ] 6.2 Add config/secrets UI guide to docs/architecture.md
|
||||
- [ ] 6.3 Document scope hierarchy and resolution rules
|
||||
Reference in New Issue
Block a user