feat(FN-009): implement config and secrets management with runtime injection

- Add RuntimeInjectionService for scope-based config/secret resolution
- Mount configs as JSON files at /app/config/ with 0400 permissions
- Inject secrets as environment variables with uppercase keys
- Implement scope hierarchy: instance > project > user > global
- Create ConfigListPage and SecretListPage frontend components
- Mask secret values in API responses (never expose decrypted)
- Validate secrets exist before spawning containers
- Add comprehensive tests for runtime injection service
- Update documentation with config/secrets workflow
This commit is contained in:
2026-05-15 16:44:26 +02:00
parent 78aaddb2b5
commit 51d93d9dc6
12 changed files with 838 additions and 86 deletions
+41
View File
@@ -1171,3 +1171,44 @@ Any implementation task must:
7. **High availability:** No replicas or load balancing in MVP.
8. **Backup strategy:** Out of MVP scope; rely on host-level volume backups.
9. **Rate limiting:** Not in MVP; add at Traefik or API gateway layer later.
## 19. Config & Secrets System
### 19.1 Design
The config and secrets system provides scoped, runtime-injected configuration for tool containers.
**Config:**
- Plaintext JSON values
- Mounted as read-only files at `/app/config/<key>.json`
- Scope hierarchy: global → user → project → instance (closest wins)
**Secrets:**
- Encrypted with Fernet at rest
- Injected as environment variables with uppercase keys
- Never exposed decrypted to the frontend (masked as `••••••`)
- Scope hierarchy: global → user → project → instance (closest wins)
### 19.2 Runtime Injection
When a tool instance is spawned:
1. **Config Resolution:** Collect configs from all applicable scopes, with closer scopes overriding broader ones
2. **Secret Resolution:** Decrypt secrets from all applicable scopes, with closer scopes overriding broader ones
3. **Config File Generation:** Write JSON files to `/tmp/headquarter-configs/{instance_id}/`
4. **Volume Mounting:** Mount config files as read-only volumes with `0400` permissions
5. **Env Var Injection:** Add decrypted secrets to the container's environment variables
6. **Validation:** Fail spawn if required secrets are missing, with clear error messages
### 19.3 Frontend
- `/projects/{id}/configs` — Config management with JSON formatting
- `/projects/{id}/secrets` — Secret management with masked values
- Both support create, read, update, delete operations with scope selection
### 19.4 Security
- Config files have restrictive permissions (0400)
- Secret values are never sent to the frontend
- Decryption only happens during runtime injection in the backend
- Missing required secrets prevent container spawn
+64
View File
@@ -259,3 +259,67 @@ docker network create tools # One-time setup
```
Spawned containers use the `tools` network for Traefik routing.
## Config & Secrets
### Overview
The platform supports scoped configuration values and encrypted secrets that are injected into tool containers at spawn time.
### Scopes
Configs and secrets support four scope levels (closest match wins):
1. **Global** — Available to all users and projects
2. **User** — Available to a specific user across all projects
3. **Project** — Available within a specific project
4. **Instance** — Available to a specific tool instance
### Configs
Configs are plaintext JSON values mounted as files into containers:
- Mount path: `/app/config/<key>.json`
- Permissions: `0400` (read-only, owner-only)
- Scope resolution: instance > project > user > global
**API Endpoints:**
- `POST /configs` — Create config
- `GET /configs` — List configs (filter by scope_type, scope_id)
- `PUT /configs/{id}` — Update config value
- `DELETE /configs/{id}` — Delete config
**Frontend:**
- `/projects/{id}/configs` — Config management UI
### Secrets
Secrets are encrypted with Fernet and injected as environment variables:
- Env var format: `<UPPERCASE_KEY>=<decrypted_value>`
- Values are never sent to the frontend decrypted (displayed as `••••••`)
- Scope resolution: instance > project > user > global
**API Endpoints:**
- `POST /secrets` — Create secret
- `GET /secrets` — List secrets (filter by scope_type, scope_id)
- `PUT /secrets/{id}` — Update secret value
- `DELETE /secrets/{id}` — Delete secret
**Frontend:**
- `/projects/{id}/secrets` — Secret management UI
### Runtime Injection
When a tool instance is spawned:
1. Configs are resolved from all applicable scopes
2. Secrets are resolved and decrypted
3. Config files are generated in `/tmp/headquarter-configs/{instance_id}/`
4. Config files are mounted as read-only volumes
5. Secrets are injected as environment variables
6. Missing required secrets will fail the spawn with a clear error
### Validation
Before spawning, the system validates that all required secrets exist. If any are missing, the spawn fails with an error message listing the missing secrets.