# Environment Variables Reference

Complete reference for all environment variables used in Agencio Predict. Last updated: 2026-04-23.

---

## Quick Reference by Deployment Target

| Target | Variables Needed |
|--------|------------------|
| **Amplify (Frontend)** | `NEXT_PUBLIC_*`, `JWT_SECRET`, `DATABASE_URL`, `REDIS_URL`, `COGNITO_*`, `TURNSTILE_*`, all API keys |
| **EC2 Backend** | `DATABASE_URL`, `REDIS_URL`, `JWT_SECRET` (set via docker-compose or systemd) |
| **GitHub Actions** | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION` |

---

## 1. Core Infrastructure

### Required

| Variable | Description | Example |
|----------|-------------|---------|
| `NODE_ENV` | Environment mode | `production` / `development` |
| `JWT_SECRET` | JWT signing secret (min 32 chars) | `openssl rand -base64 32` |
| `DATABASE_URL` | PostgreSQL connection string | `postgresql://user:pass@host:5432/predict_db` |
| `REDIS_URL` | Redis connection string | `redis://host:6379` |

### Optional

| Variable | Description | Default |
|----------|-------------|---------|
| `DATABASE_POOL_MIN` | Min DB connections | `2` |
| `DATABASE_POOL_MAX` | Max DB connections | `10` (use `30` for high traffic) |
| `CREDENTIALS_ENCRYPTION_KEY` | AES key for credential storage (32 bytes hex) | - |
| `API_VERSION` | API version prefix | `v1` |
| `NEXT_PUBLIC_APP_URL` | Public app URL | `http://localhost:3000` |

---

## 2. Authentication

### Provider Selection

| Variable | Description | Options |
|----------|-------------|---------|
| `AUTH_PROVIDER` | Auth backend to use | `local` / `cognito` / `agencio` |
| `ALLOW_DEV_AUTH_BYPASS` | Dev-only auth bypass | `false` (NEVER enable in production) |

### AWS Cognito (when `AUTH_PROVIDER=cognito`)

| Variable | Description | Example |
|----------|-------------|---------|
| `COGNITO_USER_POOL_ID` | Cognito User Pool ID | `ap-southeast-2_XXXXXXXXX` |
| `COGNITO_CLIENT_ID` | Cognito App Client ID | `xxxxxxxxxxxxxxxxxxxxxxxxxx` |
| `COGNITO_REGION` | AWS region for Cognito | `ap-southeast-2` |
| `COGNITO_DOMAIN` | Cognito hosted UI domain | `agencio-predict.auth.ap-southeast-2.amazoncognito.com` |
| `COGNITO_ENDPOINT` | Custom endpoint (local dev only) | `http://localhost:9080` |

### Agencio Auth Service (when `AUTH_PROVIDER=agencio`)

| Variable | Description | Example |
|----------|-------------|---------|
| `AGENCIO_AUTH_URL` | Auth service URL | `https://auth.agencio.cloud` |
| `AGENCIO_AUTH_API_KEY` | Auth service API key | - |
| `AUTH_SERVICE_URL` | Legacy auth URL | `http://localhost:4000` |

### Anti-Bot (Cloudflare Turnstile)

| Variable | Description | Example |
|----------|-------------|---------|
| `NEXT_PUBLIC_TURNSTILE_SITE_KEY` | Turnstile site key (public) | `0x4AAAAAAA...` |
| `TURNSTILE_SECRET_KEY` | Turnstile secret key | `0x4AAAAAAA...` |

**Test Keys (always pass):**
- Site: `1x00000000000000000000AA`
- Secret: `1x0000000000000000000000000000000AA`

---

## 3. Object Storage

### MinIO (Development)

| Variable | Description | Default |
|----------|-------------|---------|
| `STORAGE_PROVIDER` | Storage backend | `minio` |
| `MINIO_ENDPOINT` | MinIO host | `localhost` |
| `MINIO_PORT` | MinIO port | `9000` |
| `MINIO_USE_SSL` | Use HTTPS | `false` |
| `MINIO_ACCESS_KEY` | Access key | `minioadmin` |
| `MINIO_SECRET_KEY` | Secret key | `minioadmin` |

### AWS S3 (Production)

| Variable | Description | Example |
|----------|-------------|---------|
| `STORAGE_PROVIDER` | Storage backend | `s3` |
| `AWS_REGION` | AWS region | `ap-southeast-2` |
| `AWS_ACCESS_KEY_ID` | IAM access key | `AKIA...` |
| `AWS_SECRET_ACCESS_KEY` | IAM secret key | - |
| `AWS_S3_BUCKET` | S3 bucket name | `agencio-predict-files` |
| `S3_BUCKET_PREFIX` | Bucket prefix | `agencio-predict` |

---

## 4. AI Services

