gabriel / musehub public
config.py python
98 lines 3.4 KB
e893a97c Remove LLM, Storpheus, HuggingFace, and Qdrant from codebase Gabriel Cardona <gabriel@tellurstori.com> 6d ago
1 """
2 Muse Configuration
3
4 Environment-based configuration for the Muse service.
5 """
6 from __future__ import annotations
7
8 import logging
9 from functools import lru_cache
10
11 from pydantic import model_validator
12 from pydantic_settings import BaseSettings, SettingsConfigDict
13
14
15 def _app_version_from_package() -> str:
16 """Read version from the single source of truth (pyproject.toml via protocol.version)."""
17 from musehub.protocol.version import MUSE_VERSION
18 return MUSE_VERSION
19
20
21 class Settings(BaseSettings):
22 """Application settings loaded from environment variables."""
23
24 # Service Info
25 app_name: str = "Muse"
26 app_version: str = _app_version_from_package()
27 debug: bool = False
28
29 # Server Configuration
30 host: str = "0.0.0.0"
31 port: int = 10001
32
33 # Database Configuration
34 # PostgreSQL: postgresql+asyncpg://user:pass@localhost:5432/muse
35 # SQLite (dev): sqlite+aiosqlite:///./muse.db
36 database_url: str | None = None
37 db_password: str | None = None
38
39 # CORS Settings (fail closed: no default origins)
40 # Set CORS_ORIGINS (JSON array) in .env. Local dev: ["http://localhost:10003", "muse://"].
41 # Production: exact origins only. Never use "*" in production.
42 cors_origins: list[str] = []
43
44 @model_validator(mode="after")
45 def _warn_cors_wildcard_in_production(self) -> "Settings":
46 """Warn when CORS allows all origins in non-debug (production) mode."""
47 if not self.debug and self.cors_origins and "*" in self.cors_origins:
48 logging.getLogger(__name__).warning(
49 "CORS allows all origins (*) with DEBUG=false. "
50 "Set CORS_ORIGINS to exact origins in production."
51 )
52 return self
53
54 # Access Token Settings
55 # Generate secret with: openssl rand -hex 32
56 access_token_secret: str | None = None
57 access_token_algorithm: str = "HS256"
58 # In-memory revocation cache TTL (seconds). Reduces DB hits; revocation visible within this window.
59 token_revocation_cache_ttl_seconds: int = 60
60
61 # AWS S3 Asset Delivery (drum kits, GM soundfont)
62 # Region MUST match the bucket's region (S3 returns 301 if URL uses wrong region).
63 aws_region: str = "eu-west-1"
64 aws_s3_asset_bucket: str | None = None
65 aws_cloudfront_domain: str | None = None
66 presign_expiry_seconds: int = 1800 # 30-min default for presigned download URLs
67
68 # Asset endpoint rate limits (UUID-only auth, no JWT)
69 asset_rate_limit_per_device: str = "30/minute"
70 asset_rate_limit_per_ip: str = "120/minute"
71
72 # Stdio MCP server: proxy DAW tools to Muse backend
73 muse_mcp_url: str | None = None
74 mcp_token: str | None = None
75
76 # Muse Hub object storage — binary artifacts (MIDI, MP3, WebP) stored as flat files
77 # under <musehub_objects_dir>/<repo_id>/<object_id>. Mount on a persistent volume in prod.
78 musehub_objects_dir: str = "/data/musehub/objects"
79
80 # Webhook secret encryption key — AES-256 (Fernet) key for encrypting webhook signing
81 # secrets at rest. Generate with:
82 # python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
83 webhook_secret_key: str | None = None
84
85 model_config = SettingsConfigDict(
86 env_file=".env",
87 env_file_encoding="utf-8",
88 )
89
90
91 @lru_cache()
92 def get_settings() -> Settings:
93 """Get cached settings instance."""
94 return Settings()
95
96
97 # Convenience access
98 settings = get_settings()