# ============================================
# Database (MongoDB)
# ============================================
# The application reads the connection string from MONGODB_URI only — no
# connection string is hardcoded anywhere in the source.
#
# For a self-hosted MongoDB (docker-compose.prod.yml / docker-compose.dev.yml):
#   set DB_USER / DB_PASSWORD / DB_NAME below. docker compose injects them into
#   the mongodb container AND builds the backend MONGODB_URI from them, so you do
#   NOT put a password-bearing MONGODB_URI in the compose file or a committed env.
# For MongoDB Atlas (or any external DB): leave DB_* empty and set MONGODB_URI
#   directly in your (git-ignored) .env.
#
# IMPORTANT for persistence + local/live sync:
#   • Point EVERY environment (local + live) at the SAME MongoDB so configuration
#     (settings, platform credentials, etc.) is shared and survives restarts.
#   • Prefer the NON-SRV connection string. The mongodb+srv:// form needs a DNS
#     SRV lookup that frequently times out on servers / behind firewalls; when it
#     fails the app cannot connect. Atlas → Connect → "Drivers" shows the standard
#     (non-SRV) URI listing the shard hosts, e.g.:
#     mongodb://user:pass@shard0:27017,shard1:27017,shard2:27017/<db>?replicaSet=atlas-xxxx&authSource=admin&tls=true
#   • Whitelist the server IP in Atlas → Network Access.
# If MONGODB_URI is set but unreachable, the server now FAILS FAST (it will not
# silently run on an in-memory mock that loses data on restart).
DB_USER=santoshshimpankarukvalley_db_user
DB_PASSWORD=pllUTaY0EHhCpl6n
DB_NAME=eduatlas
# ---------------------------------------------------------------------------
# EduAtlas pivot: this app no longer connects to the shared Mengo/ai-cmo Atlas
# cluster below (kept here, commented out, only for reference/rollback — that
# cluster is untouched and still holds the marketing product's data for any
# other developer/deployment still using it). EduAtlas gets its own, dedicated
# Atlas cluster instead, so nothing here can collide with or affect that
# cluster in any way.
#
# MONGODB_URI=mongodb+srv://santoshshimpankarukvalley_db_user:pllUTaY0EHhCpl6n@cluster0.hxelmbl.mongodb.net
#
# Dedicated EduAtlas Atlas cluster (separate project/cluster from Mengo above).
# /eduatlas names the database explicitly rather than relying on the driver's
# "test" default, matching DB_NAME above.
MONGODB_URI=mongodb+srv://santoshshimpankarukvalley_db_user:SJcB1HnlurBmV9Yg@cluster0.tek536k.mongodb.net/eduatlas

# Dev-only escape hatch: run on the in-memory mock database when Mongo is
# unreachable (data is NOT persisted; lost on restart). Never enable in prod.
# Leave unset for normal use — the app auto-uses the mock only when MONGODB_URI
# is not set at all.
ALLOW_MOCK_DB=

# One-off super-admin migration script (src/backend/scripts/migrate-superadmin.js)
# reads these instead of hardcoded connection strings. Set only when running it.
OLD_MONGODB_URI=
NEW_MONGODB_URI=mongodb+srv://santoshshimpankarukvalley_db_user:pllUTaY0EHhCpl6n@cluster0.hxelmbl.mongodb.net

# Super Admin bootstrap — src/backend/src/index.js creates this account
# automatically on server startup, ONLY if no user with role 'super-admin'
# already exists in the database. Safe to leave set permanently; it is a
# no-op once the account exists.
SUPER_ADMIN_EMAIL=superadmin@eduatlas.com
SUPER_ADMIN_PASSWORD=02mLBxpWmsWJ

# Redis
REDIS_URL=redis://localhost:6379

# JWT
JWT_SECRET=your-super-secret-key-change-in-production
JWT_EXPIRES_IN=30d

# Encryption (services/utils/encryption.js + services/auth/secretBox.js — the
# 2FA TOTP secret box). MUST be exactly 64 hex characters (32 bytes); a fresh
# one is generated with:
#   node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Changing this after data has been encrypted under it makes that data
# undecryptable — set it once per environment and keep it stable.
ENCRYPTION_KEY=6c27c664d4a21521e04411ea9e8948cbcd907a40012917f293431124998fd9e7

# Signed file download links (services/fileUrlSigner.js) — HMAC secret for
# time-limited /api/files/download URLs. Generate a fresh one for production
# with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
FILE_URL_SIGNING_SECRET=fc4648410a5664d79e4622adb1bf4aa1cd8508665d6e272a48f9313466918298
FILE_URL_EXPIRY_SECONDS=900

