Files
EvoScientist-Multi/tests/test_model_config_v4.py
T
m4 5a581c78a2
Build / build (push) Has been cancelled
Docker / build (push) Has been cancelled
Lint / ruff (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.11) (push) Has been cancelled
Test / pytest (ubuntu-latest, 3.12) (push) Has been cancelled
Test / pytest (windows-latest, 3.11) (push) Has been cancelled
Test / pytest (windows-latest, 3.12) (push) Has been cancelled
feat: add scoped model runtime configuration
Introduce provider, model, and invocation contracts with encrypted configuration persistence. Add web runtime fencing, route fallback, recovery middleware, workspace scoping, and comprehensive tests.
2026-08-14 22:03:04 +08:00

823 lines
29 KiB
Python

from __future__ import annotations
import json
import sqlite3
import uuid
from datetime import UTC, datetime, timedelta
import pytest
from EvoScientist.llm.contracts import EvoRuntimeError, HmacGrantAuthority
from EvoScientist.llm.crypto import HmacKeyRing, KeyMaterial, sha256_id
from EvoScientist.llm.model_config_v4 import (
EvoModelConfig,
UnifiedModelConfigStore,
build_supported_v3_evidence,
model_profile_identity_map,
normalize_v4_config,
project_v4_to_v3,
)
from EvoScientist.llm.runtime import EvoModelRuntime
def _payload(*, provider_id: str | None = None, profile_id: str | None = None) -> dict:
provider_id = provider_id or str(uuid.uuid4())
profile_id = profile_id or str(uuid.uuid4())
return {
"schema_version": 4,
"default_model_profile_id": profile_id,
"purpose_defaults": {},
"purpose_call_limits": {},
"providers": [
{
"provider_id": provider_id,
"display_name": "OpenAI Production",
"adapter_id": "openai",
"adapter_revision": "openai-v1",
"enabled": True,
"connection": {"base_url": "https://api.openai.com/v1"},
"models": [
{
"model_profile_id": profile_id,
"provider_model_id": "gpt-test",
"display_name": "General",
"enabled": True,
"version_policy": "rolling",
"invocation": {
"api_mode": "responses",
"tool_call_transport": "native",
},
"capabilities": {"text": True, "tools": True},
"limits": {
"context_tokens": 128_000,
"max_output_tokens": 8_192,
},
"parameters": {},
"billing": {
"sku": "internal/gpt-test",
"pricing_revision": "configured-v1",
"currency": "CNY",
"unit_scale": 1_000_000,
"input_microunits_per_million": 1_000_000,
"cached_microunits_per_million": 200_000,
"output_microunits_per_million": 4_000_000,
"multiplier": 1,
},
}
],
}
],
}
def _ring() -> HmacKeyRing:
return HmacKeyRing(KeyMaterial.create("identity-v1", "i" * 32))
def test_v4_normalization_uses_stable_profile_identity():
payload = normalize_v4_config(_payload())
identities = model_profile_identity_map(payload)
assert payload["schema_version"] == 4
assert payload["default_model_profile_id"] in identities
assert identities[payload["default_model_profile_id"]][1] == "gpt-test"
def test_v4_rejects_enabled_model_without_billing_configuration():
raw = _payload()
raw["providers"][0]["models"][0].pop("billing")
with pytest.raises(EvoRuntimeError) as raised:
normalize_v4_config(raw, lenient=True, warnings=[])
assert raised.value.details[0]["code"] == "CONFIG_PRICING_REQUIRED"
def test_v4_accepts_explicit_zero_price_for_free_model():
raw = _payload()
raw["providers"][0]["models"][0]["billing"].update(
input_microunits_per_million=0,
cached_microunits_per_million=0,
output_microunits_per_million=0,
)
payload = normalize_v4_config(raw, lenient=True, warnings=[])
assert payload["providers"][0]["models"][0]["billing"][
"input_microunits_per_million"
] == 0
def test_v4_normalization_preserves_model_output_token_limit():
raw = _payload()
raw["providers"][0]["models"][0]["parameters"] = {
"defaults": {"output_token_limit": 2048, "temperature": 0.2},
"purpose_overrides": {
"main_agent": {"output_token_limit": 1024, "temperature": 0.3}
},
"user_options": {
"output_token_limit": {
"default": 512,
"applies_to": ["main_agent"],
}
},
}
payload = normalize_v4_config(raw)
parameters = payload["providers"][0]["models"][0]["parameters"]
assert parameters["defaults"] == {"output_token_limit": 2048, "temperature": 0.2}
assert parameters["purpose_overrides"]["main_agent"] == {
"output_token_limit": 1024,
"temperature": 0.3,
}
assert parameters["user_options"] == {}
for limit in payload["purpose_call_limits"].values():
assert "max_output_tokens" not in limit
assert payload["purpose_call_limits"]["main_agent"] == {
"max_attempts_per_run": 4
}
def test_v4_rejects_output_token_limit_above_model_capability():
raw = _payload()
raw["providers"][0]["models"][0]["parameters"] = {
"defaults": {"output_token_limit": 16_384}
}
with pytest.raises(EvoRuntimeError) as raised:
normalize_v4_config(raw)
assert raised.value.code == "LLM_ROUTE_CONFIGURATION_REQUIRED"
assert raised.value.details[0]["code"] == "CONFIG_LIMIT_EXCEEDED"
def test_v4_lenient_clamps_output_token_limit_to_model_capability():
raw = _payload()
raw["providers"][0]["models"][0]["parameters"] = {
"defaults": {"output_token_limit": 16_384}
}
warnings: list[dict] = []
payload = normalize_v4_config(raw, lenient=True, warnings=warnings)
defaults = payload["providers"][0]["models"][0]["parameters"]["defaults"]
assert defaults["output_token_limit"] == 8_192
assert any(item["code"] == "CONFIG_LIMIT_EXCEEDED" for item in warnings)
def test_v4_removes_legacy_tool_transport_from_admin_config():
raw = _payload()
raw["providers"][0]["models"][0]["capabilities"]["tools"] = False
payload = normalize_v4_config(raw)
model = payload["providers"][0]["models"][0]
assert model["invocation"] == {"api_mode": "responses"}
def test_v4_runtime_projection_derives_tool_transport_from_capabilities():
raw = _payload()
raw["providers"][0]["models"][0]["capabilities"]["tools"] = False
warnings: list[dict] = []
payload = normalize_v4_config(raw, lenient=True, warnings=warnings)
model = payload["providers"][0]["models"][0]
assert "tool_call_transport" not in model["invocation"]
assert not any(
item["code"] == "CONFIG_INVOCATION_CONTRACT_INVALID" for item in warnings
)
projection = project_v4_to_v3(
payload,
revision=1,
identity_key_id=_ring().current.key_id,
bindings={payload["providers"][0]["provider_id"]: 1},
)
config = EvoModelConfig.parse(projection, require_evidence=False)
route = config.concrete_routes(next(iter(config.route_selectors)))[0]
assert route.tool_call_transport == "disabled"
def test_v4_rejects_non_uuid_business_ids():
raw = _payload(provider_id="openai-main")
with pytest.raises(EvoRuntimeError) as raised:
normalize_v4_config(raw)
assert raised.value.code == "LLM_ROUTE_CONFIGURATION_REQUIRED"
@pytest.mark.parametrize(
"base_url",
[
"",
"not a url",
"ftp://user:pass@example.test/path?key=value#fragment",
"http://127.0.0.1:11434/v1",
"https://169.254.169.254/latest/meta-data",
"custom://model.internal:70000/path",
],
)
def test_v4_base_url_is_not_validated(base_url):
raw = _payload()
raw["providers"][0]["connection"]["base_url"] = base_url
payload = normalize_v4_config(raw)
provider_id = payload["providers"][0]["provider_id"]
projection = project_v4_to_v3(
payload,
revision=1,
identity_key_id=_ring().current.key_id,
bindings={provider_id: 1},
)
assert payload["providers"][0]["connection"]["base_url"] == base_url
assert projection["providers"][0]["connection"]["base_url"] == base_url
def test_unified_store_commits_config_and_secret_without_evidence_gate(tmp_path):
ring = _ring()
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
payload = normalize_v4_config(_payload())
provider_id = payload["providers"][0]["provider_id"]
profile_id = payload["default_model_profile_id"]
plan = store.plan_credentials(payload, {provider_id: "sk-secret-value"})
projection = project_v4_to_v3(
payload,
revision=1,
identity_key_id=ring.current.key_id,
bindings=plan.bindings,
)
evidence = build_supported_v3_evidence(
projection,
identity_key_ring=ring,
verified_profiles={provider_id: frozenset({profile_id})},
)
request_hash = sha256_id({"payload": payload, "fingerprints": plan.fingerprints})
store.begin_operation(
"save-1",
request_hash=request_hash,
expected_revision=0,
actor="admin",
lease_owner="worker-1",
)
result = store.commit(
payload,
expected_revision=0,
operation_id="save-1",
actor="admin",
request_hash=request_hash,
credential_plan=plan,
evidence=evidence,
)
assert result.config_revision == 1
assert result.changed is True
runtime = store.load()
assert runtime.main_routes.default_alias == profile_id
assert store.resolve(
runtime.providers[provider_id].endpoints[provider_id].auth
).value == "sk-secret-value"
revision, admin_payload, credentials = store.get_admin_config()
assert revision == 1
assert admin_payload == payload
assert credentials[provider_id].configured is True
assert "sk-secret-value" not in str(credentials)
with sqlite3.connect(store.path) as connection:
assert connection.execute("SELECT COUNT(*) FROM model_config_revisions").fetchone()[0] == 1
assert connection.execute("SELECT COUNT(*) FROM provider_secret_versions").fetchone()[0] == 1
assert connection.execute("SELECT COUNT(*) FROM capability_evidence").fetchone()[0] == 0
store.record_runtime_observation(
config_revision=1,
provider_id=provider_id,
model_profile_id=profile_id,
provider_model_id="gpt-test",
api_mode="responses",
purpose="main_agent",
outcome="succeeded",
error_code=None,
strategy={"structured_output": False},
)
summary = store.runtime_observation_summary()
assert len(summary) == 1
assert summary[0]["model_profile_id"] == profile_id
assert summary[0]["provider_id"] == provider_id
assert summary[0]["latest_outcome"] == "succeeded"
assert summary[0]["latest_error_code"] is None
assert summary[0]["total_calls"] == 1
assert summary[0]["successful_calls"] == 1
assert summary[0]["strategy"] == {"structured_output": False}
assert summary[0]["latest_at"]
def test_unified_store_idempotency_rejects_same_id_different_request(tmp_path):
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=_ring(),
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
store.begin_operation(
"save-1",
request_hash="hmac:one",
expected_revision=0,
actor="admin",
lease_owner="worker-1",
)
with pytest.raises(EvoRuntimeError) as raised:
store.begin_operation(
"save-1",
request_hash="hmac:two",
expected_revision=0,
actor="admin",
lease_owner="worker-2",
)
assert raised.value.code == "IDEMPOTENCY_CONFLICT"
def test_operation_failure_preserves_last_progress(tmp_path):
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=_ring(),
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
store.begin_operation(
"save-1", request_hash="request-1", expected_revision=0,
actor="admin", lease_owner="worker",
)
store.set_operation_status(
"save-1", "PROBING", progress={"completed": 2, "total": 3}
)
store.set_operation_status(
"save-1",
"FAILED_RETRYABLE",
stage="PROBING",
error_code="MODEL_PROBE_FAILED",
error_details=({"path": "models.test", "code": "MODEL_TIMEOUT"},),
)
operation = store.get_operation("save-1")
assert operation is not None
assert operation["progress"] == {"completed": 2, "total": 3}
assert operation["error_details"] == [
{"path": "models.test", "code": "MODEL_TIMEOUT"}
]
def test_unified_store_load_ignores_historical_evidence(tmp_path):
ring = _ring()
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
payload = normalize_v4_config(_payload())
provider_id = payload["providers"][0]["provider_id"]
profile_id = payload["default_model_profile_id"]
plan = store.plan_credentials(payload, {provider_id: "sk-secret-value"})
projection = project_v4_to_v3(
payload, revision=1, identity_key_id=ring.current.key_id, bindings=plan.bindings
)
evidence = build_supported_v3_evidence(
projection,
identity_key_ring=ring,
verified_profiles={provider_id: frozenset({profile_id})},
)
store.begin_operation(
"save-1", request_hash="request-1", expected_revision=0,
actor="admin", lease_owner="worker",
)
store.commit(
payload, expected_revision=0, operation_id="save-1", actor="admin",
request_hash="request-1", credential_plan=plan, evidence=evidence,
)
# The supplied evidence is intentionally not persisted or read by load.
# A legacy/tampered evidence row therefore cannot make the revision stale.
assert store.load_revision(1).config_revision == 1
def test_rollback_publishes_a_new_monotonic_revision(tmp_path):
ring = _ring()
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
first = normalize_v4_config(_payload())
provider_id = first["providers"][0]["provider_id"]
profile_id = first["default_model_profile_id"]
def publish(payload: dict, revision: int, operation_id: str, request_hash: str):
plan = store.plan_credentials(
payload, {provider_id: "sk-secret-value"} if revision == 1 else {}
)
projection = project_v4_to_v3(
payload,
revision=revision,
identity_key_id=ring.current.key_id,
bindings=plan.bindings,
)
evidence = build_supported_v3_evidence(
projection,
identity_key_ring=ring,
verified_profiles={provider_id: frozenset({profile_id})},
)
store.begin_operation(
operation_id, request_hash=request_hash, expected_revision=revision - 1,
actor="admin", lease_owner="worker",
)
return store.commit(
payload, expected_revision=revision - 1, operation_id=operation_id,
actor="admin", request_hash=request_hash, credential_plan=plan,
evidence=evidence,
)
publish(first, 1, "save-1", "request-1")
second = json.loads(json.dumps(first))
second["providers"][0]["display_name"] = "Changed display name"
publish(second, 2, "save-2", "request-2")
store.begin_operation(
"rollback-1", request_hash="rollback-request", expected_revision=2,
actor="admin", lease_owner="worker",
)
result = store.rollback(
target_revision=1,
expected_revision=2,
operation_id="rollback-1",
actor="admin",
request_hash="rollback-request",
)
assert result.config_revision == 3
assert store.current_revision() == 3
assert store.get_admin_config()[1]["providers"][0]["display_name"] == "OpenAI Production"
assert store.load().config_revision == 3
def test_identity_key_rotation_does_not_rotate_unchanged_credential(tmp_path):
first_ring = _ring()
path = tmp_path / "model-config.sqlite"
store = UnifiedModelConfigStore(
path,
identity_key_ring=first_ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
payload = normalize_v4_config(_payload())
provider_id = payload["providers"][0]["provider_id"]
profile_id = payload["default_model_profile_id"]
plan = store.plan_credentials(payload, {provider_id: "sk-same-secret"})
projection = project_v4_to_v3(
payload, revision=1, identity_key_id=first_ring.current.key_id,
bindings=plan.bindings,
)
evidence = build_supported_v3_evidence(
projection,
identity_key_ring=first_ring,
verified_profiles={provider_id: frozenset({profile_id})},
)
store.begin_operation(
"save-1", request_hash="request-1", expected_revision=0,
actor="admin", lease_owner="worker",
)
store.commit(
payload, expected_revision=0, operation_id="save-1", actor="admin",
request_hash="request-1", credential_plan=plan, evidence=evidence,
)
rotated_ring = HmacKeyRing(
KeyMaterial.create("identity-v2", "j" * 32), retained=(first_ring.current,)
)
rotated_store = UnifiedModelConfigStore(
path,
identity_key_ring=rotated_ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
rotated_plan = rotated_store.plan_credentials(
payload, {provider_id: "sk-same-secret"}
)
assert rotated_plan.new_versions == frozenset()
assert rotated_plan.bindings[provider_id] == 1
assert rotated_plan.fingerprints[provider_id] == plan.fingerprints[provider_id]
def test_evidence_requires_observed_results_for_every_declared_capability():
ring = _ring()
raw = _payload()
raw["providers"][0]["models"][0]["capabilities"] = {
"text": True,
"vision": True,
"tools": True,
}
payload = normalize_v4_config(raw)
provider_id = payload["providers"][0]["provider_id"]
profile_id = payload["default_model_profile_id"]
projection = project_v4_to_v3(
payload,
revision=1,
identity_key_id=ring.current.key_id,
bindings={provider_id: 1},
)
with pytest.raises(EvoRuntimeError) as raised:
build_supported_v3_evidence(
projection,
identity_key_ring=ring,
probe_results={
provider_id: {profile_id: {"connectivity": "supported"}}
},
)
assert raised.value.code == "CAPABILITY_EVIDENCE_STALE"
def test_historical_evidence_is_not_reused_for_route_admission(tmp_path):
ring = _ring()
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
payload = normalize_v4_config(_payload())
provider_id = payload["providers"][0]["provider_id"]
profile_id = payload["default_model_profile_id"]
plan = store.plan_credentials(payload, {provider_id: "sk-secret-value"})
projection = project_v4_to_v3(
payload,
revision=1,
identity_key_id=ring.current.key_id,
bindings=plan.bindings,
)
evidence = build_supported_v3_evidence(
projection,
identity_key_ring=ring,
verified_profiles={provider_id: frozenset({profile_id})},
)
store.begin_operation(
"save-1", request_hash="request-1", expected_revision=0,
actor="admin", lease_owner="worker",
)
store.commit(
payload, expected_revision=0, operation_id="save-1", actor="admin",
request_hash="request-1", credential_plan=plan, evidence=evidence,
)
next_payload = json.loads(json.dumps(payload))
next_payload["providers"][0]["display_name"] = "Renamed Provider"
next_plan = store.plan_credentials(next_payload, {})
next_projection = project_v4_to_v3(
next_payload,
revision=2,
identity_key_id=ring.current.key_id,
bindings=next_plan.bindings,
)
observed, windows, missing = store.reusable_probe_results(
next_projection,
fingerprints=next_plan.fingerprints,
versions=next_plan.bindings,
)
assert observed == {}
assert windows == {}
assert missing == frozenset({(provider_id, profile_id)})
def test_availability_reflects_enabled_state(tmp_path):
ring = _ring()
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
raw = _payload()
disabled_profile_id = str(uuid.uuid4())
disabled = json.loads(json.dumps(raw["providers"][0]["models"][0]))
disabled.update(
{
"model_profile_id": disabled_profile_id,
"provider_model_id": "disabled-model",
"display_name": "Disabled",
"enabled": False,
}
)
raw["providers"][0]["models"].append(disabled)
payload = normalize_v4_config(raw)
provider_id = payload["providers"][0]["provider_id"]
profile_id = payload["default_model_profile_id"]
plan = store.plan_credentials(payload, {provider_id: "sk-secret-value"})
store.begin_operation(
"save-1", request_hash="request-1", expected_revision=0,
actor="admin", lease_owner="worker",
)
store.commit(
payload, expected_revision=0, operation_id="save-1", actor="admin",
request_hash="request-1", credential_plan=plan, evidence=[],
)
availability = store.get_model_availability()
assert availability[profile_id] == {
"model_profile_id": profile_id,
"enabled": True,
"selectable": True,
}
assert availability[disabled_profile_id] == {
"model_profile_id": disabled_profile_id,
"enabled": False,
"selectable": False,
}
def test_schema_upgrade_adds_availability_and_operation_columns(tmp_path):
path = tmp_path / "model-config.sqlite"
UnifiedModelConfigStore(
path,
identity_key_ring=_ring(),
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
with sqlite3.connect(path) as connection:
connection.execute("DROP INDEX idx_capability_evidence_semantics")
connection.execute("ALTER TABLE active_model_config DROP COLUMN evidence_epoch")
connection.execute("ALTER TABLE capability_evidence DROP COLUMN credential_version")
connection.execute("ALTER TABLE model_config_operations DROP COLUMN stage")
connection.execute("ALTER TABLE model_config_operations DROP COLUMN progress_json")
connection.execute("ALTER TABLE model_config_operations DROP COLUMN error_details_json")
UnifiedModelConfigStore(
path,
identity_key_ring=_ring(),
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
with sqlite3.connect(path) as connection:
assert "evidence_epoch" in {
row[1] for row in connection.execute("PRAGMA table_info(active_model_config)")
}
assert "credential_version" in {
row[1] for row in connection.execute("PRAGMA table_info(capability_evidence)")
}
operation_columns = {
row[1] for row in connection.execute("PRAGMA table_info(model_config_operations)")
}
assert {"stage", "progress_json", "error_details_json"} <= operation_columns
def test_v3_runtime_accepts_expired_historical_evidence(tmp_path):
ring = _ring()
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
payload = normalize_v4_config(_payload())
provider_id = payload["providers"][0]["provider_id"]
profile_id = payload["default_model_profile_id"]
plan = store.plan_credentials(payload, {provider_id: "sk-secret-value"})
projection = project_v4_to_v3(
payload, revision=1, identity_key_id=ring.current.key_id,
bindings=plan.bindings,
)
now = datetime.now(UTC)
evidence = build_supported_v3_evidence(
projection,
identity_key_ring=ring,
verified_profiles={provider_id: frozenset({profile_id})},
evidence_windows={
provider_id: {
profile_id: (
(now - timedelta(hours=2)).isoformat(timespec="microseconds"),
(now - timedelta(hours=1)).isoformat(timespec="microseconds"),
)
}
},
)
store.begin_operation(
"save-1", request_hash="request-1", expected_revision=0,
actor="admin", lease_owner="worker",
)
store.commit(
payload, expected_revision=0, operation_id="save-1", actor="admin",
request_hash="request-1", credential_plan=plan, evidence=evidence,
)
config = store.load()
authority = HmacGrantAuthority("r" * 32)
runtime = EvoModelRuntime(
store,
admission_verifier=authority,
quote_authority=authority,
identity_key_ring=ring,
secret_resolver=store.resolve,
)
selector = config.resolve_main_selector(None)
route = config.concrete_routes(selector.selector_id)[0]
resolved = runtime._resolve_route(config, route, "main_agent")
assert resolved.identity.model_id == "gpt-test"
def test_lenient_normalization_ignores_unknown_fields_with_warning():
raw = _payload()
raw["unexpected_top"] = True
raw["providers"][0]["unexpected_provider"] = "x"
raw["providers"][0]["models"][0]["unexpected_model"] = 1
warnings: list[dict] = []
payload = normalize_v4_config(raw, lenient=True, warnings=warnings)
assert payload["schema_version"] == 4
assert [item["code"] for item in warnings] == ["CONFIG_UNKNOWN_FIELDS"] * 3
def test_lenient_normalization_clamps_out_of_range_and_timeout_conflict():
raw = _payload()
raw["providers"][0]["connection"] = {
"base_url": "https://api.openai.com/v1",
"connect_timeout_seconds": 120,
"attempt_timeout_seconds": 30,
}
warnings: list[dict] = []
payload = normalize_v4_config(raw, lenient=True, warnings=warnings)
connection = payload["providers"][0]["connection"]
assert connection["connect_timeout_seconds"] == 60
assert connection["attempt_timeout_seconds"] == 60
codes = {item["code"] for item in warnings}
assert "CONFIG_VALUE_OUT_OF_RANGE" in codes
assert "CONFIG_VALUE_CONFLICT" in codes
def test_lenient_normalization_forces_text_capability_and_keeps_unknown_purpose():
raw = _payload()
raw["providers"][0]["models"][0]["capabilities"] = {"text": False, "vision": True}
raw["providers"][0]["models"][0]["parameters"] = {
"purpose_overrides": {"custom_purpose": {"temperature": 0.5}}
}
warnings: list[dict] = []
payload = normalize_v4_config(raw, lenient=True, warnings=warnings)
model = payload["providers"][0]["models"][0]
assert model["capabilities"]["text"] is True
assert model["parameters"]["purpose_overrides"]["custom_purpose"] == {"temperature": 0.5}
assert any(item["code"] == "CONFIG_REQUIRED" for item in warnings)
assert any(item["code"] == "CONFIG_REFERENCE_INVALID" for item in warnings)
def test_strict_normalization_still_rejects_unknown_fields():
raw = _payload()
raw["unexpected_top"] = True
with pytest.raises(EvoRuntimeError):
normalize_v4_config(raw)
def test_unverified_enabled_model_is_selectable(tmp_path):
ring = _ring()
store = UnifiedModelConfigStore(
tmp_path / "model-config.sqlite",
identity_key_ring=ring,
encryption_keys={"enc-v1": "e" * 32},
current_encryption_key_id="enc-v1",
)
payload = normalize_v4_config(_payload())
provider_id = payload["providers"][0]["provider_id"]
profile_id = payload["default_model_profile_id"]
plan = store.plan_credentials(payload, {provider_id: "sk-secret-value"})
store.begin_operation(
"save-1", request_hash="request-1", expected_revision=0,
actor="admin", lease_owner="worker",
)
store.commit(
payload, expected_revision=0, operation_id="save-1", actor="admin",
request_hash="request-1", credential_plan=plan, evidence=[],
)
availability = store.get_model_availability()[profile_id]
assert availability == {
"model_profile_id": profile_id,
"enabled": True,
"selectable": True,
}