90 lines
3.5 KiB
Markdown
90 lines
3.5 KiB
Markdown
# ADR 0001: Runtime Secret Provisioning
|
|
|
|
**Status:** Accepted
|
|
**Date:** 2026-03-30
|
|
|
|
## Context
|
|
|
|
CapaKraken historically allowed some operational runtime secrets to be persisted through `SystemSettings`.
|
|
|
|
That included values such as:
|
|
|
|
- primary AI API credentials
|
|
- dedicated DALL-E credentials
|
|
- Gemini credentials
|
|
- SMTP password
|
|
- anonymization seed
|
|
|
|
This was convenient for fast iteration, but it coupled operational secret material to the main application data plane and blurred the line between configuration metadata and deployment secrets.
|
|
|
|
The project is moving toward a production model where the running artifact should be immutable and environment-driven. That model is weakened if operators can still rotate runtime secrets through normal application writes.
|
|
|
|
## Decision
|
|
|
|
Operational runtime secrets must be provisioned outside the application database.
|
|
|
|
Allowed sources:
|
|
|
|
- deployment environment variables
|
|
- host-level secret files such as `.env.production` on self-managed infrastructure
|
|
- platform secret managers or encrypted environment facilities
|
|
|
|
Disallowed source for new secret values:
|
|
|
|
- admin updates that write runtime secrets into `SystemSettings`
|
|
|
|
`SystemSettings` remains valid for non-secret runtime metadata such as:
|
|
|
|
- provider selection
|
|
- endpoints
|
|
- model names
|
|
- SMTP host/user/from settings
|
|
- anonymization mode and domain
|
|
|
|
Legacy secret values that already exist in `SystemSettings` may still be read during migration for compatibility, but they are not the target state and should be cleared after equivalent deployment secrets are provisioned.
|
|
|
|
## Consequences
|
|
|
|
Positive:
|
|
|
|
- production updates become more predictable because images and runtime secrets are managed as separate deployment concerns
|
|
- operational secrets stop depending on ordinary application write paths
|
|
- admin tooling can expose status and diagnostics without pretending to be the system of record for secrets
|
|
- secret rotation becomes an infrastructure operation rather than a product mutation
|
|
|
|
Tradeoffs:
|
|
|
|
- smaller self-managed installs need a disciplined host bootstrap process
|
|
- operators must understand that updating app settings is no longer sufficient for secret rotation
|
|
- migration requires visibility into which secrets are still backed by database residue
|
|
|
|
## Implementation Notes
|
|
|
|
The implementation should follow these rules:
|
|
|
|
1. runtime consumers resolve supported secret values from environment first
|
|
2. admin settings reads expose presence and source status, not secret values
|
|
3. admin settings updates ignore incoming secret payloads
|
|
4. the UI explains the expected environment variables for each runtime secret
|
|
5. a dedicated cleanup action removes legacy database-stored secret values after migration
|
|
|
|
## Operational Guidance
|
|
|
|
For staging and production:
|
|
|
|
1. provision runtime secrets on the host or platform before starting a new release
|
|
2. deploy the already-built application image
|
|
3. restart the application so the new process reads the current secret source
|
|
4. verify runtime status in admin settings
|
|
5. clear any leftover legacy database secret values once the environment-backed source is confirmed
|
|
|
|
Secret rotation should follow the same model. In most cases, no application data mutation is needed. The operator updates the deployment secret source and restarts or redeploys the app.
|
|
|
|
## Follow-up
|
|
|
|
Still required after this decision:
|
|
|
|
- complete the canonical image-based staging/production rollout
|
|
- ensure staging and production hosts both use the same secret provisioning rules
|
|
- periodically verify that legacy database secret fields remain empty
|