Files
celery/app/config.py
giles 49097eef53 Replace L2 JWT auth with OAuth SSO via account.rose-ash.com
- config.py: OAuth settings replace l2_server/l2_domain
- auth.py: full rewrite — login/callback/logout with itsdangerous
  signed state cookies and httpx token exchange
- dependencies.py: remove l2_server assignment, fix redirect path
- home.py: simplify /login to redirect to /auth/login
- base.html: cross-app nav (Blog, Market, Account) + Rose Ash branding
- requirements.txt: add itsdangerous

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:26:17 +00:00

117 lines
4.1 KiB
Python

"""
L1 Server Configuration.
Environment-based configuration with sensible defaults.
All config should go through this module - no direct os.environ calls elsewhere.
"""
import os
import sys
from pathlib import Path
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class Settings:
"""Application settings loaded from environment."""
# Server
host: str = field(default_factory=lambda: os.environ.get("HOST", "0.0.0.0"))
port: int = field(default_factory=lambda: int(os.environ.get("PORT", "8000")))
debug: bool = field(default_factory=lambda: os.environ.get("DEBUG", "").lower() == "true")
# Cache (use /data/cache in Docker via env var, ~/.artdag/cache locally)
cache_dir: Path = field(
default_factory=lambda: Path(os.environ.get("CACHE_DIR", str(Path.home() / ".artdag" / "cache")))
)
# Redis
redis_url: str = field(
default_factory=lambda: os.environ.get("REDIS_URL", "redis://localhost:6379/5")
)
# Database
database_url: str = field(
default_factory=lambda: os.environ.get("DATABASE_URL", "")
)
# IPFS
ipfs_api: str = field(
default_factory=lambda: os.environ.get("IPFS_API", "/dns/localhost/tcp/5001")
)
ipfs_gateway_url: str = field(
default_factory=lambda: os.environ.get("IPFS_GATEWAY_URL", "https://ipfs.io/ipfs")
)
# OAuth SSO (replaces L2 auth)
oauth_authorize_url: str = field(
default_factory=lambda: os.environ.get("OAUTH_AUTHORIZE_URL", "https://account.rose-ash.com/auth/oauth/authorize")
)
oauth_token_url: str = field(
default_factory=lambda: os.environ.get("OAUTH_TOKEN_URL", "https://account.rose-ash.com/auth/oauth/token")
)
oauth_client_id: str = field(
default_factory=lambda: os.environ.get("OAUTH_CLIENT_ID", "artdag")
)
oauth_redirect_uri: str = field(
default_factory=lambda: os.environ.get("OAUTH_REDIRECT_URI", "https://celery-artdag.rose-ash.com/auth/callback")
)
oauth_logout_url: str = field(
default_factory=lambda: os.environ.get("OAUTH_LOGOUT_URL", "https://account.rose-ash.com/auth/sso-logout/")
)
secret_key: str = field(
default_factory=lambda: os.environ.get("SECRET_KEY", "change-me-in-production")
)
# GPU/Streaming settings
streaming_gpu_persist: bool = field(
default_factory=lambda: os.environ.get("STREAMING_GPU_PERSIST", "0") == "1"
)
ipfs_gateways: str = field(
default_factory=lambda: os.environ.get(
"IPFS_GATEWAYS", "https://ipfs.io,https://cloudflare-ipfs.com,https://dweb.link"
)
)
# Derived paths
@property
def plan_cache_dir(self) -> Path:
return self.cache_dir / "plans"
@property
def analysis_cache_dir(self) -> Path:
return self.cache_dir / "analysis"
def ensure_dirs(self) -> None:
"""Create required directories."""
self.cache_dir.mkdir(parents=True, exist_ok=True)
self.plan_cache_dir.mkdir(parents=True, exist_ok=True)
self.analysis_cache_dir.mkdir(parents=True, exist_ok=True)
def log_config(self, logger=None) -> None:
"""Log all configuration values for debugging."""
output = logger.info if logger else lambda x: print(x, file=sys.stderr)
output("=" * 60)
output("CONFIGURATION")
output("=" * 60)
output(f" cache_dir: {self.cache_dir}")
output(f" redis_url: {self.redis_url}")
output(f" database_url: {self.database_url[:50]}...")
output(f" ipfs_api: {self.ipfs_api}")
output(f" ipfs_gateway_url: {self.ipfs_gateway_url}")
output(f" ipfs_gateways: {self.ipfs_gateways[:50]}...")
output(f" streaming_gpu_persist: {self.streaming_gpu_persist}")
output(f" oauth_client_id: {self.oauth_client_id}")
output(f" oauth_authorize_url: {self.oauth_authorize_url}")
output("=" * 60)
# Singleton settings instance
settings = Settings()
# Log config on import if DEBUG or SHOW_CONFIG is set
if os.environ.get("DEBUG") or os.environ.get("SHOW_CONFIG"):
settings.log_config()