Security architecture
Virtual keys are hashed
Only a SHA-256 digest is stored. The plaintext exists once, at reveal time. Key rotation or master-key rotation never invalidates them.
No master API key
There is no all-powerful bearer token on the gateway. Admin actions happen in the portal behind Entra ID SSO and role-based access control.
Provider secrets
Provider API keys are either:
- AES-256-GCM encrypted at rest with
ZEALLM_ENCRYPTION_KEY(formativ:tag:ciphertext, each base64), or - Azure Key Vault references (
akv:<secret-name>) resolved at runtime withDefaultAzureCredential. Vault-referenced keys rotate by publishing a new secret version — no redeploy.
Invite-only portal
Sign-in is rejected unless the email is in ZEALLM_ADMIN_EMAILS or was invited under Users. All emails must match ZEALLM_ALLOWED_DOMAIN. Suspended users are rejected at sign-in.
Production hardening
AUTH_DEV_BYPASSmust be false- TLS-terminate in front of
:3000and:8080 - Do not publish Postgres on a host port
- Keep Redis on the internal network (compose Redis has no password)
- Portal mutation rate limits are in-memory — add Redis/edge limits before running multiple portal replicas
Encryption key
Never rotate ZEALLM_ENCRYPTION_KEY after credentials are stored except via the rotation runbook.