Skip to content

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:

MethodPathPurpose
GET/api/credentialsList stored credentials (secrets never returned)
GET/api/credentials/catalogWell-known services plus master-key status
PUT/api/credentialsCreate or replace a credential
DELETE/api/credentials/{id}Delete a credential

The catalog exposes six well-known services. Steelframe only looks up recognized names; unknown services are rejected.

ServiceEnvironment-scopedShapeUsed for
grafanastaging + productionURL + secretgcx metrics/logs/alerts during investigation
kubectlstaging + productionURL + secretCluster correlation via a written kubeconfig
github_app_private_keyglobalsecret only (PEM)GitHub App installation tokens
discord_webhookglobalURL onlyFailure and investigation notifications
memory_s3globalURL + secretSession-memory WAL access key + secret

Shapes:

  • url_and_secrettarget_url and secret are 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_onlysecret is required. github_app_private_key defaults target_url to https://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.

Workers receive env at spawn. Secrets are never put in LLM prompts:

  • Grafana: GRAFANA_SERVER and GRAFANA_TOKEN.
  • Kubernetes: KUBECONFIG pointing at a written kubeconfig.
  • GitHub: a nine-variable bundle (GH_TOKEN, GIT_AUTHOR_*, GIT_COMMITTER_*, and git config headers) so worker gh and git push run under the bot identity.
  • PUT /api/credentials without a configured master key returns 412 and 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.