hyf

Context-aware query service for Radroots
git clone https://radroots.dev/git/hyf.git
Log | Files | Refs | README | LICENSE

commit 723d29ccbf1062cc40d39d9b865e0dcd2c327aa3
parent 1c7566e06a2e4ca91aaae22c312319eae51a73a0
Author: triesap <tyson@radroots.org>
Date:   Mon, 15 Jun 2026 14:12:53 -0700

runtime: reject padded provider config

- reject leading or trailing whitespace on assisted.provider and max_local string settings

- validate HTTP URLs without silently trimming runtime config values

- cover provider, URL, model, and route padding through stdio config-load failures

- validation: pixi run test-provider-adapter; pixi run test; rg -n 'python|\.py\b|max_local_http_stub' pixi.toml src tests

Diffstat:
Msrc/hyf_runtime/config.mojo | 25+++++++++++++++++++++++--
Mtests/test_stdio_contract.mojo | 48++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/src/hyf_runtime/config.mojo b/src/hyf_runtime/config.mojo @@ -139,6 +139,11 @@ def _validate_runtime_config(config: HyfRuntimeConfig) raises: "runtime.default_execution_mode must be 'deterministic' in the foundation wave" ) + if config.assisted.provider != "": + _require_no_boundary_whitespace( + config.assisted.provider, "assisted.provider" + ) + if config.runtime.allow_assisted: if config.assisted.provider != "max_local": raise Error( @@ -165,9 +170,13 @@ def _require_non_empty(value: String, context: String) raises: raise Error(context + " must not be empty") +def _require_no_boundary_whitespace(value: String, context: String) raises: + if String(value) != String(value).strip(): + raise Error(context + " must not include leading or trailing whitespace") + + def _require_http_url(value: String, context: String) raises: - var trimmed = String(value).strip() - if not (trimmed.startswith("http://") or trimmed.startswith("https://")): + if not (value.startswith("http://") or value.startswith("https://")): raise Error(context + " must use http or https") @@ -175,10 +184,22 @@ def _validate_max_local_provider_config( config: HyfMaxLocalProviderRuntimeConfig ) raises: _require_non_empty(config.base_url, "assisted.max_local.base_url") + _require_no_boundary_whitespace( + config.base_url, "assisted.max_local.base_url" + ) _require_http_url(config.base_url, "assisted.max_local.base_url") _require_non_empty(config.health_url, "assisted.max_local.health_url") + _require_no_boundary_whitespace( + config.health_url, "assisted.max_local.health_url" + ) _require_http_url(config.health_url, "assisted.max_local.health_url") _require_non_empty(config.model, "assisted.max_local.model") + _require_no_boundary_whitespace( + config.model, "assisted.max_local.model" + ) _require_non_empty(config.route, "assisted.max_local.route") + _require_no_boundary_whitespace( + config.route, "assisted.max_local.route" + ) if config.request_timeout_ms <= 0: raise Error("assisted.max_local.request_timeout_ms must be greater than zero") diff --git a/tests/test_stdio_contract.mojo b/tests/test_stdio_contract.mojo @@ -934,6 +934,10 @@ def test_status_rejects_invalid_max_local_runtime_config() raises: "assisted.provider", ) _assert_invalid_runtime_config_load_error( + prefix + '[assisted]\nprovider = " max_local"\n', + "assisted.provider", + ) + _assert_invalid_runtime_config_load_error( disabled_prefix + provider + max_local_header @@ -958,6 +962,28 @@ def test_status_rejects_invalid_max_local_runtime_config() raises: prefix + provider + max_local_header + + 'base_url = " http://127.0.0.1:8000/v1"\n' + + 'health_url = "http://127.0.0.1:8000/health"\n' + + 'model = "max-local-query-rewrite"\n' + + 'route = "provider_runtime.query_rewrite.max_local"\n' + + 'request_timeout_ms = 15000\n', + "assisted.max_local.base_url", + ) + _assert_invalid_runtime_config_load_error( + prefix + + provider + + max_local_header + + 'base_url = "http://127.0.0.1:8000/v1"\n' + + 'health_url = "http://127.0.0.1:8000/health "\n' + + 'model = "max-local-query-rewrite"\n' + + 'route = "provider_runtime.query_rewrite.max_local"\n' + + 'request_timeout_ms = 15000\n', + "assisted.max_local.health_url", + ) + _assert_invalid_runtime_config_load_error( + prefix + + provider + + max_local_header + 'base_url = "file:///tmp/max"\n' + 'health_url = "http://127.0.0.1:8000/health"\n' + 'model = "max-local-query-rewrite"\n' @@ -971,6 +997,17 @@ def test_status_rejects_invalid_max_local_runtime_config() raises: + max_local_header + 'base_url = "http://127.0.0.1:8000/v1"\n' + 'health_url = "http://127.0.0.1:8000/health"\n' + + 'model = " max-local-query-rewrite"\n' + + 'route = "provider_runtime.query_rewrite.max_local"\n' + + 'request_timeout_ms = 15000\n', + "assisted.max_local.model", + ) + _assert_invalid_runtime_config_load_error( + prefix + + provider + + max_local_header + + 'base_url = "http://127.0.0.1:8000/v1"\n' + + 'health_url = "http://127.0.0.1:8000/health"\n' + 'model = ""\n' + 'route = "provider_runtime.query_rewrite.max_local"\n' + 'request_timeout_ms = 15000\n', @@ -983,6 +1020,17 @@ def test_status_rejects_invalid_max_local_runtime_config() raises: + 'base_url = "http://127.0.0.1:8000/v1"\n' + 'health_url = "http://127.0.0.1:8000/health"\n' + 'model = "max-local-query-rewrite"\n' + + 'route = "provider_runtime.query_rewrite.max_local "\n' + + 'request_timeout_ms = 15000\n', + "assisted.max_local.route", + ) + _assert_invalid_runtime_config_load_error( + prefix + + provider + + max_local_header + + 'base_url = "http://127.0.0.1:8000/v1"\n' + + 'health_url = "http://127.0.0.1:8000/health"\n' + + 'model = "max-local-query-rewrite"\n' + 'route = ""\n' + 'request_timeout_ms = 15000\n', "assisted.max_local.route",