Credentials
Credentials are secrets stored encrypted at rest. Coding runtimes never see raw credential material; the agent injects only the environment variables a worker needs and keeps secrets out of prompts and step state.
Encryption is AES-256-GCM with a key derived from the master key. The master key is resolved from the config table first and falls back to STEELFRAME_MASTER_KEY. “Master key not configured” means no key exists anywhere; a failure reading the key is a database error, surfaced as one.
Manage credentials under Config → Credentials or the JSON API:
| Method | Path | Purpose |
|---|---|---|
GET | /api/credentials | List stored credentials (secrets never returned) |
GET | /api/credentials/catalog | Well-known services plus master-key status |
PUT | /api/credentials | Create or replace a credential |
DELETE | /api/credentials/{id} | Delete a credential |
Services and shapes
Section titled “Services and shapes”The catalog exposes six well-known services. Steelframe only looks up recognized names; unknown services are rejected.
| Service | Environment-scoped | Shape | Used for |
|---|---|---|---|
grafana | staging + production | URL + secret | gcx metrics/logs/alerts during investigation |
kubectl | staging + production | URL + secret | Cluster correlation via a written kubeconfig |
github_app_private_key | global | secret only (PEM) | GitHub App installation tokens |
discord_webhook | global | URL only | Failure and investigation notifications |
memory_s3 | global | URL + secret | Session-memory WAL access key + secret |
Shapes:
- url_and_secret —
target_urlandsecretare both required. - url_only — the webhook URL is the whole credential. Accept it in either field; it is stored as an encrypted secret with kind
webhook. - secret_only —
secretis required.github_app_private_keydefaultstarget_urltohttps://api.github.com.
kind is one of token, pem, or webhook; it defaults per service.
Environment-scoped services require environment to be exactly staging or production. Global services must omit it. Lookups prefer the exact environment and fall back to a legacy global row.
Injection into workers
Section titled “Injection into workers”Workers receive env at spawn. Secrets are never put in LLM prompts:
- Grafana:
GRAFANA_SERVERandGRAFANA_TOKEN. - Kubernetes:
KUBECONFIGpointing at a written kubeconfig. - GitHub: a nine-variable bundle (
GH_TOKEN,GIT_AUTHOR_*,GIT_COMMITTER_*, and git config headers) so workerghandgit pushrun under the bot identity.
Gotchas
Section titled “Gotchas”PUT /api/credentialswithout a configured master key returns412and writes nothing.- A failed master-key read is
500, not “not configured”. - Upsert replaces in place, which is how you rotate the GitHub App private key.
- Discord webhook URLs are redacted when returned (
…/api/webhooks/••••); the stored secret still holds the full value. - Listing never returns secret material — only
target_url(redacted where applicable), kind, and service.