Secrets Management Secrets Management Last updated: 2026-02-17 Source: src/drop-app/src/lib/secrets.ts Overview Drop uses an abstracted secrets management system with pluggable providers. The system is backward compatible -- if no secrets provider is configured, it reads directly from environment variables (existing behavior). Provider Selection The provider is selected automatically based on which environment variables are set: Priority Condition Provider Description 1 DOPPLER_TOKEN set Doppler Cloud secrets manager via Doppler API 2 AWS_SECRET_ARN set AWS AWS Secrets Manager (requires AWS SDK) 3 (default) env Reads from process.env Initialization (call once at app startup): import { initSecrets } from '@/lib/secrets'; // Auto-detect provider based on env vars initSecrets(); // Optional: custom cache TTL (default 5 minutes) initSecrets({ ttlMs: 10 * 60 * 1000 }); // 10 minutes Usage: import { getSecret } from '@/lib/secrets'; const jwtSecret = await getSecret('JWT_SECRET'); const dbUrl = await getSecret('DATABASE_URL'); Caching All secret values are cached in memory with a configurable TTL (default: 5 minutes). This reduces API calls to external providers while ensuring secrets are refreshed periodically. Cache is cleared on initSecrets() call Cache entries expire individually based on TTL If a provider returns undefined , the system falls back to process.env Rotation Procedures JWT_SECRET Impact: All active user sessions will be invalidated. Generate new secret: openssl rand -base64 48 Update in secrets provider (Doppler/AWS/env) Call rotateSecret('JWT_SECRET', newValue) or restart the app Users will need to log in again Recommended frequency: Every 90 days or after a suspected compromise. DATABASE_URL (PostgreSQL credentials) Impact: Application loses DB connectivity until updated. Create new PostgreSQL credentials Update PostgreSQL user: ALTER USER drop WITH PASSWORD 'new_value'; Update DATABASE_URL in secrets provider with new credentials Restart the application (or call rotateSecret ) Recommended frequency: Every 90 days. SENTRY_DSN Status: REMOVED (MC #1271 — Sentry deinstalled) SLACK_WEBHOOK_URL Impact: Alerts stop sending to Slack until updated. Create new incoming webhook in Slack workspace Update SLACK_WEBHOOK_URL in secrets provider Restart the application Recommended frequency: Only on suspected compromise. Open Banking API Keys Impact: Bank connectivity (AISP/PISP) stops working. Regenerate keys in the Open Banking provider dashboard Update the relevant env vars in secrets provider Restart the application Verify bank account connectivity via /api/health Recommended frequency: Per provider policy or every 180 days. Environment Setup per Provider Environment Variables (Default) No setup required. Set secrets as environment variables: # .env.local (development) JWT_SECRET=dev-secret-do-not-use-in-production # Production (Fly.io) fly secrets set JWT_SECRET="$(openssl rand -base64 48)" fly secrets set DATABASE_URL="postgresql://..." # Production (Docker) # Pass via -e flags or docker-compose environment section Doppler Create account at doppler.com Create project "drop" with environments (dev, staging, production) Add all secrets in the Doppler dashboard Generate a service token for each environment Set DOPPLER_TOKEN in your deployment: # Fly.io fly secrets set DOPPLER_TOKEN="dp.st.production.xxxxx" # Docker (pass as environment variable) AWS Secrets Manager Create a secret in AWS Secrets Manager (JSON format): { "JWT_SECRET": "your-jwt-secret", "DATABASE_URL": "postgresql://...", "SLACK_WEBHOOK_URL": "https://..." } Note the secret ARN Ensure the application has IAM permissions for secretsmanager:GetSecretValue Install the AWS SDK: npm install @aws-sdk/client-secrets-manager Set AWS_SECRET_ARN in your deployment Audit Trail All secret rotation events are logged to the audit_log table: Field Value action secret_rotated resource_type secret resource_id Secret key name (e.g., JWT_SECRET ) details JSON with provider name and rotation timestamp Query rotation history: SELECT * FROM audit_log WHERE action = 'secret_rotated' ORDER BY timestamp DESC;