Single-user application running on a private server. Not exposed to the public internet. No multi-tenant concerns.
None. All API routes are open. The only exception is /api/cron, which requires a CRON_SECRET bearer token in the Authorization header.
Private keys are encrypted at rest using AES-256-GCM:
- Algorithm: AES-256-GCM (authenticated encryption)
- Key: 32-byte key from
ENCRYPTION_KEYenv var (64 hex chars) - Storage:
Bot.encryptedKeyfield in database - Decryption: Only at runtime via
decrypt()inlib/encryption.ts - Derivation: Wallet address derived from decrypted key via
privateKeyToAccount(viem)
Sensitive values that must be protected:
ENCRYPTION_KEY— master encryption keyDATABASE_URL— database connection stringCRON_SECRET— cron endpoint authCRON_ALERT_WEBHOOK_URL— optional Discord webhook for cron failure alerts
Per-bot Discord webhook URLs are stored in the bots.discord_webhook_url column (not an env var).
- CORS: Not a public API
- CSRF: No browser-based auth sessions
- Rate limiting: Single user
- Input sanitization for XSS: API-only interactions, no user-generated HTML rendering