# API
API_PORT=3001
API_URL=http://localhost:3001

# Frontend
FRONTEND_PORT=5173
FRONTEND_URL=http://localhost:5173

# ML Service
ML_PORT=5000
ML_API_URL=http://localhost:5000

# AWS (if using)
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=us-east-1
S3_BUCKET_NAME=

# CSP — extra domains allowed for img-src in generated website/landing-page previews.
# Comma-separated origins, e.g. CSP_IMG_SRC_EXTRA=https://cdn.example.com,https://assets.example.com
# Leave empty unless your deployment serves brand assets or AI images from an external CDN or S3 bucket.
CSP_IMG_SRC_EXTRA=

# CSP — extra domains allowed for connect-src (XHR/fetch/WebSocket) in generated previews.
# Comma-separated origins, e.g. CSP_CONNECT_SRC_EXTRA=https://api.external-service.com,wss://ws.example.com
# Leave empty unless your deployment makes API calls to external services from generated pages.
CSP_CONNECT_SRC_EXTRA=

# CSP — extra domains allowed for script-src in generated website/landing-page previews.
# The CSP uses per-request nonces for inline scripts — 'unsafe-inline' is NOT present.
# Comma-separated origins, e.g. CSP_SCRIPT_SRC_EXTRA=https://cdn.example.com,https://widgets.example.com
# Leave empty unless your deployment loads external scripts from domains not listed above.
CSP_SCRIPT_SRC_EXTRA=

# CSP — extra domains allowed for style-src in generated website/landing-page previews.
# The CSP uses per-request nonces for inline styles — 'unsafe-inline' is NOT present.
# Inline style= attributes are extracted to a nonce-bearing <style> block at serve time.
# Comma-separated origins, e.g. CSP_STYLE_SRC_EXTRA=https://cdn.example.com
# Leave empty unless your deployment loads external stylesheets from domains not listed above.
CSP_STYLE_SRC_EXTRA=

# CSP — extra origins allowed to embed generated previews in iframes (frame-ancestors).
# Comma-separated origins, e.g. CSP_FRAME_ANCESTORS_EXTRA=https://staging.example.com,https://admin.example.com
# Leave empty unless your deployment embeds previews on additional domains beyond the app's own origin.
CSP_FRAME_ANCESTORS_EXTRA=

# CORS — extra origins allowed to submit leads from published landing pages.
# The lead capture endpoint (/api/landing-page-leads) uses origin-validated CORS
# instead of a wildcard (*). The app's own origins (FRONTEND_URL, production domain,
# ALLOWED_APP_ORIGINS) are always allowed. Add landing page hosting domains here
# (e.g. Netlify, Vercel, custom domains) so cross-origin form submissions work.
# Comma-separated origins, e.g. CORS_LEAD_CAPTURE_ORIGINS=https://promo.example.com,https://pages.example.com
# Leave empty unless landing pages are hosted on domains not covered by the app's origins.
CORS_LEAD_CAPTURE_ORIGINS=

# Monitoring
SENTRY_DSN=
LOG_LEVEL=debug

# Feature Flags
FEATURE_NEW_DASHBOARD=false

# Payment Gateway — Razorpay (for INR / India payments)
# Get your keys from https://dashboard.razorpay.com → Settings → API Keys
RAZORPAY_KEY_ID=
RAZORPAY_KEY_SECRET=
RAZORPAY_WEBHOOK_SECRET=

# Payment Gateway — Stripe (for USD / AED / international payments)
# Get your keys from https://dashboard.stripe.com → Developers → API Keys
STRIPE_PUBLISHABLE_KEY=
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
# Where Stripe sends the buyer after checkout. Left unset, redirects go to the
# production domain (https://app.mengoengine.com) — a localhost FRONTEND_URL is
# ignored for redirects because Stripe cannot reach it. Set this to a public
# tunnel URL (e.g. ngrok) to test the return flow locally.
# STRIPE_REDIRECT_BASE_URL=

# Email Integration — Brevo (formerly Sendinblue)
# Get your API key from https://app.brevo.com/settings/keys/api
BREVO_API_KEY=

