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"