Secrets at rest: encrypted keys and tokens

Secrets encrypted at rest are credentials stored in a database in encrypted form; DevFlow encrypts provider keys and GitHub tokens with AES-256-GCM under a 32-byte key.

The risk

A tool that opens pull requests and calls model providers needs credentials for both. If the database is copied, through a leaked backup or a misconfigured replica, unencrypted credentials go with it. Encrypting them at rest means that a copy of the rows alone is not enough.

What DevFlow encrypts

DevFlow encrypts these credentials before they reach the database:

  • provider API keys stored per workspace;
  • GitHub access and refresh tokens;
  • the provisioned OpenRouter sub-key used for managed inference;
  • chat bridge bot tokens and signing secrets.

Encryption happens in the database query layer: values are encrypted on write and decrypted on read.

How the encryption works

The cipher is AES-256-GCM, an authenticated mode, so a tampered value fails to decrypt instead of producing garbage. The key comes from SECRETS_ENCRYPTION_KEY, a base64 value that must decode to exactly 32 bytes; with a key of any other length, the API refuses to start.

Each value gets a fresh random nonce and is stored as enc:v1: followed by base64 text. The version tag lets a later format be told apart from this one. An empty value is stored empty, so a cleared field stays visibly blank instead of turning into ciphertext.

A worked example

Suppose an owner saves an OpenRouter key in workspace settings. The row holds only the enc:v1: text, and the plain key is produced only when DevFlow reads the row, for example to start a run. Someone holding a copy of the database without SECRETS_ENCRYPTION_KEY sees the encrypted string and nothing more.

Beyond the database

Encryption at rest is one layer. For runs that go through DevFlow's model relay, the relay looks up the workspace's own stored key first. For OpenRouter it never falls back to a key in the server's environment, so a workspace without its own OpenRouter key cannot run on the operator's key by accident.

FAQ

Which credentials does DevFlow encrypt at rest, and with which cipher?

DevFlow encrypts workspace provider API keys, GitHub access and refresh tokens, the provisioned OpenRouter sub-key for managed inference, and chat bridge bot tokens and signing secrets with AES-256-GCM before storing them.

Can DevFlow agents read the server's own secrets?

No. DevFlow builds each agent's environment from an allowlist, so server secrets such as the database URL or the GitHub client secret never reach agent processes.