Files
headquarter/openspec/changes/archive/2026-05-14-config-secrets/design.md
T
alex 8b4784f5ed
CI / Web CI (push) Failing after 10s
CI / API CI (push) Failing after 11s
chore(openspec): archive completed changes
- Archive config-secrets (FN-009) - 31 tasks complete
- Archive runfusion-poc (FN-008) - 25 tasks complete
- Archive deployment-config (FN-006) - 27 tasks complete
- All changes moved to openspec/changes/archive/
2026-05-16 11:33:37 +02:00

2.5 KiB

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?