/admin/credentials) manages the API keys the app calls out
to. Keys saved here take effect immediately — no Vercel environment variable to set,
no redeploy.
The providers
Each row on the Credentials page shows a real logo (via logo.dev), the provider’s
purpose, and a status:
db-managed— an active key is stored, encrypted, in the database..env— no database key, but the corresponding environment variable is set on the server (e.g.HARVEST_API_KEY). Still usable; just not rotatable from this page yet.not configured— neither. Adapters that need this provider will fail clearly rather than silently degrading.
Adding or rotating a key
Click Add key, paste the key, and save. Rotating a key doesn’t overwrite the old one — the previous key is deactivated (is_active = false, retired_at set) and a new
row is inserted, so there’s an audit trail of every key that was ever active.
Deactivate requires a confirm click (the button becomes Confirm / Cancel) before it
takes effect — no accidental one-click removal of a working key.
How this stays secure
- Keys are encrypted with AES-256-GCM before they ever touch the database
(
lib/crypto.ts), using a server-onlyCREDENTIAL_ENCRYPTION_KEY. - The browser never receives a key back in plaintext — only a masked hint like
px_test_••••2345, generated at save time and never re-derivable from the stored ciphertext. - Decryption happens exclusively in server-side code
(
lib/domain/credentials.getProviderApiKey), which resolves a database-stored key first and only falls back to the environment variable if nothing is active in the database. - Every credential is scoped to your organization — the same encrypted key isn’t shared across organizations, and the lookup always goes through your current session.
Which endpoints actually consume a saved key today
As of this writing, only Anthropic is wired into a real code path (lib/providers/anthropic.ts, used by the calibrate screen’s extraction call). Harvest
and Serper keys save and encrypt correctly, but nothing in the app calls those APIs yet —
their provider adapters land in a later phase. Once they do, they’ll automatically pick
up whatever’s saved here with no additional wiring.