From a3ca32355aff15a781502f8349cb681109b67d02 Mon Sep 17 00:00:00 2001 From: Chaim Date: Mon, 4 May 2026 06:17:22 +0000 Subject: [PATCH] fix(settings): tighten coerce/normalize per code review - reject non-integer floats in int coerce path - document masking responsibility on to_public_dict - use tuple for enum_values (immutable) - treat empty string as None in normalize_for_compare --- web/mcp_env_catalog.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web/mcp_env_catalog.py b/web/mcp_env_catalog.py index 0de73f1..a16f91a 100644 --- a/web/mcp_env_catalog.py +++ b/web/mcp_env_catalog.py @@ -26,11 +26,11 @@ class EnvSpec: default: Any = None min: float | None = None max: float | None = None - enum_values: list[str] | None = None + enum_values: tuple[str, ...] | None = None def to_public_dict(self) -> dict[str, Any]: - d = asdict(self) - return d + """Return spec fields as a dict. Does NOT mask secret values — caller must handle.""" + return asdict(self) ENV_CATALOG: dict[str, EnvSpec] = { @@ -162,6 +162,8 @@ def coerce(spec: EnvSpec, raw: Any) -> Any: return False raise ValueError(f"ערך bool לא חוקי: {raw}") if spec.type == "int": + if isinstance(raw, float) and not raw.is_integer(): + raise ValueError(f"ערך int לא חוקי (שבר עשרוני): {raw}") try: v = int(raw) except (TypeError, ValueError): @@ -190,7 +192,7 @@ def coerce(spec: EnvSpec, raw: Any) -> Any: def normalize_for_compare(spec: EnvSpec, raw: str | None) -> str | None: """Normalize a raw env string to a canonical form for drift comparison.""" - if raw is None: + if not raw: # None or "" return None try: v = coerce(spec, raw)