Removes hardcoded fallback secrets and makes a misconfigured deploy fail loudly instead of silently falling back to development defaults. - Remove insecure JWT fallback secrets (messages.module, configuration) - Remove the 'default-secret' fallback for the 2FA TOTP encryption key and allow a dedicated TWO_FACTOR_ENCRYPTION_KEY so rotating JWT_SECRET no longer locks out every 2FA user (see docs/2fa-key-rotation.md) - Require EMAIL_API_URL; drop the hardcoded vendor email endpoint - Drive WebSocket CORS from CORS_ORIGINS instead of origin:'*' - Load .env before any Nest module is imported (src/load-env.ts). Decorator arguments evaluate at import time, so the gateway previously froze its CORS config to the localhost fallback even when CORS_ORIGINS was set - Add boot-time env validation: missing required vars, weak JWT_SECRET, and inverted access/refresh token lifetimes now abort startup - Enable Redis TLS certificate verification - Require ADMIN_EMAIL/ADMIN_PASSWORD for the seed; remove the published default super-admin credentials and stop printing them - Add the initial Prisma migration and stop gitignoring prisma/migrations - Make .env.example an accurate configuration contract (admin bootstrap, REDIS_TLS, S3_ENDPOINT, 2FA key, Firebase path; drop the dead SMTP block) - Add handover documentation: architecture, ER model, sequence and data-flow diagrams, 2FA key rotation runbook Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
104 lines
3.9 KiB
Plaintext
104 lines
3.9 KiB
Plaintext
# ===========================================
|
|
# Real Estate Agent Platform - Backend Environment Variables
|
|
# Copy this file to .env and fill in your values
|
|
# ===========================================
|
|
|
|
# Application
|
|
NODE_ENV=development
|
|
PORT=3001
|
|
APP_NAME="Real Estate Agent Platform"
|
|
API_URL=http://localhost:3001
|
|
FRONTEND_URL=http://localhost:3000
|
|
ADMIN_URL=http://localhost:3002
|
|
|
|
# Database (PostgreSQL)
|
|
DATABASE_URL="postgresql://postgres:password@localhost:5432/real_estate_db?schema=public"
|
|
|
|
# JWT Authentication
|
|
# Required. Minimum 32 chars in production; boot fails if shorter.
|
|
JWT_SECRET=your-super-secret-jwt-key-change-in-production
|
|
# JWT_REFRESH_EXPIRATION MUST be longer than JWT_ACCESS_EXPIRATION.
|
|
JWT_ACCESS_EXPIRATION=15m
|
|
JWT_REFRESH_EXPIRATION=7d
|
|
|
|
# Two-Factor Authentication
|
|
# Key used to encrypt stored TOTP secrets. Optional — falls back to JWT_SECRET.
|
|
# Set this BEFORE enabling 2FA in a new environment: once secrets are encrypted
|
|
# under JWT_SECRET, rotating JWT_SECRET without re-encrypting locks out every
|
|
# 2FA user. See docs/2fa-key-rotation.md.
|
|
TWO_FACTOR_ENCRYPTION_KEY=
|
|
|
|
# Admin bootstrap (used by `npm run db:seed` only)
|
|
# Required by the seed — there are no defaults. Password must be >= 12 chars.
|
|
ADMIN_EMAIL=admin@example.com
|
|
ADMIN_PASSWORD=change-me-before-seeding
|
|
|
|
# Password Hashing
|
|
BCRYPT_SALT_ROUNDS=12
|
|
|
|
# Google OAuth
|
|
# NOTE: Google sign-in is handled by NextAuth in the frontend, which posts the
|
|
# verified profile to POST /auth/social. These backend vars are currently NOT
|
|
# consumed by the backend; the authoritative values live in the frontend env.
|
|
GOOGLE_CLIENT_ID=your-google-client-id
|
|
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
|
GOOGLE_CALLBACK_URL=http://localhost:3001/auth/google/callback
|
|
|
|
# Facebook OAuth — NOT IN USE (Google is the only enabled social provider).
|
|
# Kept only so config/configuration.ts keeps type-checking. Leave blank.
|
|
FACEBOOK_APP_ID=
|
|
FACEBOOK_APP_SECRET=
|
|
FACEBOOK_CALLBACK_URL=
|
|
|
|
# AWS S3 (File Storage)
|
|
AWS_ACCESS_KEY_ID=your-aws-access-key
|
|
AWS_SECRET_ACCESS_KEY=your-aws-secret-key
|
|
AWS_REGION=us-east-1
|
|
AWS_S3_BUCKET=your-s3-bucket-name
|
|
S3_FOLDER_PREFIX=development # Root folder for all uploads (e.g., 'development', 'staging', 'production')
|
|
# Custom endpoint for S3-compatible storage (DigitalOcean Spaces, MinIO,
|
|
# Contabo). Leave blank for real AWS S3.
|
|
S3_ENDPOINT=
|
|
|
|
# Email (REQUIRED — boot fails without it)
|
|
# The app POSTs JSON to this endpoint to send all transactional email.
|
|
# There is no SMTP path in the code: MAIL_*/SMTP_* variables are NOT read.
|
|
EMAIL_API_URL=https://your-email-provider.example.com/v1/send
|
|
|
|
# Stripe (Payments)
|
|
STRIPE_SECRET_KEY=sk_test_your-stripe-secret-key
|
|
STRIPE_WEBHOOK_SECRET=whsec_your-webhook-secret
|
|
STRIPE_PUBLISHABLE_KEY=pk_test_your-stripe-publishable-key
|
|
|
|
# Firebase (Push Notifications)
|
|
# Either point at a service-account JSON file (preferred, path is relative to
|
|
# the process working directory) or supply the three vars below. If neither is
|
|
# present the app still boots and push notifications are silently disabled.
|
|
FIREBASE_SERVICE_ACCOUNT_KEY_PATH=./firebase-service-account.json
|
|
FIREBASE_PROJECT_ID=your-firebase-project-id
|
|
FIREBASE_CLIENT_EMAIL=firebase-adminsdk@your-project.iam.gserviceaccount.com
|
|
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nYour-Private-Key\n-----END PRIVATE KEY-----"
|
|
|
|
# Redis (Caching & Queue)
|
|
REDIS_HOST=localhost
|
|
REDIS_PORT=6379
|
|
REDIS_PASSWORD=
|
|
REDIS_DB=0
|
|
# Set to "true" for managed Redis/Valkey over TLS. Certificates are verified —
|
|
# a self-signed cert will be rejected.
|
|
REDIS_TLS=false
|
|
|
|
# Rate Limiting
|
|
THROTTLE_TTL=60
|
|
THROTTLE_LIMIT=100
|
|
|
|
# Logging
|
|
LOG_LEVEL=debug
|
|
|
|
# CORS
|
|
# REQUIRED in production (boot fails without it). Consumed by both the HTTP
|
|
# server and the WebSocket gateway — if unset, real-time messaging only accepts
|
|
# localhost origins and every browser connection from the live domain is
|
|
# rejected.
|
|
CORS_ORIGINS=http://localhost:3000,http://localhost:3002
|