| Variable | Description | Required |
|----------|-------------|----------|
| `ANTHROPIC_API_KEY` | Claude API key | Yes (or use Bedrock) |
| `CLAUDE_API_KEY` | Alias for ANTHROPIC_API_KEY | - |
| `USE_BEDROCK` | Use AWS Bedrock instead | `true` / `false` |
| `LLM_PROVIDER` | LLM backend | `claude` / `bedrock` / `router` |
| `LLMROUTER_BASE_URL` | Agencio LLM Router URL | - |
| `LLMROUTER_API_KEY` | LLM Router API key | - |

---

## 5. Market Data

### Price Data

| Variable | Description | Free Tier | Required |
|----------|-------------|-----------|----------|
| `FINNHUB_API_KEY` | US equity quotes, news | 60 req/min | No (falls back to Yahoo) |
| `POLYGON_API_KEY` | FX OHLC, equity ticks | 5 req/min EOD | No (falls back to Frankfurter) |

### Derivatives & Macro

| Variable | Description | Free Tier | Required |
|----------|-------------|-----------|----------|
| `FRED_API_KEY` | Treasury yields, CPI, fed funds | Unlimited | No |
| `COINGLASS_API_KEY` | Crypto liquidations | Limited | No |

### Prediction Markets

| Variable | Description | Required |
|----------|-------------|----------|
| `METACULUS_TOKEN` | Metaculus API token | No |

**Note:** Polymarket, Kalshi, CoinGecko, Binance, Yahoo Finance, Frankfurter require no API keys.

---

## 6. News & Social

| Variable | Description | Free Tier | Required |
|----------|-------------|-----------|----------|
| `NEWSAPI_KEY` | News articles | 100 req/day | No |
| `GITHUB_TOKEN` | GitHub trending repos | Higher rate limits | No |
| `TWITTER_BEARER_TOKEN` | Twitter/X sentiment | $100/mo Basic tier | No |

---

## 7. Ad Platforms (Marketing Module)

### Google Ads

| Variable | Description |
|----------|-------------|
| `GOOGLE_ADS_CLIENT_ID` | OAuth client ID |
| `GOOGLE_ADS_CLIENT_SECRET` | OAuth client secret |
| `GOOGLE_ADS_DEVELOPER_TOKEN` | Developer token |
| `GOOGLE_ADS_REFRESH_TOKEN` | OAuth refresh token |
| `GOOGLE_ADS_CUSTOMER_ID` | Customer ID (format: 000-000-0000) |
| `GOOGLE_ADS_LOGIN_CUSTOMER_ID` | MCC login customer ID |

### Meta (Facebook/Instagram)

| Variable | Description |
|----------|-------------|
| `META_APP_ID` | App ID |
| `META_APP_SECRET` | App secret |
| `META_ACCESS_TOKEN` | Access token |
| `META_AD_ACCOUNT_ID` | Ad account ID (format: act_0000000000) |
| `META_PIXEL_ID` | Pixel ID |

### LinkedIn

| Variable | Description |
|----------|-------------|
| `LINKEDIN_CLIENT_ID` | OAuth client ID |
| `LINKEDIN_CLIENT_SECRET` | OAuth client secret |
| `LINKEDIN_ACCESS_TOKEN` | Access token |
| `LINKEDIN_AD_ACCOUNT_ID` | Ad account ID |

### TikTok

| Variable | Description |
|----------|-------------|
| `TIKTOK_APP_ID` | App ID |
| `TIKTOK_APP_SECRET` | App secret |
| `TIKTOK_ACCESS_TOKEN` | Access token |
| `TIKTOK_ADVERTISER_ID` | Advertiser ID |

### Pinterest

| Variable | Description |
|----------|-------------|
| `PINTEREST_APP_ID` | App ID |
| `PINTEREST_APP_SECRET` | App secret |
| `PINTEREST_ACCESS_TOKEN` | Access token |
| `PINTEREST_AD_ACCOUNT_ID` | Ad account ID |

---

## 8. Billing (Stripe)

| Variable | Description | Required |
|----------|-------------|----------|
| `STRIPE_SECRET_KEY` | Stripe secret key | For billing features |
| `STRIPE_WEBHOOK_SECRET` | Webhook signing secret | For webhook verification |

**Test mode keys start with `sk_test_`**

---

## 9. Email (Azure Graph / Microsoft 365)

| Variable | Description |
|----------|-------------|
| `AZURE_TENANT_ID` | Azure AD tenant ID |
| `AZURE_CLIENT_ID` | App registration client ID |
| `AZURE_CLIENT_SECRET` | App registration secret |
| `AZURE_SENDER_EMAIL` | Sender email address |
| `AZURE_GRAPH_SENDER_EMAIL` | Alias for sender email |

**Requires Azure AD app registration with `Mail.Send` permission.**

---

## 10. SMS (Twilio)

| Variable | Description |
|----------|-------------|
| `TWILIO_ACCOUNT_SID` | Account SID (starts with `AC`) |
| `TWILIO_AUTH_TOKEN` | Auth token |
| `TWILIO_PHONE_NUMBER` | Sender phone number (E.164 format) |

