From ccfe6a47c3fd68064a286b648d118bf73d9730d7 Mon Sep 17 00:00:00 2001 From: simbam99 Date: Mon, 27 Apr 2026 11:53:02 +0300 Subject: [PATCH] fix(gateway): coerce StreamingConfig booleans and malformed numerics safely --- gateway/config.py | 30 +++++++++++++++++++++++++----- tests/gateway/test_config.py | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/gateway/config.py b/gateway/config.py index 9cf4ec12f6..ce7baffac1 100644 --- a/gateway/config.py +++ b/gateway/config.py @@ -36,6 +36,26 @@ def _coerce_bool(value: Any, default: bool = True) -> bool: return is_truthy_value(value, default=default) +def _coerce_float(value: Any, default: float) -> float: + """Coerce numeric config values, falling back on malformed input.""" + if value is None: + return default + try: + return float(value) + except (TypeError, ValueError): + return default + + +def _coerce_int(value: Any, default: int) -> int: + """Coerce integer config values, falling back on malformed input.""" + if value is None: + return default + try: + return int(value) + except (TypeError, ValueError): + return default + + def _normalize_unauthorized_dm_behavior(value: Any, default: str = "pair") -> str: """Normalize unauthorized DM behavior to a supported value.""" if isinstance(value, str): @@ -301,13 +321,13 @@ class StreamingConfig: if not data: return cls() return cls( - enabled=data.get("enabled", False), + enabled=_coerce_bool(data.get("enabled"), False), transport=data.get("transport", "edit"), - edit_interval=float(data.get("edit_interval", 1.0)), - buffer_threshold=int(data.get("buffer_threshold", 40)), + edit_interval=_coerce_float(data.get("edit_interval"), 1.0), + buffer_threshold=_coerce_int(data.get("buffer_threshold"), 40), cursor=data.get("cursor", " ▉"), - fresh_final_after_seconds=float( - data.get("fresh_final_after_seconds", 60.0) + fresh_final_after_seconds=_coerce_float( + data.get("fresh_final_after_seconds"), 60.0 ), ) diff --git a/tests/gateway/test_config.py b/tests/gateway/test_config.py index 669545c8f4..0f5a1440b1 100644 --- a/tests/gateway/test_config.py +++ b/tests/gateway/test_config.py @@ -9,6 +9,7 @@ from gateway.config import ( Platform, PlatformConfig, SessionResetPolicy, + StreamingConfig, _apply_env_overrides, load_gateway_config, ) @@ -149,6 +150,24 @@ class TestSessionResetPolicy: assert restored.notify is False +class TestStreamingConfig: + def test_from_dict_coerces_quoted_false_enabled(self): + restored = StreamingConfig.from_dict({"enabled": "false"}) + assert restored.enabled is False + + def test_from_dict_malformed_numeric_values_fall_back_to_defaults(self): + restored = StreamingConfig.from_dict( + { + "edit_interval": "oops", + "buffer_threshold": "oops", + "fresh_final_after_seconds": "oops", + } + ) + assert restored.edit_interval == 1.0 + assert restored.buffer_threshold == 40 + assert restored.fresh_final_after_seconds == 60.0 + + class TestGatewayConfigRoundtrip: def test_full_roundtrip(self): config = GatewayConfig(