diff --git a/backend/.env.example b/backend/.env.example index de53d85..30b2248 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -9,10 +9,13 @@ APP_NAME=BlackRoad Operating System APP_VERSION=1.0.0 DEBUG=False ENVIRONMENT=production +NODE_ENV=production +PYTHON_ENV=production # Database connectivity DATABASE_URL=postgresql://YOUR_DB_USER:YOUR_DB_PASSWORD@YOUR_DB_HOST:5432/blackroad DATABASE_ASYNC_URL=postgresql+asyncpg://YOUR_DB_USER:YOUR_DB_PASSWORD@YOUR_DB_HOST:5432/blackroad +POSTGRES_URL=postgresql://YOUR_DB_USER:YOUR_DB_PASSWORD@YOUR_DB_HOST:5432/blackroad REDIS_URL=redis://YOUR_REDIS_HOST:6379/0 # Security / auth @@ -22,6 +25,9 @@ ACCESS_TOKEN_EXPIRE_MINUTES=30 REFRESH_TOKEN_EXPIRE_DAYS=7 WALLET_MASTER_KEY=changeme-wallet-master-key ALLOWED_ORIGINS=https://blackroad.systems,https://your-frontend.example +JWT_SECRET=changeme-jwt-secret +SESSION_SECRET=changeme-session-secret +NEXTAUTH_SECRET=changeme-nextauth-secret # Object storage AWS_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY_ID @@ -38,6 +44,7 @@ EMAIL_FROM=blackroad@example.com # AI integrations OPENAI_API_KEY=sk-your-openai-key +ANTHROPIC_API_KEY=anthropic-key-placeholder # Blockchain tuning BLOCKCHAIN_DIFFICULTY=4 @@ -50,9 +57,10 @@ RAILWAY_ENVIRONMENT_ID=00000000-0000-0000-0000-000000000000 RAILWAY_DOMAIN=your-service.up.railway.app SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXX/YYY/ZZZ DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/XXX/YYY +CLOUDFLARE_API_TOKEN=cloudflare-api-token-placeholder # Optional cloud/API integrations -DIGITALOCEAN_TOKEN=your-digitalocean-token +DIGITAL_OCEAN_API_KEY=your-digital-ocean-api-key GITHUB_TOKEN=your-github-personal-access-token HUGGINGFACE_TOKEN=your-huggingface-token VERCEL_TOKEN=vercel-token-placeholder diff --git a/backend/app/routers/api_health.py b/backend/app/routers/api_health.py index 361afc3..4702591 100644 --- a/backend/app/routers/api_health.py +++ b/backend/app/routers/api_health.py @@ -324,7 +324,7 @@ async def check_huggingface_status(): async def check_digitalocean_status(): """Check DigitalOcean API status""" - do_token = os.getenv("DIGITALOCEAN_TOKEN") + do_token = os.getenv("DIGITAL_OCEAN_API_KEY") or os.getenv("DIGITALOCEAN_TOKEN") if not do_token: return { "connected": False, diff --git a/backend/app/routers/dashboard.py b/backend/app/routers/dashboard.py index d912df8..1c2f717 100644 --- a/backend/app/routers/dashboard.py +++ b/backend/app/routers/dashboard.py @@ -42,8 +42,11 @@ async def get_dashboard_overview( """ # Check which services are configured + digital_ocean_token = os.getenv("DIGITAL_OCEAN_API_KEY") or os.getenv( + "DIGITALOCEAN_TOKEN" + ) services_config = { - "digitalocean": bool(os.getenv("DIGITALOCEAN_TOKEN")), + "digitalocean": bool(digital_ocean_token), "github": bool(os.getenv("GITHUB_TOKEN")), "huggingface": bool(os.getenv("HUGGINGFACE_TOKEN")), "openai": bool(os.getenv("OPENAI_API_KEY")), @@ -282,7 +285,7 @@ async def list_all_services( "description": "Cloud infrastructure management", "category": "infrastructure", "icon": "🌊", - "configured": bool(os.getenv("DIGITALOCEAN_TOKEN")) + "configured": bool(digital_ocean_token) }, { "id": "github", diff --git a/backend/app/routers/digitalocean.py b/backend/app/routers/digitalocean.py index 53b9aed..c047cef 100644 --- a/backend/app/routers/digitalocean.py +++ b/backend/app/routers/digitalocean.py @@ -24,7 +24,15 @@ router = APIRouter(prefix="/api/digitalocean", tags=["digitalocean"]) # DigitalOcean API configuration DO_API_URL = "https://api.digitalocean.com/v2" -DO_TOKEN = os.getenv("DIGITALOCEAN_TOKEN", "") + + +def get_digital_ocean_token() -> str: + """Return the configured DigitalOcean API key, preferring the canonical name.""" + + return os.getenv("DIGITAL_OCEAN_API_KEY") or os.getenv("DIGITALOCEAN_TOKEN", "") + + +DO_TOKEN = get_digital_ocean_token() class DropletCreate(BaseModel): diff --git a/scripts/railway/validate_env_template.py b/scripts/railway/validate_env_template.py index a87c3d3..5c728f0 100644 --- a/scripts/railway/validate_env_template.py +++ b/scripts/railway/validate_env_template.py @@ -24,7 +24,8 @@ EXTRA_REQUIRED_KEYS: Set[str] = { "RAILWAY_DOMAIN", "SLACK_WEBHOOK_URL", "DISCORD_WEBHOOK_URL", - "DIGITALOCEAN_TOKEN", + "DIGITAL_OCEAN_API_KEY", + "CLOUDFLARE_API_TOKEN", "GITHUB_TOKEN", "HUGGINGFACE_TOKEN", "VERCEL_TOKEN", @@ -46,6 +47,13 @@ EXTRA_REQUIRED_KEYS: Set[str] = { "MQTT_USERNAME", "MQTT_PASSWORD", "DEVICE_HEARTBEAT_TIMEOUT_SECONDS", + "ANTHROPIC_API_KEY", + "POSTGRES_URL", + "JWT_SECRET", + "SESSION_SECRET", + "NEXTAUTH_SECRET", + "NODE_ENV", + "PYTHON_ENV", } SENSITIVE_KEYS: Set[str] = { @@ -64,7 +72,8 @@ SENSITIVE_KEYS: Set[str] = { "RAILWAY_DOMAIN", "SLACK_WEBHOOK_URL", "DISCORD_WEBHOOK_URL", - "DIGITALOCEAN_TOKEN", + "DIGITAL_OCEAN_API_KEY", + "CLOUDFLARE_API_TOKEN", "GITHUB_TOKEN", "HUGGINGFACE_TOKEN", "VERCEL_TOKEN", @@ -82,6 +91,11 @@ SENSITIVE_KEYS: Set[str] = { "ROADCOIN_WALLET_ADDRESS", "MQTT_BROKER_URL", "MQTT_PASSWORD", + "ANTHROPIC_API_KEY", + "POSTGRES_URL", + "JWT_SECRET", + "SESSION_SECRET", + "NEXTAUTH_SECRET", } PLACEHOLDER_MARKERS: Tuple[str, ...] = (