---

## 11. Push Notifications (VAPID)

| Variable | Description |
|----------|-------------|
| `VAPID_PUBLIC_KEY` | Public key (Base64) |
| `VAPID_PRIVATE_KEY` | Private key (Base64) |
| `VAPID_EMAIL` | Contact email |
| `VAPID_SUBJECT` | Subject identifier (mailto:) |

**Generate keys:** `npx web-push generate-vapid-keys`

---

## 12. AWS Secrets Manager (Production)

| Variable | Description |
|----------|-------------|
| `USE_SECRETS_MANAGER` | Enable Secrets Manager | `true` / `false` |
| `AWS_SECRETS_REGION` | Secrets Manager region |
| `SECRETS_PREFIX` | Secret name prefix | `predict/` |
| `SECRETS_MANAGER_ENDPOINT` | Custom endpoint (local dev) |

---

## 13. Development Only

| Variable | Description | Default |
|----------|-------------|---------|
| `WATCHPACK_POLLING` | Enable file polling in Docker | `true` |
| `NODE_OPTIONS` | Node.js options | `--max-old-space-size=6144` |
| `SCHEDULER_SKIP_LOCK` | Skip Redis leader lock | `true` |
| `INTEL_SERVICE_URL` | Intel service endpoint | `http://localhost:4001` |

---

## Mock Values for Testing

Use these placeholder values when you don't have real credentials yet. The app will start but those features won't work.

```bash
# Ad Platforms
GOOGLE_ADS_CLIENT_ID=000000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
GOOGLE_ADS_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxx
GOOGLE_ADS_DEVELOPER_TOKEN=xxxxxxxxxxxxxxxxxxxx
GOOGLE_ADS_REFRESH_TOKEN=1//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
GOOGLE_ADS_CUSTOMER_ID=000-000-0000
GOOGLE_ADS_LOGIN_CUSTOMER_ID=000-000-0000

META_APP_ID=000000000000000
META_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
META_ACCESS_TOKEN=EAAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
META_AD_ACCOUNT_ID=act_0000000000000000
META_PIXEL_ID=0000000000000000

LINKEDIN_CLIENT_ID=xxxxxxxxxxxxxx
LINKEDIN_CLIENT_SECRET=xxxxxxxxxxxxxxxx
LINKEDIN_ACCESS_TOKEN=AQxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
LINKEDIN_AD_ACCOUNT_ID=000000000

TIKTOK_APP_ID=0000000000000000000
TIKTOK_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TIKTOK_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TIKTOK_ADVERTISER_ID=0000000000000000000

PINTEREST_APP_ID=0000000000000000000
PINTEREST_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
PINTEREST_ACCESS_TOKEN=pina_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
PINTEREST_AD_ACCOUNT_ID=000000000000000000

# Email
AZURE_TENANT_ID=00000000-0000-0000-0000-000000000000
AZURE_CLIENT_ID=00000000-0000-0000-0000-000000000000
AZURE_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AZURE_GRAPH_SENDER_EMAIL=noreply@agencio.cloud

# SMS
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_PHONE_NUMBER=+10000000000

# Push
VAPID_PUBLIC_KEY=BPxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
VAPID_PRIVATE_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
VAPID_SUBJECT=mailto:admin@agencio.cloud
```

---

## Amplify Environment Variables Checklist

These are the variables you should configure in AWS Amplify Console:

### Critical (App Won't Work Without)

- [ ] `JWT_SECRET`
- [ ] `DATABASE_URL`
- [ ] `REDIS_URL`
- [ ] `AUTH_PROVIDER`
- [ ] `COGNITO_USER_POOL_ID`
- [ ] `COGNITO_CLIENT_ID`
- [ ] `COGNITO_REGION`

### Authentication

- [ ] `COGNITO_DOMAIN`
- [ ] `NEXT_PUBLIC_TURNSTILE_SITE_KEY`
- [ ] `TURNSTILE_SECRET_KEY`

### AI Features

- [ ] `ANTHROPIC_API_KEY`

### Market Data (Optional but Recommended)

- [ ] `FINNHUB_API_KEY`
- [ ] `POLYGON_API_KEY`
- [ ] `FRED_API_KEY`

### Billing

- [ ] `STRIPE_SECRET_KEY`
- [ ] `STRIPE_WEBHOOK_SECRET`

### All Others

See sections 7-11 above for ad platforms, email, SMS, and push notifications.

---

## Security Notes

1. **Never commit real secrets** to git. Use `.env.local` (gitignored) for local dev.
2. **NEXT_PUBLIC_* variables** are exposed to the browser. Only use for non-sensitive values.
3. **ALLOW_DEV_AUTH_BYPASS** must NEVER be `true` in production.
4. **Rotate secrets regularly**, especially `JWT_SECRET` and API keys.
5. Use **AWS Secrets Manager** in production for sensitive credentials.
