BrianIsaac's picture
fix: implement authentication security hardening
4f454b4
raw
history blame
6.29 kB
"""Configuration module for Portfolio Intelligence Platform.
Loads environment variables and provides configuration settings.
"""
import os
from typing import Optional
from pydantic import Field, ConfigDict
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
"""Application settings loaded from environment variables.
Attributes:
anthropic_api_key: Anthropic API key for Claude
anthropic_model: Anthropic model ID (default: claude-sonnet-4-5-20250929)
supabase_url: Supabase project URL
supabase_key: Supabase anon key
fmp_api_key: Financial Modeling Prep API key
fred_api_key: FRED (Federal Reserve Economic Data) API key
upstash_redis_url: Upstash Redis REST URL for caching
upstash_redis_token: Upstash Redis REST token
cache_enabled: Enable/disable caching globally
cache_fallback_enabled: Enable in-memory fallback when Redis unavailable
environment: Application environment (development/production)
log_level: Logging level
"""
# AI/LLM Configuration
anthropic_api_key: str = Field(
default="",
validation_alias="ANTHROPIC_API_KEY"
)
anthropic_model: str = Field(
default="claude-sonnet-4-5-20250929",
validation_alias="ANTHROPIC_MODEL"
)
# Database Configuration
supabase_url: Optional[str] = Field(
default=None,
validation_alias="SUPABASE_URL"
)
supabase_key: Optional[str] = Field(
default=None,
validation_alias="SUPABASE_KEY"
)
supabase_service_role_key: Optional[str] = Field(
default=None,
validation_alias="SUPABASE_SERVICE_ROLE_KEY"
)
# Financial Data APIs
fmp_api_key: Optional[str] = Field(
default=None,
validation_alias="FMP_API_KEY"
)
fred_api_key: Optional[str] = Field(
default=None,
validation_alias="FRED_API_KEY"
)
finnhub_api_key: Optional[str] = Field(
default=None,
validation_alias="FINNHUB_API_KEY"
)
alpaca_api_key: Optional[str] = Field(
default=None,
validation_alias="ALPACA_API_KEY"
)
alpaca_secret_key: Optional[str] = Field(
default=None,
validation_alias="ALPACA_SECRET_KEY"
)
# Application Settings
environment: str = Field(
default="development",
validation_alias="ENVIRONMENT"
)
log_level: str = Field(
default="INFO",
validation_alias="LOG_LEVEL"
)
app_url: str = Field(
default="http://localhost:7860",
validation_alias="APP_URL",
description="Public URL where the application is accessible"
)
# Rate Limiting Settings
redis_url: Optional[str] = Field(
default=None,
validation_alias="REDIS_URL"
)
rate_limit_enabled: bool = Field(
default=True,
validation_alias="RATE_LIMIT_ENABLED"
)
# Rate limit tiers (fixed window - resets daily at midnight UTC)
# Anonymous (Demo Mode): 1 request per day
rate_limit_anonymous_capacity: int = Field(
default=1,
validation_alias="RATE_LIMIT_ANONYMOUS_CAPACITY",
description="Number of requests allowed per day for anonymous users"
)
rate_limit_anonymous_refill_rate: float = Field(
default=1.0 / 86400.0, # DEPRECATED: Not used with fixed window
validation_alias="RATE_LIMIT_ANONYMOUS_REFILL_RATE"
)
# Authenticated: 3 requests per day
rate_limit_authenticated_capacity: int = Field(
default=3,
validation_alias="RATE_LIMIT_AUTHENTICATED_CAPACITY",
description="Number of requests allowed per day for authenticated users"
)
rate_limit_authenticated_refill_rate: float = Field(
default=1.0 / 86400.0, # DEPRECATED: Not used with fixed window
validation_alias="RATE_LIMIT_AUTHENTICATED_REFILL_RATE"
)
# Premium: 200 requests capacity, refills at 2.0 requests/second (2 every second)
rate_limit_premium_capacity: int = Field(
default=200,
validation_alias="RATE_LIMIT_PREMIUM_CAPACITY"
)
rate_limit_premium_refill_rate: float = Field(
default=2.0,
validation_alias="RATE_LIMIT_PREMIUM_REFILL_RATE"
)
# Market Data Provider Configuration
market_data_provider: str = Field(
default="yfinance",
validation_alias="MARKET_DATA_PROVIDER"
)
fmp_tier: str = Field(
default="free",
validation_alias="FMP_TIER"
)
# Caching Configuration (Upstash Redis)
upstash_redis_url: Optional[str] = Field(
default=None,
validation_alias="UPSTASH_REDIS_URL"
)
upstash_redis_token: Optional[str] = Field(
default=None,
validation_alias="UPSTASH_REDIS_TOKEN"
)
cache_enabled: bool = Field(
default=True,
validation_alias="CACHE_ENABLED"
)
cache_fallback_enabled: bool = Field(
default=True,
validation_alias="CACHE_FALLBACK_ENABLED"
)
cache_fallback_max_size: int = Field(
default=1000,
validation_alias="CACHE_FALLBACK_MAX_SIZE"
)
# Cache TTLs for different data types
cache_ttl_quotes: int = Field(
default=60,
validation_alias="CACHE_TTL_QUOTES"
)
cache_ttl_historical: int = Field(
default=14400,
validation_alias="CACHE_TTL_HISTORICAL"
)
cache_ttl_fundamentals: int = Field(
default=86400,
validation_alias="CACHE_TTL_FUNDAMENTALS"
)
cache_ttl_ratios: int = Field(
default=604800,
validation_alias="CACHE_TTL_RATIOS"
)
# Sentry Error Monitoring
sentry_dsn: Optional[str] = Field(
default=None,
validation_alias="SENTRY_DSN"
)
sentry_tier: str = Field(
default="free",
validation_alias="SENTRY_TIER"
)
sentry_release: Optional[str] = Field(
default=None,
validation_alias="SENTRY_RELEASE"
)
sentry_debug: bool = Field(
default=False,
validation_alias="SENTRY_DEBUG"
)
model_config = ConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
)
# Global settings instance
settings = Settings()