Files
EvoScientist-Multi/tests/test_admin_control_v2.py
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

163 lines
5.7 KiB
Python

from __future__ import annotations
import sqlite3
from dataclasses import fields
import pytest
from EvoScientist.llm.config_admin import EvoModelConfigAdminService
from EvoScientist.llm.contracts import (
ADMIN_CONTROL_VERSION,
CommitProposalRequest,
CreateProposalRequest,
HmacGrantAuthority,
ProbeProposalRequest,
UpdateProposalRequest,
ValidateProposalRequest,
)
from EvoScientist.llm.crypto import HmacKeyRing, KeyMaterial, sha256_id
from EvoScientist.llm.model_config import FileEvoModelConfigStore
from EvoScientist.llm.secret_store import EncryptedModelSecretStore
from tests.test_provider_model_config_v3 import v3_payload
def _request(authority, cls, action: str, **values):
payload = {"admin_control_version": ADMIN_CONTROL_VERSION, **values}
operation_id = str(values["operation_id"])
grant = authority.sign_admin(
subject_id="admin-1",
action=action,
operation_id=operation_id,
request_digest=sha256_id(payload),
)
valid = {item.name for item in fields(cls)}
complete = {**values, "admin_grant": grant, "admin_control_version": 2}
return cls(**{key: complete[key] for key in valid})
@pytest.mark.asyncio
async def test_admin_control_v2_proposal_commit(tmp_path) -> None:
authority = HmacGrantAuthority("g" * 32, key_id="grant-v1")
ring = HmacKeyRing(KeyMaterial.create("identity-v1", "i" * 32))
store = FileEvoModelConfigStore(
tmp_path / "model_routes.yaml",
admin_verifier=authority,
ops_path=tmp_path / "model_config_ops.sqlite",
)
secrets = EncryptedModelSecretStore(
tmp_path / "model_secrets.sqlite", master_secret="s" * 32
)
payload = v3_payload()
for provider in payload["providers"]:
item = secrets.create_pending(
provider["provider_id"],
"sk-" + provider["provider_id"],
created_by="admin-1",
operation_id="secret-" + provider["provider_id"],
)
provider["connection"]["credential_ref"] = item.ref
service = EvoModelConfigAdminService(
store,
grant_authority=authority,
identity_key_ring=ring,
secret_resolver=secrets.resolve,
secret_store=secrets,
probe_runner=lambda _config, _route, _kind: True,
)
created = service.create_proposal(
_request(
authority,
CreateProposalRequest,
"model_config:proposal:create",
operation_id="create-1",
expected_active_revision=0,
)
)
updated = service.update_proposal(
_request(
authority,
UpdateProposalRequest,
"model_config:proposal:update",
operation_id="update-1",
proposal_id=created.proposal_id,
expected_state_version=created.state_version,
expected_draft_etag=created.draft_etag,
draft_payload=payload,
)
)
validated = service.validate_proposal(
_request(
authority,
ValidateProposalRequest,
"model_config:proposal:validate",
operation_id="validate-1",
proposal_id=created.proposal_id,
expected_state_version=updated.state_version,
expected_draft_etag=updated.draft_etag,
)
)
current = validated
for index, route in enumerate(validated.routes):
for kind in route["required_probe_kinds"]:
current = await service.probe_proposal(
_request(
authority,
ProbeProposalRequest,
"model_config:proposal:probe",
operation_id=f"probe-{index}-{kind}",
proposal_id=created.proposal_id,
validated_digest=validated.validated_digest,
route_semantics_hash=route["route_semantics_hash"],
probe_kind=kind,
)
)
assert current.state == "READY"
committed = service.commit_proposal(
_request(
authority,
CommitProposalRequest,
"model_config:proposal:commit",
operation_id="commit-1",
proposal_id=created.proposal_id,
expected_active_revision=0,
expected_state_version=current.state_version,
expected_draft_etag=current.draft_etag,
validated_digest=validated.validated_digest,
evidence_ids=current.evidence_ids,
)
)
assert committed.state == "COMMITTED"
assert committed.active_revision == 1
active = store.load()
assert active.schema_version == 3
assert len(active.providers) == 4
assert all(item.status == "active" for item in secrets.list_metadata())
with sqlite3.connect(store.ops_path) as connection:
connection.execute(
"UPDATE config_commit_operations SET stage='CONFIG_COMMITTED' WHERE operation_id='commit-1'"
)
connection.execute(
"UPDATE config_proposals SET state='COMMITTING' WHERE proposal_id=?",
(created.proposal_id,),
)
EvoModelConfigAdminService(
store,
grant_authority=authority,
identity_key_ring=ring,
secret_resolver=secrets.resolve,
secret_store=secrets,
probe_runner=lambda _config, _route, _kind: True,
)
with sqlite3.connect(store.ops_path) as connection:
stage = connection.execute(
"SELECT stage FROM config_commit_operations WHERE operation_id='commit-1'"
).fetchone()[0]
state = connection.execute(
"SELECT state FROM config_proposals WHERE proposal_id=?",
(created.proposal_id,),
).fetchone()[0]
assert stage == "COMPLETED"
assert state == "COMMITTED"