"""Runtime settings service. Resolution order per key: database value → environment variable → schema default. Writing a value persists it to the database, so changes take effect immediately without a restart. """ import os from apps.core.models import SystemSetting from apps.core.settings_registry import SCHEMA_BY_KEY, SETTINGS_SCHEMA class SettingsService: def schema(self): return SETTINGS_SCHEMA def _env_key(self, key: str) -> str: return key.upper().replace(".", "_") def get(self, key: str, default=None): setting = SystemSetting.objects.filter(key=key).first() if setting is not None: return setting.value env_value = os.environ.get(self._env_key(key)) if env_value is not None: return env_value entry = SCHEMA_BY_KEY.get(key) if entry and "default" in entry: return entry["default"] return default def get_bool(self, key: str, default=False) -> bool: value = self.get(key, default) if isinstance(value, bool): return value return str(value).lower() in {"1", "true", "yes", "on"} def set(self, key: str, value) -> None: SystemSetting.objects.update_or_create(key=key, defaults={"value": value}) def all_values(self, mask_secrets: bool = True) -> dict: result = {} for entry in SETTINGS_SCHEMA: value = self.get(entry["key"]) if mask_secrets and entry.get("type") == "secret" and value: result[entry["key"]] = "••••••" else: result[entry["key"]] = value return result