Every secret is encrypted on your device before it reaches our servers. The decryption key never leaves you.
Zero-knowledge encryption
XChaCha20-Poly1305 on every secret value, with the variable ID bound as associated data. X25519 sealed boxes wrap each org key to each member.
Argon2id derives your key from your vault passphrase. libsodium does all the math; no homegrown crypto.
We store ciphertext, sealed boxes, public keys, and your encrypted private key. We do not store your passphrase or any plaintext secret.
Recovery without a back door
At signup we show a one-time recovery code. Save it offline; it wraps a second copy of your private key.
Forget your passphrase? The recovery code lets you back in and reset it.
Lose both? Your data is permanently unreadable. We have no override.
Transport and hosting
TLS 1.2+ on every endpoint, certificates rotated automatically. The CLI verifies certs and refuses plaintext fallback.
Managed Postgres with provider-managed encrypted backups. Two app slots behind Caddy for zero-downtime deploys; root login disabled.
Even if every server-side secret were exposed, no organization data is decryptable.
Honest note: HSTS preload and a strict Content Security Policy are queued for the next hardening pass.
Access and accountability
Better Auth with email OTP, password, and GitHub OAuth. HTTP-only session cookies. Role-based access: owner, admin, member.
Each CLI/API token carries its own X25519 keypair. We store only a SHA-256 hash plus the sealed key; the token string is shown once.
Project, environment, variable, and token events are recorded with actor, action, and timestamp. Our logger redacts secrets everywhere.
Honest note: TOTP 2FA, login events, and client IP in the audit log are not yet shipped.
The trade-offs
What zero-knowledge costs you.
Forget your passphrase AND lose your recovery code and access is gone. We cannot reset it.
New members cannot read existing secrets until an existing member is online to seal the org key for them.
No server-side search, no webhooks with values, no email previews. Anything that would need plaintext server-side does not exist.
Removing a member immediately revokes their sessions, API tokens, and wrapped copy of the org key. Re-encryption of existing variables happens the next time an admin loads the org page. Anything they already pulled to disk is already plaintext on their machine; we cannot un-cache it.