* Initial plan * Fix onLimitReached deprecation in rate-limit middleware - Replace deprecated onLimitReached callback with inline logging in handler - Update tests to verify logging happens in the rate limit handler - Remove onLimitReached from exports as it's no longer a separate function Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> * Fix fromBlock: 0 in event queries for better performance - Replace fromBlock: 0 with smart default (last 1M blocks) - Add REGISTRY_START_BLOCK env var for configurable starting block - Update make-proof.ts, verification-jobs.routes.ts, and verification-queue.service.ts - Document new env variable in .env.example Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> * Remove hardcoded testnet RPC fallback for production safety - Replace testnet fallbacks with proper error handling when RPC_URL is not configured - Update registry.service.ts, blockchain.service.ts to throw errors if RPC_URL missing - Update CLI scripts (verify.ts, register.ts, make-proof.ts) to fail fast without RPC_URL - Update API routes to return 503 error when RPC_URL is not configured - Update .env.example to emphasize RPC_URL is required Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> * Add documentation for dual Prisma generators and pin Redis version - Add comprehensive comments in schema.prisma explaining dual generator setup - Document why both generators are needed (API vs Next.js web app) - Pin Redis version to 7.2-alpine in all docker-compose files for reproducibility - Update docker-compose.yml, docker-compose.production.yml, and docker-compose.staging.yml Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> * Address code review feedback - add validation for REGISTRY_START_BLOCK - Add proper validation for parseInt to handle NaN cases - Ensure REGISTRY_START_BLOCK is validated before use - Add comment explaining intentional empty catch block - Prevents invalid block numbers from breaking event queries Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> * Refactor block range validation into shared utility function - Create block-range.util.ts with getStartBlock helper - Extract duplicated validation logic from make-proof.ts, verification-jobs.routes.ts, and verification-queue.service.ts - Improves code maintainability and ensures consistent validation - Add comprehensive JSDoc documentation Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> * Add comprehensive test coverage for block-range utility - Create test/utils/block-range.util.test.ts following existing test patterns - Test valid REGISTRY_START_BLOCK values (positive, zero, large numbers) - Test invalid inputs (NaN, negative, empty string, whitespace) - Test default fallback behavior (current block - 1M) - Test edge cases (low block numbers, decimals, provider errors) - 15 test cases covering all code paths and validation logic Co-authored-by: PatrickFanella <61631520+PatrickFanella@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: onnwee <211922112+onnwee@users.noreply.github.com> Co-authored-by: PatrickFanella <61631520+PatrickFanella@users.noreply.github.com>
407 lines
14 KiB
Plaintext
407 lines
14 KiB
Plaintext
# =============================================================================
|
||
# Internet-ID API Server & Scripts Environment Configuration
|
||
# =============================================================================
|
||
# Copy this file to .env and fill in your values
|
||
# DO NOT commit .env to git (it's in .gitignore)
|
||
#
|
||
# For web app configuration, see web/.env.example
|
||
# See docs/CONTRIBUTOR_ONBOARDING.md for detailed setup instructions
|
||
# =============================================================================
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Blockchain Configuration (REQUIRED)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Private key of the deployer/creator account (without 0x prefix or with it)
|
||
# REQUIRED for deploying contracts and registering content
|
||
# SECURITY: Never commit this value! Keep it secret!
|
||
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
||
PRIVATE_KEY=
|
||
|
||
# Default RPC URL for blockchain interactions
|
||
# REQUIRED: This must be configured for the API server to function
|
||
# For production, use a reliable RPC provider (Infura, Alchemy, QuickNode, etc.)
|
||
# For development/testing, use a testnet (Base Sepolia recommended)
|
||
# See Multi-Chain section below for other networks
|
||
RPC_URL=https://sepolia.base.org
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Multi-Chain RPC Configuration (Optional - defaults provided in config/chains.ts)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Ethereum networks
|
||
# ETHEREUM_RPC_URL=https://eth.llamarpc.com
|
||
# SEPOLIA_RPC_URL=https://ethereum-sepolia-rpc.publicnode.com
|
||
|
||
# Polygon networks
|
||
# POLYGON_RPC_URL=https://polygon-rpc.com
|
||
# POLYGON_AMOY_RPC_URL=https://rpc-amoy.polygon.technology
|
||
|
||
# Base networks (Coinbase L2)
|
||
# BASE_RPC_URL=https://mainnet.base.org
|
||
# BASE_SEPOLIA_RPC_URL=https://sepolia.base.org
|
||
|
||
# Arbitrum networks
|
||
# ARBITRUM_RPC_URL=https://arb1.arbitrum.io/rpc
|
||
# ARBITRUM_SEPOLIA_RPC_URL=https://sepolia-rollup.arbitrum.io/rpc
|
||
|
||
# Optimism networks
|
||
# OPTIMISM_RPC_URL=https://mainnet.optimism.io
|
||
# OPTIMISM_SEPOLIA_RPC_URL=https://sepolia.optimism.io
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# SSL/TLS Configuration (Production)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Domain name for SSL certificates
|
||
DOMAIN=example.com
|
||
|
||
# Email for Let's Encrypt notifications and alerts
|
||
SSL_EMAIL=admin@example.com
|
||
SSL_ALERT_EMAIL=ops@example.com
|
||
|
||
# Certificate monitoring thresholds (days before expiration)
|
||
CERT_WARNING_DAYS=14
|
||
CERT_CRITICAL_DAYS=7
|
||
|
||
# Use Let's Encrypt staging environment for testing (0=production, 1=staging)
|
||
CERTBOT_STAGING=0
|
||
|
||
# Application environment
|
||
NODE_ENV=production
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Logging & Observability Configuration
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Log level (trace, debug, info, warn, error, fatal)
|
||
# Default: info
|
||
LOG_LEVEL=info
|
||
|
||
# Log destination configuration for external services
|
||
# Uncomment and configure for production deployments
|
||
|
||
# Logtail (BetterStack) Configuration
|
||
# LOGTAIL_SOURCE_TOKEN=your_logtail_source_token
|
||
|
||
# Datadog Configuration
|
||
# DATADOG_API_KEY=your_datadog_api_key
|
||
# DATADOG_APP_KEY=your_datadog_app_key
|
||
# DATADOG_SITE=datadoghq.com # or datadoghq.eu for EU region
|
||
|
||
# ELK Stack / Elasticsearch Configuration
|
||
# ELASTICSEARCH_URL=https://your-elasticsearch-host:9200
|
||
# ELASTICSEARCH_USERNAME=your_username
|
||
# ELASTICSEARCH_PASSWORD=your_password
|
||
# ELASTICSEARCH_INDEX=internet-id-logs
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Error Tracking Configuration (Sentry)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Sentry DSN for error tracking
|
||
# Get this from your Sentry project settings
|
||
# Leave empty to disable error tracking
|
||
# SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id
|
||
|
||
# Sentry environment (defaults to NODE_ENV)
|
||
# SENTRY_ENVIRONMENT=production
|
||
|
||
# Sentry release version (for tracking deployments)
|
||
# SENTRY_RELEASE=1.0.0
|
||
|
||
# Performance monitoring sample rate (0.0 to 1.0)
|
||
# 1.0 = 100% of transactions, 0.1 = 10% of transactions
|
||
# SENTRY_TRACES_SAMPLE_RATE=0.1
|
||
|
||
# Profiling sample rate (0.0 to 1.0)
|
||
# SENTRY_PROFILES_SAMPLE_RATE=0.1
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# IPFS Configuration (REQUIRED - choose one provider)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# IPFS is used for decentralized storage of content files and manifests
|
||
# The uploader automatically falls back between providers on failures
|
||
# REQUIRED: Configure at least one provider below
|
||
|
||
# IPFS provider options (choose one or configure multiple for fallback):
|
||
|
||
# 1) Infura IPFS
|
||
# Create IPFS project, then set:
|
||
IPFS_API_URL=https://ipfs.infura.io:5001
|
||
# IPFS_PROJECT_ID=your_project_id
|
||
# IPFS_PROJECT_SECRET=your_project_secret
|
||
|
||
# 2) Web3.Storage
|
||
# Create an API token at https://web3.storage
|
||
# The uploader will use this if set.
|
||
# WEB3_STORAGE_TOKEN=your_web3_storage_token
|
||
|
||
# 3) Pinata (JWT)
|
||
# Create a JWT at https://pinata.cloud
|
||
# The uploader will use this if set and WEB3_STORAGE_TOKEN is not set.
|
||
PINATA_JWT=
|
||
#API Key:
|
||
#API Secret:
|
||
#JWT:
|
||
|
||
# Optional: Force a specific IPFS provider for uploads
|
||
# Allowed values: web3storage | pinata | infura | local
|
||
# If not set, the uploader will auto-fallback: Web3.Storage -> Pinata -> Infura (-> Local if configured)
|
||
IPFS_PROVIDER=pinata
|
||
|
||
# Local node override (optional)
|
||
LOCAL_RPC_URL=http://127.0.0.1:8545
|
||
|
||
# Local IPFS node (optional)
|
||
# To use a local Kubo node without credentials, run IPFS locally and set:
|
||
# IPFS_PROVIDER=local
|
||
# IPFS_API_URL=http://127.0.0.1:5001
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Smart Contract Event Query Configuration (Optional)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Starting block number for querying ContentRegistered events
|
||
# This avoids scanning the entire blockchain history when searching for registration transactions
|
||
# Set this to the block number when the registry contract was deployed
|
||
# If not set, defaults to scanning the last 1,000,000 blocks
|
||
# Example for Base Sepolia: 14000000 (approximate deployment block)
|
||
# REGISTRY_START_BLOCK=14000000
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# API Configuration
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# API key for protected endpoints (optional but recommended)
|
||
# If set, the following endpoints require x-api-key header:
|
||
# - POST /api/upload (file upload to IPFS)
|
||
# - POST /api/manifest (manifest generation)
|
||
# - POST /api/register (on-chain registration)
|
||
# - POST /api/bind (platform binding)
|
||
# Generate with: openssl rand -hex 32
|
||
# Leave empty to disable API key protection (not recommended for production)
|
||
API_KEY=supersecret
|
||
|
||
# Rate Limiting (optional)
|
||
# Redis URL for distributed rate limiting (if not set, uses in-memory store)
|
||
REDIS_URL=redis://localhost:6379
|
||
# Optional: API key that exempts from rate limiting (for internal services)
|
||
# RATE_LIMIT_EXEMPT_API_KEY=internal_service_key
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Caching Configuration (optional)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Redis is used for both rate limiting and caching
|
||
# If REDIS_URL is set, the API will use Redis for:
|
||
# 1. Distributed rate limiting across multiple instances
|
||
# 2. Caching frequently accessed data (content metadata, manifests, bindings)
|
||
#
|
||
# Cache TTLs (configured in code):
|
||
# - Content metadata: 10 minutes
|
||
# - Manifest data: 15 minutes
|
||
# - Platform bindings: 3 minutes
|
||
# - Verification status: 5 minutes
|
||
# - IPFS gateway URLs: 30 minutes
|
||
#
|
||
# Redis configuration (automatically set by cache service):
|
||
# - Eviction policy: allkeys-lru (evicts least recently used keys)
|
||
# - Max memory: 256MB (configurable in cache.service.ts)
|
||
#
|
||
# To disable caching, simply don't set REDIS_URL (API will use database fallback)
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Database Configuration (REQUIRED)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Database connection URL for Prisma ORM
|
||
# The web app shares the same database, so web/.env.local must have the same value
|
||
# REQUIRED: Choose one option below
|
||
|
||
# Option 1: SQLite (Recommended for development)
|
||
# Easiest setup, no separate database server needed
|
||
# Creates dev.db file in the root directory
|
||
DATABASE_URL="file:./dev.db"
|
||
|
||
# Option 2: PostgreSQL (Recommended for production)
|
||
# Better performance and features for production deployments
|
||
# Start with: docker compose up -d
|
||
# Uncomment the lines below and comment out the SQLite option above
|
||
# POSTGRES_USER=internetid
|
||
# POSTGRES_PASSWORD=internetid
|
||
# POSTGRES_DB=internetid
|
||
# DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?schema=public"
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Database Seed Data (Development Only)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# The seed script populates the database with test data for local development:
|
||
# - 5 test creator accounts
|
||
# - 5 sample content entries (video, image, audio, document)
|
||
# - 10 platform bindings (YouTube, TikTok, GitHub, Instagram, Discord, LinkedIn)
|
||
# - 3 verification records
|
||
#
|
||
# Usage:
|
||
# npm run db:seed - Populate test data
|
||
# npm run db:reset - Clear database and reseed
|
||
#
|
||
# ⚠️ NEVER use seed data in production! All test accounts use publicly known keys.
|
||
# See prisma/SEED_DATA.md for detailed documentation.
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Authentication (Auth.js / NextAuth recommended)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Base app URL (used for callback URLs)
|
||
APP_BASE_URL=http://localhost:3000
|
||
|
||
# NextAuth core
|
||
# If using NextAuth/Auth.js, set these:
|
||
NEXTAUTH_URL=${APP_BASE_URL}
|
||
NEXTAUTH_SECRET=supersupersecret
|
||
|
||
# Optional: Cookie/session hints if your auth needs them
|
||
SESSION_SECRET=change_me
|
||
COOKIE_NAME=internet-id.session
|
||
COOKIE_SECURE=false
|
||
|
||
# Generic OIDC (works with any standards-compliant provider)
|
||
# OIDC_ISSUER=https://your-issuer.example.com
|
||
# OIDC_CLIENT_ID=your_oidc_client_id
|
||
# OIDC_CLIENT_SECRET=your_oidc_client_secret
|
||
# OIDC_REDIRECT_URI=${APP_BASE_URL}/api/auth/callback/oidc
|
||
# OIDC_SCOPES="openid profile email"
|
||
# Optional overrides if discovery isn’t available:
|
||
# OIDC_AUTHORIZATION_URL=
|
||
# OIDC_TOKEN_URL=
|
||
# OIDC_USERINFO_URL=
|
||
# OIDC_END_SESSION_URL=
|
||
|
||
# Provider-specific examples (Auth.js/NextAuth)
|
||
# Callback for all providers will be: ${APP_BASE_URL}/api/auth/callback/<provider>
|
||
|
||
# GitHub
|
||
# GITHUB_ID=your_github_client_id
|
||
# GITHUB_SECRET=your_github_client_secret
|
||
|
||
# Google
|
||
GOOGLE_CLIENT_ID=
|
||
GOOGLE_CLIENT_SECRET=
|
||
|
||
# Auth0 (as an OIDC provider)
|
||
# AUTH0_ISSUER=https://your-tenant.us.auth0.com
|
||
# AUTH0_CLIENT_ID=your_auth0_client_id
|
||
# AUTH0_CLIENT_SECRET=your_auth0_client_secret
|
||
|
||
# Discord
|
||
# DISCORD_CLIENT_ID=your_discord_client_id
|
||
# DISCORD_CLIENT_SECRET=your_discord_client_secret
|
||
|
||
# Twitter (X) - OAuth2
|
||
TWITTER_CLIENT_ID=
|
||
TWITTER_CLIENT_SECRET=
|
||
|
||
# Apple
|
||
# APPLE_ID=your_service_id
|
||
# APPLE_TEAM_ID=your_team_id
|
||
# APPLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
|
||
# APPLE_KEY_ID=your_key_id
|
||
|
||
# LinkedIn
|
||
# LINKEDIN_CLIENT_ID=your_linkedin_client_id
|
||
# LINKEDIN_CLIENT_SECRET=your_linkedin_client_secret
|
||
|
||
# Slack
|
||
# SLACK_CLIENT_ID=your_slack_client_id
|
||
# SLACK_CLIENT_SECRET=your_slack_client_secret
|
||
|
||
# Microsoft (Azure AD)
|
||
# AZURE_AD_CLIENT_ID=your_azure_client_id
|
||
# AZURE_AD_CLIENT_SECRET=your_azure_client_secret
|
||
# AZURE_AD_TENANT_ID=common
|
||
|
||
# Reddit
|
||
# REDDIT_CLIENT_ID=your_reddit_client_id
|
||
# REDDIT_CLIENT_SECRET=your_reddit_client_secret
|
||
|
||
# Coinbase
|
||
# COINBASE_CLIENT_ID=your_coinbase_client_id
|
||
# COINBASE_CLIENT_SECRET=your_coinbase_client_secret
|
||
|
||
# TikTok
|
||
TIKTOK_CLIENT_ID=
|
||
TIKTOK_CLIENT_SECRET=
|
||
|
||
# Optional: CORS
|
||
# -----------------------------------------------------------------------------
|
||
# Alerting Configuration
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# PagerDuty Integration
|
||
# Get these from your PagerDuty account settings
|
||
# PAGERDUTY_SERVICE_KEY=your_pagerduty_service_key
|
||
# PAGERDUTY_ROUTING_KEY=your_pagerduty_routing_key
|
||
# PAGERDUTY_DATABASE_KEY=your_pagerduty_database_key
|
||
# PAGERDUTY_DBA_ROUTING_KEY=your_pagerduty_dba_routing_key
|
||
|
||
# Slack Integration
|
||
# Create a webhook at https://api.slack.com/messaging/webhooks
|
||
# SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
|
||
# SLACK_CRITICAL_CHANNEL=#alerts-critical
|
||
# SLACK_WARNINGS_CHANNEL=#alerts-warnings
|
||
|
||
# Email Alerting
|
||
# ALERT_EMAIL=ops@example.com
|
||
# INFO_EMAIL=team@example.com
|
||
# ALERT_FROM_EMAIL=alerts@internet-id.com
|
||
|
||
# SMTP Configuration for Email Alerts
|
||
# SMTP_HOST=smtp.gmail.com
|
||
# SMTP_PORT=587
|
||
# SMTP_USERNAME=your_smtp_username
|
||
# SMTP_PASSWORD=your_smtp_password
|
||
|
||
# -----------------------------------------------------------------------------
|
||
# Email Notification System (Optional)
|
||
# -----------------------------------------------------------------------------
|
||
|
||
# Email service provider (sendgrid, postmark, ses, smtp)
|
||
# If not set, email notifications will be disabled
|
||
# EMAIL_PROVIDER=sendgrid
|
||
|
||
# SendGrid Configuration
|
||
# SENDGRID_API_KEY=your_sendgrid_api_key_here
|
||
|
||
# Postmark Configuration
|
||
# POSTMARK_SERVER_TOKEN=your_postmark_server_token_here
|
||
|
||
# AWS SES Configuration
|
||
# AWS_SES_REGION=us-east-1
|
||
# AWS_SES_ACCESS_KEY_ID=your_aws_access_key_id
|
||
# AWS_SES_SECRET_ACCESS_KEY=your_aws_secret_access_key
|
||
|
||
# SMTP Configuration (fallback provider)
|
||
# SMTP_HOST=smtp.example.com
|
||
# SMTP_PORT=587
|
||
# SMTP_SECURE=false
|
||
# SMTP_USER=your_smtp_username
|
||
# SMTP_PASS=your_smtp_password
|
||
|
||
# Email settings
|
||
# EMAIL_FROM=noreply@internet-id.com
|
||
# EMAIL_FROM_NAME=Internet ID
|
||
# EMAIL_REPLY_TO=support@internet-id.com
|
||
|
||
# Email notification base URL (for links in emails)
|
||
# EMAIL_BASE_URL=https://internet-id.com
|
||
|
||
# Grafana Configuration
|
||
# GRAFANA_ADMIN_USER=admin
|
||
# GRAFANA_ADMIN_PASSWORD=changeme
|
||
# GRAFANA_ROOT_URL=http://localhost:3000
|
||
# GRAFANA_ANONYMOUS_ENABLED=false
|
||
|