app/config.py: centralized Settings (DEMO_MODE, CLOUD_MODE, ports, etc.) app/middleware/demo.py: DemoModeMiddleware — caps sessions (429), blocks export (403), adds X-Linnet-Mode header app/middleware/cloud.py: CloudAuthMiddleware — requires X-CF-Session on /session/* routes, 401 without it app/services/session_store.py: active_session_count() for demo cap app/main.py: wires middleware conditionally, extends CORS for cloud origins compose.test.yml: hermetic pytest runner in Docker (CF_VOICE_MOCK=1) compose.demo.yml: DEMO_MODE=true, ports 8523/8524, demo.circuitforge.tech/linnet compose.cloud.yml: CLOUD_MODE=true, ports 8522/8527, menagerie.circuitforge.tech/linnet docker/web/Dockerfile: two-stage build (node:20 → nginx:alpine), VITE_BASE_URL/VITE_API_BASE ARGs docker/web/nginx.conf: SSE + WS proxy, SPA routing (dev/demo) docker/web/nginx.cloud.conf: adds X-CF-Session forwarding, /linnet/ alias for path-strip Caddy routing manage.sh: profile arg (dev|demo|cloud|test), start/stop/restart/status/test/logs/build/open per profile tests/test_profiles.py: 8 tests — demo export block, session cap, cloud auth gate, mode headers
29 lines
1.2 KiB
Python
29 lines
1.2 KiB
Python
# app/config.py — runtime mode settings
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
|
|
class Settings:
|
|
"""Read-once settings from environment variables."""
|
|
|
|
demo_mode: bool = os.getenv("DEMO_MODE", "").lower() in ("1", "true", "yes")
|
|
cloud_mode: bool = os.getenv("CLOUD_MODE", "").lower() in ("1", "true", "yes")
|
|
|
|
# DEMO: max simultaneous active sessions (prevents resource abuse on the demo server)
|
|
demo_max_sessions: int = int(os.getenv("DEMO_MAX_SESSIONS", "3"))
|
|
# DEMO: auto-kill sessions after this many seconds of inactivity
|
|
demo_session_ttl_s: int = int(os.getenv("DEMO_SESSION_TTL_S", "300")) # 5 min
|
|
|
|
# CLOUD: where Caddy injects the cf_session user token
|
|
cloud_session_header: str = os.getenv("CLOUD_SESSION_HEADER", "X-CF-Session")
|
|
cloud_data_root: str = os.getenv("CLOUD_DATA_ROOT", "/devl/linnet-cloud-data")
|
|
|
|
heimdall_url: str = os.getenv("HEIMDALL_URL", "https://license.circuitforge.tech")
|
|
|
|
linnet_port: int = int(os.getenv("LINNET_PORT", "8522"))
|
|
linnet_frontend_port: int = int(os.getenv("LINNET_FRONTEND_PORT", "8521"))
|
|
linnet_base_url: str = os.getenv("LINNET_BASE_URL", "")
|
|
|
|
|
|
settings = Settings()
|