Phase 1 & 2: Authentication and Children Management
Completed Features:
- Full JWT authentication system with refresh tokens
- User registration and login with device fingerprinting
- Child profile CRUD operations with permission-based access
- Family management with roles and permissions
- Database migrations for core auth and family structure
- Comprehensive test coverage (37 unit + E2E tests)
Tech Stack:
- NestJS backend with TypeORM
- PostgreSQL database
- JWT authentication with Passport
- bcrypt password hashing
- Docker Compose for infrastructure
🤖 Generated with Claude Code
This commit is contained in:
507
docs/maternal-app-env-config.md
Normal file
507
docs/maternal-app-env-config.md
Normal file
@@ -0,0 +1,507 @@
|
||||
# Environment Configuration Guide - Maternal Organization App
|
||||
|
||||
## Environment Structure
|
||||
|
||||
### Environment Types
|
||||
- **Development** (`dev`): Local development with hot reload
|
||||
- **Staging** (`staging`): Pre-production testing environment
|
||||
- **Production** (`prod`): Live application environment
|
||||
- **Testing** (`test`): Automated testing environment
|
||||
|
||||
---
|
||||
|
||||
## Backend Environment Variables (.env)
|
||||
|
||||
### Core Configuration
|
||||
```bash
|
||||
# Application
|
||||
NODE_ENV=development
|
||||
APP_NAME=MaternalApp
|
||||
APP_VERSION=1.0.0
|
||||
API_VERSION=v1
|
||||
PORT=3000
|
||||
HOST=localhost
|
||||
|
||||
# URLs
|
||||
BACKEND_URL=http://localhost:3000
|
||||
FRONTEND_URL=http://localhost:8081
|
||||
WEBSOCKET_URL=ws://localhost:3000
|
||||
```
|
||||
|
||||
### Database Configuration
|
||||
```bash
|
||||
# PostgreSQL Primary
|
||||
DATABASE_URL=postgresql://user:password@localhost:5432/maternal_app
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
DB_NAME=maternal_app
|
||||
DB_USER=maternal_user
|
||||
DB_PASSWORD=secure_password_here
|
||||
DB_SSL=false
|
||||
DB_POOL_MIN=2
|
||||
DB_POOL_MAX=10
|
||||
|
||||
# MongoDB (AI Chat History)
|
||||
MONGODB_URI=mongodb://localhost:27017/maternal_ai
|
||||
MONGODB_DB=maternal_ai
|
||||
|
||||
# Redis
|
||||
REDIS_URL=redis://localhost:6379
|
||||
REDIS_PASSWORD=
|
||||
REDIS_DB=0
|
||||
REDIS_CACHE_TTL=3600
|
||||
```
|
||||
|
||||
### Authentication & Security
|
||||
```bash
|
||||
# JWT Configuration
|
||||
JWT_SECRET=your-256-bit-secret-key-here
|
||||
JWT_REFRESH_SECRET=different-256-bit-secret-key-here
|
||||
JWT_EXPIRES_IN=1h
|
||||
JWT_REFRESH_EXPIRES_IN=30d
|
||||
|
||||
# Encryption
|
||||
ENCRYPTION_KEY=32-character-encryption-key-here
|
||||
ENCRYPTION_IV=16-character-iv-here
|
||||
|
||||
# Device Fingerprinting
|
||||
FINGERPRINT_SECRET=device-fingerprint-secret-key
|
||||
|
||||
# Rate Limiting
|
||||
RATE_LIMIT_WINDOW_MS=60000
|
||||
RATE_LIMIT_MAX_REQUESTS=100
|
||||
```
|
||||
|
||||
### AI Services
|
||||
```bash
|
||||
# OpenAI
|
||||
OPENAI_API_KEY=sk-your-openai-api-key
|
||||
OPENAI_MODEL=gpt-4
|
||||
OPENAI_TEMPERATURE=0.7
|
||||
OPENAI_MAX_TOKENS=1000
|
||||
|
||||
# Anthropic Claude (Alternative)
|
||||
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
|
||||
ANTHROPIC_MODEL=claude-3-opus-20240229
|
||||
|
||||
# Whisper (Voice Recognition)
|
||||
WHISPER_API_KEY=your-whisper-api-key
|
||||
WHISPER_MODEL=whisper-1
|
||||
|
||||
# LangChain
|
||||
LANGCHAIN_TRACING_V2=true
|
||||
LANGCHAIN_API_KEY=your-langchain-api-key
|
||||
LANGCHAIN_PROJECT=maternal-app
|
||||
```
|
||||
|
||||
### External Services
|
||||
```bash
|
||||
# Email Service (SendGrid)
|
||||
SENDGRID_API_KEY=SG.your-sendgrid-api-key
|
||||
SENDGRID_FROM_EMAIL=support@maternalapp.com
|
||||
SENDGRID_FROM_NAME=Maternal App
|
||||
|
||||
# Push Notifications
|
||||
FCM_SERVER_KEY=your-firebase-server-key
|
||||
FCM_PROJECT_ID=maternal-app-prod
|
||||
APNS_KEY_ID=your-apple-key-id
|
||||
APNS_TEAM_ID=your-apple-team-id
|
||||
|
||||
# File Storage (MinIO/S3)
|
||||
S3_ENDPOINT=http://localhost:9000
|
||||
S3_ACCESS_KEY=minioadmin
|
||||
S3_SECRET_KEY=minioadmin
|
||||
S3_BUCKET=maternal-uploads
|
||||
S3_REGION=us-east-1
|
||||
S3_USE_SSL=false
|
||||
|
||||
# Monitoring
|
||||
SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id
|
||||
SENTRY_ENVIRONMENT=development
|
||||
SENTRY_TRACES_SAMPLE_RATE=0.1
|
||||
```
|
||||
|
||||
### Compliance & Analytics
|
||||
```bash
|
||||
# COPPA/GDPR
|
||||
COPPA_VERIFICATION_REQUIRED=true
|
||||
GDPR_ENABLED=true
|
||||
DATA_RETENTION_DAYS=365
|
||||
AUDIT_LOG_ENABLED=true
|
||||
|
||||
# Analytics
|
||||
MIXPANEL_TOKEN=your-mixpanel-token
|
||||
GA_TRACKING_ID=G-XXXXXXXXXX
|
||||
POSTHOG_API_KEY=your-posthog-key
|
||||
POSTHOG_HOST=https://app.posthog.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend Environment Variables (.env)
|
||||
|
||||
### React Native Configuration
|
||||
```bash
|
||||
# API Configuration
|
||||
REACT_APP_API_BASE_URL=http://localhost:3000/api/v1
|
||||
REACT_APP_GRAPHQL_URL=http://localhost:3000/graphql
|
||||
REACT_APP_WS_URL=ws://localhost:3000/ws
|
||||
|
||||
# Feature Flags
|
||||
REACT_APP_ENABLE_VOICE=true
|
||||
REACT_APP_ENABLE_AI_CHAT=true
|
||||
REACT_APP_ENABLE_DARK_MODE=true
|
||||
REACT_APP_ENABLE_OFFLINE=true
|
||||
REACT_APP_MAX_CHILDREN_FREE=2
|
||||
REACT_APP_AI_QUERIES_FREE=10
|
||||
|
||||
# App Configuration
|
||||
REACT_APP_NAME=Maternal
|
||||
REACT_APP_VERSION=1.0.0
|
||||
REACT_APP_BUILD_NUMBER=1
|
||||
REACT_APP_BUNDLE_ID=com.maternalapp.app
|
||||
```
|
||||
|
||||
### Platform-Specific (iOS)
|
||||
```bash
|
||||
# iOS Configuration
|
||||
IOS_APP_ID=1234567890
|
||||
IOS_TEAM_ID=XXXXXXXXXX
|
||||
IOS_PROVISIONING_PROFILE=maternal-app-dev
|
||||
APPLE_SIGN_IN_SERVICE_ID=com.maternalapp.signin
|
||||
```
|
||||
|
||||
### Platform-Specific (Android)
|
||||
```bash
|
||||
# Android Configuration
|
||||
ANDROID_PACKAGE_NAME=com.maternalapp.app
|
||||
ANDROID_KEYSTORE_PATH=./android/app/maternal.keystore
|
||||
ANDROID_KEY_ALIAS=maternal-key
|
||||
ANDROID_KEYSTORE_PASSWORD=keystore-password
|
||||
ANDROID_KEY_PASSWORD=key-password
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Docker Environment Configuration
|
||||
|
||||
### docker-compose.yml
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
environment:
|
||||
POSTGRES_DB: ${DB_NAME}
|
||||
POSTGRES_USER: ${DB_USER}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
command: redis-server --requirepass ${REDIS_PASSWORD}
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
mongodb:
|
||||
image: mongo:6
|
||||
environment:
|
||||
MONGO_INITDB_DATABASE: maternal_ai
|
||||
volumes:
|
||||
- mongo_data:/data/db
|
||||
ports:
|
||||
- "27017:27017"
|
||||
|
||||
minio:
|
||||
image: minio/minio
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${S3_ACCESS_KEY}
|
||||
MINIO_ROOT_PASSWORD: ${S3_SECRET_KEY}
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
mongo_data:
|
||||
minio_data:
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Secret Management
|
||||
|
||||
### Development Secrets (.env.local)
|
||||
```bash
|
||||
# Never commit this file
|
||||
# Copy from .env.example and fill with real values
|
||||
cp .env.example .env.local
|
||||
```
|
||||
|
||||
### Production Secrets (AWS Secrets Manager)
|
||||
```bash
|
||||
# Store production secrets in AWS Secrets Manager
|
||||
aws secretsmanager create-secret \
|
||||
--name maternal-app/production \
|
||||
--secret-string file://secrets.json
|
||||
|
||||
# Retrieve secrets in application
|
||||
aws secretsmanager get-secret-value \
|
||||
--secret-id maternal-app/production
|
||||
```
|
||||
|
||||
### Kubernetes Secrets
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: maternal-app-secrets
|
||||
type: Opaque
|
||||
data:
|
||||
jwt-secret: <base64-encoded-secret>
|
||||
database-url: <base64-encoded-url>
|
||||
openai-api-key: <base64-encoded-key>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Environment File Templates
|
||||
|
||||
### .env.example (Commit to repo)
|
||||
```bash
|
||||
# Copy this file to .env.local and fill in values
|
||||
NODE_ENV=development
|
||||
PORT=3000
|
||||
|
||||
# Database
|
||||
DATABASE_URL=postgresql://user:password@localhost:5432/maternal_app
|
||||
|
||||
# Add all variables with placeholder values...
|
||||
JWT_SECRET=change-this-to-random-256-bit-key
|
||||
OPENAI_API_KEY=sk-your-api-key-here
|
||||
```
|
||||
|
||||
### .env.test (Testing)
|
||||
```bash
|
||||
NODE_ENV=test
|
||||
DATABASE_URL=postgresql://test:test@localhost:5432/maternal_test
|
||||
REDIS_URL=redis://localhost:6380
|
||||
JWT_SECRET=test-jwt-secret-not-for-production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific Configuration
|
||||
|
||||
### iOS Info.plist Additions
|
||||
```xml
|
||||
<key>API_BASE_URL</key>
|
||||
<string>$(API_BASE_URL)</string>
|
||||
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Voice input for hands-free logging</string>
|
||||
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Take photos of your child</string>
|
||||
```
|
||||
|
||||
### Android gradle.properties
|
||||
```properties
|
||||
API_BASE_URL=http://10.0.2.2:3000/api/v1
|
||||
ENABLE_VOICE_INPUT=true
|
||||
ENABLE_PROGUARD=false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration Loading Order
|
||||
|
||||
### Backend (Node.js)
|
||||
```javascript
|
||||
// config/index.ts
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
// Load in order of precedence
|
||||
dotenv.config({ path: '.env.local' }); // Local overrides
|
||||
dotenv.config({ path: `.env.${NODE_ENV}` }); // Environment specific
|
||||
dotenv.config(); // Default values
|
||||
|
||||
export const config = {
|
||||
app: {
|
||||
name: process.env.APP_NAME || 'MaternalApp',
|
||||
version: process.env.APP_VERSION || '1.0.0',
|
||||
env: process.env.NODE_ENV || 'development',
|
||||
},
|
||||
// ... rest of config
|
||||
};
|
||||
```
|
||||
|
||||
### Frontend (React Native)
|
||||
```javascript
|
||||
// config/env.js
|
||||
import Config from 'react-native-config';
|
||||
|
||||
export const ENV = {
|
||||
dev: {
|
||||
API_URL: 'http://localhost:3000/api/v1',
|
||||
WS_URL: 'ws://localhost:3000/ws',
|
||||
},
|
||||
staging: {
|
||||
API_URL: 'https://staging-api.maternalapp.com/api/v1',
|
||||
WS_URL: 'wss://staging-api.maternalapp.com/ws',
|
||||
},
|
||||
prod: {
|
||||
API_URL: 'https://api.maternalapp.com/api/v1',
|
||||
WS_URL: 'wss://api.maternalapp.com/ws',
|
||||
},
|
||||
}[Config.ENV || 'dev'];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### Secret Rotation Schedule
|
||||
- **JWT Secrets**: Every 90 days
|
||||
- **API Keys**: Every 180 days
|
||||
- **Database Passwords**: Every 60 days
|
||||
- **Encryption Keys**: Every year
|
||||
|
||||
### Environment Variable Validation
|
||||
```typescript
|
||||
// validateEnv.ts
|
||||
import { cleanEnv, str, port, url, bool, num } from 'envalid';
|
||||
|
||||
export const env = cleanEnv(process.env, {
|
||||
NODE_ENV: str({ choices: ['development', 'test', 'staging', 'production'] }),
|
||||
PORT: port(),
|
||||
DATABASE_URL: url(),
|
||||
JWT_SECRET: str({ minLength: 32 }),
|
||||
OPENAI_API_KEY: str(),
|
||||
RATE_LIMIT_MAX_REQUESTS: num({ default: 100 }),
|
||||
});
|
||||
```
|
||||
|
||||
### Git Security
|
||||
```bash
|
||||
# .gitignore
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
secrets/
|
||||
*.key
|
||||
*.pem
|
||||
*.p12
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment Configuration
|
||||
|
||||
### Heroku
|
||||
```json
|
||||
// app.json
|
||||
{
|
||||
"env": {
|
||||
"NODE_ENV": {
|
||||
"value": "production"
|
||||
},
|
||||
"DATABASE_URL": {
|
||||
"required": true
|
||||
},
|
||||
"JWT_SECRET": {
|
||||
"generator": "secret"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Docker Build Args
|
||||
```dockerfile
|
||||
ARG NODE_ENV=production
|
||||
ARG API_VERSION=v1
|
||||
|
||||
ENV NODE_ENV=${NODE_ENV}
|
||||
ENV API_VERSION=${API_VERSION}
|
||||
```
|
||||
|
||||
### CI/CD Variables (GitHub Actions)
|
||||
```yaml
|
||||
env:
|
||||
NODE_ENV: production
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
JWT_SECRET: ${{ secrets.JWT_SECRET }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitoring & Debugging
|
||||
|
||||
### Debug Configuration
|
||||
```bash
|
||||
# Development debugging
|
||||
DEBUG=maternal:*
|
||||
LOG_LEVEL=debug
|
||||
PRETTY_LOGS=true
|
||||
|
||||
# Production
|
||||
LOG_LEVEL=info
|
||||
LOG_FORMAT=json
|
||||
```
|
||||
|
||||
### Health Check Variables
|
||||
```bash
|
||||
HEALTH_CHECK_INTERVAL=30000
|
||||
HEALTH_CHECK_TIMEOUT=3000
|
||||
HEALTH_CHECK_PATH=/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Start Commands
|
||||
|
||||
### Local Development Setup
|
||||
```bash
|
||||
# 1. Copy environment template
|
||||
cp .env.example .env.local
|
||||
|
||||
# 2. Start Docker services
|
||||
docker-compose up -d
|
||||
|
||||
# 3. Run migrations
|
||||
npm run migrate:up
|
||||
|
||||
# 4. Seed development data
|
||||
npm run seed:dev
|
||||
|
||||
# 5. Start development server
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Environment Verification
|
||||
```bash
|
||||
# Check all required variables are set
|
||||
npm run env:validate
|
||||
|
||||
# Display current configuration (masked)
|
||||
npm run env:debug
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
1. **Missing API Keys**: Ensure all AI service keys are valid
|
||||
2. **Database Connection**: Check DATABASE_URL format and credentials
|
||||
3. **Redis Connection**: Verify Redis is running and accessible
|
||||
4. **CORS Issues**: Confirm FRONTEND_URL is correctly set
|
||||
5. **WebSocket Failures**: Check WS_URL matches backend configuration
|
||||
Reference in New Issue
Block a user