# Email Integration — Zoho Campaigns (OAuth 2.0)
# Register your app at https://api-console.zoho.com/
ZOHO_CLIENT_ID=
ZOHO_CLIENT_SECRET=
# Must match an Authorized Redirect URI registered on the Zoho API console client
# above, character for character. Leave blank to derive it from
# PUBLIC_URL/APP_BASE_URL/BACKEND_URL (or http://localhost:$PORT) + the callback path.
ZOHO_REDIRECT_URI=http://localhost:3101/api/email-integration/zoho/callback

# Social Media OS — Zoho Social (OAuth 2.0, per-admin portal connections)
# PRIMARY credential source: each Admin saves their own Zoho client credentials
# (Client ID + Client Secret) in the app (Connectivity → Zoho Social) — stored
# encrypted in the database per admin. The variables below are an OPTIONAL
# platform-wide fallback used only for admins who never saved their own.
# A fallback client must be registered at https://api-console.zoho.com/ with
# the redirect URI below.
ZOHO_SOCIAL_CLIENT_ID=
ZOHO_SOCIAL_CLIENT_SECRET=
ZOHO_SOCIAL_REDIRECT_URI=http://localhost:3101/api/zoho-social/auth/callback
# Optional — defaults to least-privilege scopes; override to extend.
# ZOHO_SOCIAL_SCOPES=ZohoSocial.Organization.READ,ZohoSocial.Integration.READ,ZohoSocial.Publish.READ,ZohoSocial.Publish.CREATE,ZohoSocial.Media.READ,ZohoSocial.Media.CREATE

# Google OAuth — Google Business Profile (GMB module)
# Create an OAuth client at https://console.cloud.google.com/apis/credentials
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URL=http://localhost:3101/api/gmb/auth/callback

# Google Business Profile Account ID (optional — bypasses Account Management API)
# Required when the My Business Account Management API has a 0 QPM quota
# (new/unapproved projects). Find your account ID at:
#   https://business.google.com/settings → look for the account number in the URL
#   or use the Google Business Profile API explorer at:
#   https://developers.google.com/my-business/reference/accountmanagement/rest/v1/accounts/list
# Example: GOOGLE_BUSINESS_ACCOUNT_ID=1234567890
GOOGLE_BUSINESS_ACCOUNT_ID=


# n8n workflow automation (optional)
# URL of the n8n instance (default: http://localhost:5678)
N8N_BASE_URL=http://localhost:5678
# API key generated in n8n Settings → API (leave empty if n8n API auth is disabled)
N8N_API_KEY=

# Zapier automation (fallback — preferred: configure in Super Admin → Settings)
# These env vars are used only if no DB-stored config exists.
ZAPIER_BASE_URL=https://api.zapier.com
ZAPIER_API_KEY=

    
# ============================================
# Suno AI (Audio Content Generation)
# ============================================
# Suno API key for generating audio content (songs/music).
# Obtain from https://suno.ai or your Suno API provider.
# ⚠️ NEVER commit actual API keys to git. Use a git-ignored .env file.
# SUNO_API_BASE=https://api.suno.ai/v1
SUNO_API_BASE=https://api.sunoapi.org

SUNO_API_KEY=aae086200d34b5d2a17d470b11147902

# ============================================
# Testimonial AI Media (avatar video / voice audio)
# ============================================
# Optional. When unset, the Testimonials "Generate with AI" flow reports
# "AI media generation is not configured" and users upload media instead —
# nothing breaks. Set a key to enable generation via the provider abstraction
# (src/backend/src/services/testimonialMedia/avatarMediaProvider.ts).
# ⚠️ NEVER commit real keys — secrets stay backend-only.
#
# Avatar (talking-head) VIDEO — HeyGen:
# HEYGEN_API_KEY=
# HEYGEN_API_BASE=https://api.heygen.com
#
# Voice-over AUDIO — ElevenLabs:
# ELEVENLABS_API_KEY=
# ELEVENLABS_API_BASE=https://api.elevenlabs.io

# ============================================================
# STORAGE QUOTAS
# ============================================================
#
# Whether quotas actually BLOCK uploads is NOT set here -- it is a Super Admin
# setting, changed at Super Admin -> Storage Report without a restart. The
# decision belongs to whoever is reading that report.
#
# Only the worker's timing lives here.

# How often the reconciliation worker sweeps (ms). It repairs drifted counters,
# adopts files that predate the feature, and reports anything on disk with no
# ledger row. Default: daily.
# STORAGE_RECONCILE_INTERVAL_MS=86400000

# How long a released file's ledger row is kept before being purged (days).
# STORAGE_TOMBSTONE_RETENTION_DAYS=30