Files
ai-contract-platform/yuqei-infra/tests/test_production_release_tools.py
T

1658 lines
66 KiB
Python

from __future__ import annotations
import base64
import hashlib
import importlib.util
import io
import json
import sys
import tarfile
from datetime import datetime, timezone
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from threading import Thread
from types import ModuleType, SimpleNamespace
import pytest
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
REPO_ROOT = Path(__file__).resolve().parents[2]
def load_script(name: str, relative_path: str) -> ModuleType:
path = REPO_ROOT / relative_path
spec = importlib.util.spec_from_file_location(name, path)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module
preflight = load_script("yuqei_production_preflight", "yuqei-infra/deploy/preflight-production.py")
backup_run = load_script("yuqei_backup_run", "yuqei-infra/backup/run-production-backup.py")
backup_verify = load_script("yuqei_backup_verify", "yuqei-infra/backup/verify-production-backup.py")
provider_acceptance = load_script("yuqei_provider_acceptance", "yuqei-infra/scripts/run-ai-provider-acceptance.py")
contract_product_golden = load_script(
"yuqei_contract_product_golden",
"yuqei-infra/scripts/run-contract-product-golden.py",
)
release_quality_gate = load_script(
"yuqei_release_quality_gate",
"yuqei-infra/scripts/run-release-quality-gate.py",
)
from yuqei_ai_platform_api.provider_acceptance_receipt import ( # noqa: E402
RECEIPT_DOMAIN,
ProviderAcceptanceReceiptPayload,
SignedProviderAcceptanceReceipt,
canonical_receipt_payload,
)
def production_values() -> dict[str, str]:
values = preflight.parse_env_file(REPO_ROOT / "yuqei-infra/compose/.env.production.example")
replacements = {
"RELEASE_ID": "v2.0.0-rc.1",
"CONTRACT_API_IMAGE": f"registry.internal/contract-api@sha256:{'1' * 64}",
"CONTRACT_WEB_IMAGE": f"registry.internal/contract-web@sha256:{'c' * 64}",
"AI_PLATFORM_API_IMAGE": f"registry.internal/ai-platform-api@sha256:{'2' * 64}",
"AI_PLATFORM_RELEASE_IMAGE_DIGEST": f"sha256:{'2' * 64}",
"CONTRACT_API_PUBLIC_POLICY_RELEASE_DIGEST": f"sha256:{'1' * 64}",
"AI_WORKER_IMAGE": f"registry.internal/ai-worker@sha256:{'3' * 64}",
"POSTGRES_IMAGE": f"registry.internal/pgvector@sha256:{'4' * 64}",
"POSTGRES_CLIENT_IMAGE": f"registry.internal/postgres@sha256:{'5' * 64}",
"REDIS_IMAGE": f"registry.internal/redis@sha256:{'6' * 64}",
"MINIO_IMAGE": f"registry.internal/minio@sha256:{'7' * 64}",
"MINIO_MC_IMAGE": f"registry.internal/minio-mc@sha256:{'8' * 64}",
"NGINX_IMAGE": f"registry.internal/nginx@sha256:{'9' * 64}",
"BACKUP_UTILITY_IMAGE": f"registry.internal/alpine@sha256:{'a' * 64}",
"BACKEND_SERVER_NAME": "api.contracts.acme.cn",
"BACKEND_PUBLIC_BASE_URL": "https://api.contracts.acme.cn",
"POSTGRES_USER": "yuqei_prod",
"POSTGRES_PASSWORD": "postgres-secret-that-is-long-and-unique-001",
"MINIO_ROOT_USER": "yuqei_prod_minio",
"MINIO_ROOT_PASSWORD": "minio-secret-that-is-long-and-unique-002",
"CONTRACT_API_WEB_PROXY_SHARED_SECRET": "proxy-secret-that-is-long-and-unique-003",
"CONTRACT_API_IDENTITY_RATE_LIMIT_SECRET": "identity-secret-that-is-long-and-unique-004",
"CONTRACT_API_ANTI_ABUSE_HASH_SECRET": "contract-anti-abuse-secret-that-is-long-004a", # pragma: allowlist secret
"CONTRACT_WEB_SESSION_SECRET": "session-secret-that-is-long-and-unique-005",
"AI_PLATFORM_SERVICE_SHARED_SECRET": "ai-service-secret-that-is-long-and-unique-006",
"KMS_GATEWAY_IMAGE": f"registry.internal/kms-gateway@sha256:{'b' * 64}",
"KMS_GATEWAY_ALLOWED_KEY_IDS": "calendar-envelope-key-v1",
"KMS_GATEWAY_PRIMARY_KEY_ID": "calendar-envelope-key-v1",
"KMS_GATEWAY_ALLOWED_SIGNING_KEY_IDS": "reliable-evidence-signing-key-v1",
"KMS_GATEWAY_SIGNING_KEY_ID": "reliable-evidence-signing-key-v1",
"KMS_GATEWAY_SIGNING_KEY_VERSION": "version-2026-08-25",
"ALIYUN_KMS_ENDPOINT": "kst-production.cryptoservice.kms.aliyuncs.com",
"AI_PLATFORM_GENERATIVE_AI_FILING_NUMBER": "内网信算备-TEST-001",
"AI_PLATFORM_GENERATIVE_AI_SERVICE_REGISTRATION_NUMBER": "内网信生测评-TEST-001",
"AI_PLATFORM_GENERATIVE_AI_SERVICE_PROVIDER_CODE": "yuqei-test-provider-code",
"AI_PLATFORM_PROVIDER_ACCEPTANCE_EXPECTED_RECEIPT_SHA256": hashlib.sha256(
b"pinned-production-provider-acceptance-receipt"
).hexdigest(),
"PRODUCTION_ALERT_WEBHOOK_URL_FILE": "/etc/yuqei/monitoring/alert-webhook-url",
"AI_PLATFORM_ANTI_ABUSE_HASH_SECRET": "ai-anti-abuse-secret-that-is-long-and-unique-006a", # pragma: allowlist secret
"CONTRACT_API_DATABASE_URL": "postgresql+psycopg://yuqei_prod:encoded-password@postgres:5432/yuqei_contract",
"AI_PLATFORM_DATABASE_URL": "postgresql+psycopg://yuqei_prod:encoded-password@postgres:5432/yuqei_ai",
"YUQEI_WORKER_DATABASE_URL": "postgresql+psycopg://yuqei_prod:encoded-password@postgres:5432/yuqei_ai",
}
values.update(replacements)
return values
def test_minio_backup_invokes_pinned_mc_directly_without_a_shell(tmp_path: Path) -> None:
partial_dir = tmp_path / ".backup-20260811T120000Z.partial"
credentials = tmp_path / "minio.env"
values = {
"COMPOSE_PROJECT_NAME": "yuqei-v2-production",
"AI_PLATFORM_OBJECT_STORAGE_BUCKET": "ai-platform-uploads",
"MINIO_MC_IMAGE": f"minio/mc@sha256:{'a' * 64}",
}
command = backup_run.minio_mirror_command(
values=values,
partial_dir=partial_dir,
credential_env_file=credentials,
)
assert command[:2] == ["docker", "run"]
assert "--entrypoint" not in command
assert "/bin/sh" not in command
assert command[-4:] == [
"mirror",
"--overwrite",
"source/ai-platform-uploads",
"/backup/minio",
]
assert command[command.index("--env-file") + 1] == str(credentials)
assert all("secret" not in token for token in command)
@pytest.mark.parametrize(
("label", "validation_name", "table_name"),
[
("contract", "contract_api_alembic_version", "contract_api_alembic_version"),
("ai_platform", "ai_platform_alembic_version", "ai_platform_alembic_version"),
("operations", "public_table_count", "information_schema.tables"),
],
)
def test_restore_check_uses_each_database_owned_schema_marker(
label: str,
validation_name: str,
table_name: str,
) -> None:
actual_name, query = backup_verify.restore_validation_query(label)
assert actual_name == validation_name
assert table_name in query
def test_production_preflight_accepts_strict_configuration() -> None:
checks = preflight.validate_environment(production_values())
assert [check.key for check in checks if check.status == "fail"] == []
def test_production_launch_scope_excludes_support_access_and_identity_execution() -> None:
manifest = json.loads(preflight.LAUNCH_SCOPE_MANIFEST_PATH.read_text(encoding="utf-8"))
assert manifest == preflight.EXPECTED_LAUNCH_SCOPE
assert manifest["decision"] == "excluded"
assert manifest["support_access"] == {
"included": False,
"enabled": False,
"kill_switch_engaged": True,
"executor_enabled": False,
}
assert manifest["identity_executor"] == {"enabled": False}
assert manifest["destructive_identity_write_api"]["included"] is False
assert set(manifest["destructive_identity_write_api"]["forbidden_operations"]) == {
"execute",
"grant",
"revoke",
"impersonate",
"impersonation",
}
@pytest.mark.parametrize(
"activation_key",
sorted(preflight.FORBIDDEN_SUPPORT_ACCESS_ACTIVATION_KEYS),
)
def test_production_preflight_rejects_support_access_or_identity_write_activation(
activation_key: str,
) -> None:
values = production_values()
values[activation_key] = "true"
checks = {check.key: check for check in preflight.validate_environment(values)}
assert checks["launch_scope_activation_flags"].status == "fail"
assert activation_key in checks["launch_scope_activation_flags"].message
@pytest.mark.parametrize("artifact_state", ["missing", "tampered", "invalid"])
def test_production_preflight_fails_closed_on_launch_scope_artifact_drift(
tmp_path: Path,
artifact_state: str,
) -> None:
manifest_path = tmp_path / "launch-scope.json"
if artifact_state == "tampered":
tampered = dict(preflight.EXPECTED_LAUNCH_SCOPE)
tampered["support_access"] = {
**tampered["support_access"],
"enabled": True,
}
manifest_path.write_text(json.dumps(tampered), encoding="utf-8")
elif artifact_state == "invalid":
manifest_path.write_text("not-json", encoding="utf-8")
checks = {
check.key: check
for check in preflight._validate_launch_scope_exclusion(
production_values(),
manifest_path=manifest_path,
)
}
assert checks["launch_scope_support_access_exclusion"].status == "fail"
@pytest.mark.parametrize(
("contract_timeout", "provider_timeout"),
[("30", "30"), ("0", "30"), ("601", "30"), ("NaN", "30"), ("60", "inf")],
)
def test_production_preflight_rejects_invalid_ai_timeout_budgets(
contract_timeout: str,
provider_timeout: str,
) -> None:
values = production_values()
values["CONTRACT_API_AI_PLATFORM_TIMEOUT_SECONDS"] = contract_timeout
values["AI_PLATFORM_PROVIDER_REQUEST_TIMEOUT_SECONDS"] = provider_timeout
checks = {check.key: check for check in preflight.validate_environment(values)}
assert checks["ai_timeout_budget"].status == "fail"
def test_production_preflight_rejects_promotion_image_digest_drift() -> None:
values = production_values()
values["AI_PLATFORM_RELEASE_IMAGE_DIGEST"] = f"sha256:{'f' * 64}"
checks = {check.key: check for check in preflight.validate_environment(values)}
assert checks["provider_promotion_image_binding"].status == "fail"
@pytest.mark.parametrize(
"forbidden_key",
[
"AI_PLATFORM_PROVIDER_LEGAL_ATTESTATION_SECRET",
"AI_PLATFORM_PROVIDER_ACCEPTANCE_SIGNING_PRIVATE_KEY_FILE",
"AI_PLATFORM_PROVIDER_ACCEPTANCE_SIGNING_KEY",
"AI_PLATFORM_PROVIDER_ACCEPTANCE_STAGING_DATABASE_URL",
"SHARED_STAGING_POSTGRES_PASSWORD",
],
)
def test_production_preflight_rejects_promotion_private_or_staging_credentials(
forbidden_key: str,
) -> None:
values = production_values()
values[forbidden_key] = "must-not-enter-production"
checks = {check.key: check for check in preflight.validate_environment(values)}
assert checks["provider_acceptance_credential_isolation"].status == "fail"
assert forbidden_key in checks["provider_acceptance_credential_isolation"].message
@pytest.mark.parametrize(
("key", "value"),
[
("RELEASE_ID", "release id with spaces"),
("RELEASE_ID", "../release"),
("AI_PLATFORM_PROVIDER_ACCEPTANCE_EXPECTED_RECEIPT_SHA256", "0" * 64),
("AI_PLATFORM_PROVIDER_ACCEPTANCE_EXPECTED_RECEIPT_SHA256", "A" * 64),
("AI_PLATFORM_PROVIDER_ACCEPTANCE_RECEIPT_MAX_TTL_SECONDS", "604801"),
("AI_PLATFORM_PROVIDER_ACCEPTANCE_RECEIPT_MAX_TTL_SECONDS", "not-a-number"),
("AI_PLATFORM_PROVIDER_ACCEPTANCE_RECEIPT_CLOCK_SKEW_SECONDS", "301"),
("AI_PLATFORM_PROVIDER_ACCEPTANCE_RECEIPT_CLOCK_SKEW_SECONDS", "-1"),
("AI_PLATFORM_PROVIDER_ACCEPTANCE_RECEIPT_FILE_HOST", "relative/receipt.json"),
(
"AI_PLATFORM_PROVIDER_ACCEPTANCE_TRUSTED_KEYS_FILE_HOST",
"/etc/yuqei/provider-acceptance/receipt.json",
),
],
)
def test_production_preflight_rejects_unpinned_or_ambiguous_promotion_config(
key: str,
value: str,
) -> None:
values = production_values()
values[key] = value
failed = {check.key for check in preflight.validate_environment(values) if check.status == "fail"}
assert failed & {"release_id", "provider_acceptance_deployment"}
def test_provider_acceptance_promotion_files_are_present_and_hash_pinned(tmp_path: Path) -> None:
receipt_path = tmp_path / "receipt.json"
receipt_path.write_bytes(b'{"receipt":"signed"}\n')
trusted_keys_path = tmp_path / "trusted-keys.json"
trusted_keys_path.write_bytes(b'{"version":1,"keys":[]}\n')
values = production_values()
values.update(
{
"AI_PLATFORM_PROVIDER_ACCEPTANCE_RECEIPT_FILE_HOST": str(receipt_path.resolve()),
"AI_PLATFORM_PROVIDER_ACCEPTANCE_TRUSTED_KEYS_FILE_HOST": str(
trusted_keys_path.resolve()
),
"AI_PLATFORM_PROVIDER_ACCEPTANCE_EXPECTED_RECEIPT_SHA256": hashlib.sha256(
receipt_path.read_bytes()
).hexdigest(),
}
)
checks = {check.key: check for check in preflight.validate_files(values)}
assert checks["provider_acceptance_receipt_file"].status == "pass"
assert checks["provider_acceptance_receipt_hash"].status == "pass"
assert checks["provider_acceptance_trusted_keys_file"].status == "pass"
receipt_path.write_bytes(b'{"receipt":"tampered"}\n')
tampered = {check.key: check for check in preflight.validate_files(values)}
assert tampered["provider_acceptance_receipt_hash"].status == "fail"
def test_production_preflight_requires_owner_only_https_alert_webhook(tmp_path: Path) -> None:
values = production_values()
webhook = tmp_path / "alert-webhook-url"
webhook.write_text("https://alerts.acme.cn/hooks/yuqei\n", encoding="utf-8")
webhook.chmod(0o600)
values["PRODUCTION_ALERT_WEBHOOK_URL_FILE"] = str(webhook.resolve())
checks = {check.key: check for check in preflight.validate_files(values)}
assert checks["alert_webhook_file"].status == "pass"
if "alert_webhook_permissions" in checks:
assert checks["alert_webhook_permissions"].status == "pass"
webhook.write_text("http://alerts.acme.cn/hooks/yuqei\n", encoding="utf-8")
assert {check.key: check for check in preflight.validate_files(values)}["alert_webhook_file"].status == "fail"
def test_production_preflight_rejects_missing_alert_webhook_file(tmp_path: Path) -> None:
values = production_values()
values["PRODUCTION_ALERT_WEBHOOK_URL_FILE"] = str((tmp_path / "missing").resolve())
checks = {check.key: check for check in preflight.validate_files(values)}
assert checks["alert_webhook_file"].status == "fail"
def test_production_compose_mounts_only_promotion_verification_material_read_only() -> None:
override = (
REPO_ROOT / "yuqei-infra/compose/docker-compose.production.yml"
).read_text(encoding="utf-8")
assert "AI_PLATFORM_RELEASE_ID: ${RELEASE_ID:?" in override
assert "AI_PLATFORM_RELEASE_IMAGE_DIGEST: ${AI_PLATFORM_RELEASE_IMAGE_DIGEST:?" in override
assert "AI_PLATFORM_PROVIDER_ACCEPTANCE_EXPECTED_RECEIPT_SHA256: ${" in override
assert ":/run/yuqei/provider-acceptance/receipt.json:ro" in override
assert ":/run/yuqei/provider-acceptance/trusted-keys.json:ro" in override
assert "CONTRACT_API_PUBLIC_POLICY_CANDIDATE_DIR: /run/yuqei/public-policy/candidate" in override
assert "${PUBLIC_POLICY_CANDIDATE_DIR_HOST:?PUBLIC_POLICY_CANDIDATE_DIR_HOST is required}:/run/yuqei/public-policy/candidate:ro" in override
assert "${PUBLIC_POLICY_LEGAL_APPROVAL_FILE_HOST:?PUBLIC_POLICY_LEGAL_APPROVAL_FILE_HOST is required}:/run/yuqei/public-policy/named-policy-legal-approval.json:ro" in override
assert "${PUBLIC_POLICY_TRUSTED_KEYRING_FILE_HOST:?PUBLIC_POLICY_TRUSTED_KEYRING_FILE_HOST is required}:/run/yuqei/public-policy/policy-legal-keyring.trusted.json:ro" in override
assert "CONTRACT_API_PUBLIC_POLICY_EXECUTOR_ENABLED: ${CONTRACT_API_PUBLIC_POLICY_EXECUTOR_ENABLED:-false}" in override
assert 'AI_PLATFORM_PROVIDER_LEGAL_ATTESTATION_SECRET: ""' in override
assert "SIGNING_PRIVATE_KEY" not in override
assert "STAGING_DATABASE_URL" not in override
def test_production_prompt_asset_import_is_dry_run_by_default() -> None:
override = (
REPO_ROOT / "yuqei-infra/compose/docker-compose.production.yml"
).read_text(encoding="utf-8")
service = override.split(" ai-platform-prompt-assets-import:", 1)[1].split(
"\n ai-platform-api:", 1
)[0]
command_line = next(line.strip() for line in service.splitlines() if line.strip().startswith("command:"))
assert command_line == 'command: ["python", "-m", "yuqei_ai_platform_api.v1_prompt_assets_import"]'
def _write_public_policy_evidence(tmp_path: Path) -> dict[str, str]:
candidate = tmp_path / "public-policy"
candidate.mkdir()
documents = []
for policy_id, source_file in (
("user_terms", "user-terms.md"),
("privacy_policy", "privacy-policy.md"),
("service_agreement", "service-agreement.md"),
("ai_use_notice", "ai-use-notice.md"),
):
(candidate / source_file).write_text(f"# {policy_id}\n", encoding="utf-8")
documents.append({"policy_id": policy_id, "source_file": source_file})
(candidate / "manifest.json").write_text(
json.dumps(
{
"schema_version": "yuqei-public-policy-candidate-v1",
"existing_user_reconsent": "required_on_next_login",
"documents": documents,
},
ensure_ascii=False,
),
encoding="utf-8",
)
approval = tmp_path / "policy-approval.json"
approval.write_text('{"approval_id":"policy-approval"}', encoding="utf-8")
keyring = tmp_path / "policy-keyring.json"
keyring.write_text(
json.dumps({"trust_basis": {"policy_activation_authorized": False}}),
encoding="utf-8",
)
return {
"PUBLIC_POLICY_CANDIDATE_DIR_HOST": str(candidate.resolve()),
"PUBLIC_POLICY_LEGAL_APPROVAL_FILE_HOST": str(approval.resolve()),
"PUBLIC_POLICY_TRUSTED_KEYRING_FILE_HOST": str(keyring.resolve()),
}
def test_production_preflight_rejects_invalid_public_policy_deployment() -> None:
values = production_values()
values["CONTRACT_API_PUBLIC_POLICY_RELEASE_DIGEST"] = f"sha256:{'f' * 64}"
checks = {check.key: check for check in preflight.validate_environment(values)}
assert checks["public_policy_deployment"].status == "fail"
@pytest.mark.parametrize(
("key", "value"),
[
("PUBLIC_POLICY_CANDIDATE_DIR_HOST", "relative/public-policy"),
("PUBLIC_POLICY_LEGAL_APPROVAL_FILE_HOST", "/etc/yuqei/public-policy/2026-08-12/policy-legal-keyring.trusted.json"),
("CONTRACT_API_PUBLIC_POLICY_EXECUTOR_ENABLED", "true"),
],
)
def test_production_preflight_rejects_unsafe_public_policy_paths_or_executor(
key: str,
value: str,
) -> None:
values = production_values()
values[key] = value
checks = {check.key: check for check in preflight.validate_environment(values)}
assert checks["public_policy_deployment"].status == "fail"
def test_production_preflight_rejects_public_policy_private_material() -> None:
values = production_values()
values["CONTRACT_API_PUBLIC_POLICY_PRIVATE_KEY_FILE"] = "/etc/yuqei/private.pem"
checks = {check.key: check for check in preflight.validate_environment(values)}
assert checks["public_policy_credential_isolation"].status == "fail"
def test_public_policy_evidence_files_are_present_and_safe(tmp_path: Path) -> None:
values = production_values()
values.update(_write_public_policy_evidence(tmp_path))
checks = {check.key: check for check in preflight.validate_files(values)}
assert checks["public_policy_candidate_dir"].status == "pass"
assert checks["public_policy_manifest"].status == "pass"
assert checks["public_policy_legal_approval_file"].status == "pass"
assert checks["public_policy_trusted_keyring_file"].status == "pass"
def test_public_policy_preflight_fails_on_manifest_or_keyring_drift(tmp_path: Path) -> None:
values = production_values()
values.update(_write_public_policy_evidence(tmp_path))
candidate = Path(values["PUBLIC_POLICY_CANDIDATE_DIR_HOST"])
(candidate / "manifest.json").write_text('{"schema_version":"wrong"}', encoding="utf-8")
keyring = Path(values["PUBLIC_POLICY_TRUSTED_KEYRING_FILE_HOST"])
keyring.write_text(
json.dumps({"trust_basis": {"policy_activation_authorized": True}}),
encoding="utf-8",
)
checks = {check.key: check for check in preflight.validate_files(values)}
assert checks["public_policy_manifest"].status == "fail"
assert checks["public_policy_trusted_keyring_file"].status == "fail"
def test_shared_compose_wires_contract_anti_abuse_controls() -> None:
compose = (REPO_ROOT / "yuqei-infra/compose/docker-compose.yml").read_text(
encoding="utf-8"
)
for variable in (
"CONTRACT_API_ANTI_ABUSE_MODE",
"CONTRACT_API_ANTI_ABUSE_HASH_SECRET",
"CONTRACT_API_ANTI_ABUSE_S3_RECORDS_DAILY_LIMIT",
"CONTRACT_API_ANTI_ABUSE_S4_RECORDS_DAILY_LIMIT",
"CONTRACT_API_ANTI_ABUSE_FILES_DAILY_LIMIT",
"CONTRACT_API_ANTI_ABUSE_BYTES_DAILY_LIMIT",
):
assert f"{variable}: ${{{variable}:-" in compose
def test_shared_compose_and_smoke_deploy_wire_contract_ai_timeout() -> None:
compose = (REPO_ROOT / "yuqei-infra/compose/docker-compose.yml").read_text(
encoding="utf-8"
)
deploy_script = (
REPO_ROOT / "yuqei-infra/scripts/deploy-v2-smoke-docker.ps1"
).read_text(encoding="utf-8")
assert compose.count("CONTRACT_API_AI_PLATFORM_TIMEOUT_SECONDS: ${") == 3
assert "CONTRACT_API_AI_PLATFORM_TIMEOUT_SECONDS=240" in deploy_script
assert "AI_PLATFORM_PROVIDER_REQUEST_TIMEOUT_SECONDS=180" in deploy_script
def test_release_gate_benchmark_defaults_fit_enforced_anti_abuse_window(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(sys, "argv", ["run-release-quality-gate.py"])
args = release_quality_gate.parse_args()
assert args.benchmark_requests_per_scenario + args.benchmark_warmup + 1 < 20
assert 1 <= args.benchmark_concurrency <= args.benchmark_requests_per_scenario
def test_legal_qa_edge_timeout_covers_contract_client_maximum() -> None:
nginx = (
REPO_ROOT / "yuqei-infra/nginx/templates/default.conf.template"
).read_text(encoding="utf-8")
location = nginx.split("location = /contract/api/v1/legal/qa", 1)[1].split("}", 1)[0]
assert "proxy_read_timeout 660s;" in location
assert "proxy_send_timeout 660s;" in location
assert "proxy_pass http://contract_api_upstream/api/v1/legal/qa;" in location
def test_smoke_review_requests_include_server_authorized_identity_context() -> None:
deploy_script = (
REPO_ROOT / "yuqei-infra/scripts/deploy-v2-smoke-docker.ps1"
).read_text(encoding="utf-8")
assert deploy_script.count("-H 'X-Tenant-Id: default'") >= 3
assert deploy_script.count("-H 'X-User-Id: user-current-admin'") >= 3
def test_disabled_identity_email_does_not_require_smtp_secret_file() -> None:
values = production_values()
values.pop("CONTRACT_API_IDENTITY_SMTP_PASSWORD_FILE_HOST", None)
environment_checks = {check.key: check for check in preflight.validate_environment(values)}
file_checks = {check.key: check for check in preflight.validate_files(values)}
assert environment_checks["identity_email_delivery"].status == "pass"
assert file_checks["smtp_password_file"].status == "pass"
def test_smtp_identity_email_requires_and_validates_opt_in_secret_file(tmp_path: Path) -> None:
password_file = tmp_path / "contract-smtp-password"
password_file.write_text("test-smtp-password\n", encoding="utf-8")
password_file.chmod(0o600)
values = production_values()
values.update(
{
"CONTRACT_API_IDENTITY_EMAIL_DELIVERY_MODE": "smtp",
"CONTRACT_API_IDENTITY_SELF_SERVICE_ENABLED": "true",
"CONTRACT_API_IDENTITY_MANUAL_INVITATION_ENABLED": "false",
"CONTRACT_API_IDENTITY_SMTP_HOST": "smtp.mail.acme.cn",
"CONTRACT_API_IDENTITY_SMTP_USERNAME": "mailer@acme.cn",
"CONTRACT_API_IDENTITY_SMTP_PASSWORD": "",
"CONTRACT_API_IDENTITY_SMTP_PASSWORD_FILE": "/run/secrets/contract_smtp_password",
"CONTRACT_API_IDENTITY_SMTP_PASSWORD_FILE_HOST": str(password_file.resolve()),
"CONTRACT_API_IDENTITY_SMTP_FROM_EMAIL": "mailer@acme.cn",
"CONTRACT_API_IDENTITY_SMTP_USE_STARTTLS": "true",
"CONTRACT_API_IDENTITY_SMTP_USE_SSL": "false",
"CONTRACT_API_IDENTITY_PUBLIC_WEB_BASE_URL": "https://contracts.acme.cn",
}
)
environment_checks = {check.key: check for check in preflight.validate_environment(values)}
file_checks = {check.key: check for check in preflight.validate_files(values)}
assert environment_checks["identity_email_delivery"].status == "pass"
assert file_checks["smtp_password_file"].status == "pass"
if "smtp_password_permissions" in file_checks:
assert file_checks["smtp_password_permissions"].status == "pass"
unencrypted = dict(values)
unencrypted["CONTRACT_API_IDENTITY_SMTP_USE_STARTTLS"] = "false"
unencrypted["CONTRACT_API_IDENTITY_SMTP_USE_SSL"] = "false"
unencrypted_checks = {
check.key: check for check in preflight.validate_environment(unencrypted)
}
assert unencrypted_checks["identity_email_delivery"].status == "fail"
password_file.unlink()
missing_file_checks = {check.key: check for check in preflight.validate_files(values)}
assert missing_file_checks["smtp_password_file"].status == "fail"
@pytest.mark.parametrize(
("key", "value"),
[
("CONTRACT_API_IDENTITY_SMTP_PORT", "0"),
("CONTRACT_API_IDENTITY_SMTP_PORT", "not-a-port"),
("CONTRACT_API_IDENTITY_SMTP_TIMEOUT_SECONDS", "0"),
("CONTRACT_API_IDENTITY_SMTP_TIMEOUT_SECONDS", "121"),
("CONTRACT_API_IDENTITY_SMTP_FROM_EMAIL", "not-an-email"),
("CONTRACT_API_IDENTITY_SMTP_HOST", " smtp.mail.acme.cn"),
("CONTRACT_API_IDENTITY_SMTP_FROM_NAME", "AI Contract\r\nBcc: hidden@example.com"),
("CONTRACT_API_IDENTITY_SMTP_USE_STARTTLS", "sometimes"),
],
)
def test_smtp_preflight_rejects_runtime_invalid_values(
tmp_path: Path,
key: str,
value: str,
) -> None:
password_file = tmp_path / "contract-smtp-password"
password_file.write_text("test-smtp-password\n", encoding="utf-8")
values = production_values()
values.update(
{
"CONTRACT_API_IDENTITY_EMAIL_DELIVERY_MODE": "smtp",
"CONTRACT_API_IDENTITY_SELF_SERVICE_ENABLED": "true",
"CONTRACT_API_IDENTITY_MANUAL_INVITATION_ENABLED": "false",
"CONTRACT_API_IDENTITY_SMTP_HOST": "smtp.mail.acme.cn",
"CONTRACT_API_IDENTITY_SMTP_USERNAME": "mailer@acme.cn",
"CONTRACT_API_IDENTITY_SMTP_PASSWORD": "",
"CONTRACT_API_IDENTITY_SMTP_PASSWORD_FILE": "/run/secrets/contract_smtp_password",
"CONTRACT_API_IDENTITY_SMTP_PASSWORD_FILE_HOST": str(password_file.resolve()),
"CONTRACT_API_IDENTITY_SMTP_FROM_EMAIL": "mailer@acme.cn",
"CONTRACT_API_IDENTITY_SMTP_USE_STARTTLS": "true",
"CONTRACT_API_IDENTITY_SMTP_USE_SSL": "false",
"CONTRACT_API_IDENTITY_SMTP_TIMEOUT_SECONDS": "10",
"CONTRACT_API_IDENTITY_PUBLIC_WEB_BASE_URL": "https://contracts.acme.cn",
key: value,
}
)
checks = {check.key: check for check in preflight.validate_environment(values)}
assert checks["identity_email_delivery"].status == "fail"
def test_smtp_production_override_mounts_only_the_password_file_secret() -> None:
override = (
REPO_ROOT / "yuqei-infra/compose/docker-compose.production.smtp.yml"
).read_text(encoding="utf-8")
assert "CONTRACT_API_IDENTITY_SMTP_PASSWORD: \"\"" in override
assert "CONTRACT_API_IDENTITY_SMTP_PASSWORD_FILE: /run/secrets/contract_smtp_password" in override
assert "target: contract_smtp_password" in override
assert "file: ${CONTRACT_API_IDENTITY_SMTP_PASSWORD_FILE_HOST:?" in override
def test_production_preflight_rejects_smoke_database_public_bind_and_fallback() -> None:
values = production_values()
values["CONTRACT_POSTGRES_DB"] = "yuqei_contract_smoke"
values["CONTRACT_API_DATABASE_URL"] = (
"postgresql+psycopg://yuqei_prod:encoded-password@postgres:5432/yuqei_contract_smoke"
)
values["POSTGRES_BIND_ADDRESS"] = "0.0.0.0"
values["AI_PLATFORM_PROVIDER_FALLBACK_ENABLED"] = "true"
failed = {check.key for check in preflight.validate_environment(values) if check.status == "fail"}
assert {"production_modes", "internal_port_binding", "database_boundaries"} <= failed
def test_backup_manifest_and_contract_archive_are_verified(tmp_path: Path) -> None:
backup_dir = tmp_path / "backup-20260716T120000Z"
backup_dir.mkdir()
archive_path = backup_dir / "contract-files.tar.gz"
with tarfile.open(archive_path, mode="w:gz") as archive:
content = b"contract"
info = tarfile.TarInfo("contract-1/document.txt")
info.size = len(content)
archive.addfile(info, io.BytesIO(content))
dump_path = backup_dir / "postgres-contract.dump"
dump_path.write_bytes(b"postgres-dump")
artifacts = []
for path in (archive_path, dump_path):
artifacts.append(
{
"path": path.name,
"size_bytes": path.stat().st_size,
"sha256": hashlib.sha256(path.read_bytes()).hexdigest(),
}
)
(backup_dir / "manifest.json").write_text(
json.dumps(
{
"schema_version": "yuqei-production-backup.v1",
"backup_id": backup_dir.name,
"created_at": "2026-07-16T12:00:00+00:00",
"artifacts": artifacts,
}
),
encoding="utf-8",
)
manifest, verified = backup_verify.validate_backup(backup_dir)
assert manifest["backup_id"] == backup_dir.name
assert len(verified) == 2
def test_provider_acceptance_separates_technical_success_from_legal_approval() -> None:
result = provider_acceptance.evaluate_case(
row={
"sample_id": "KBQA-1",
"expected_citation_required": "true",
"expected_source_ids": "LAW-CIVIL-001",
"production_ready": "false",
"status": "LEGAL_REVIEW",
"legal_reviewer": "待法务复核",
},
suite="legal_qa",
response={
"answer": "应结合合同和证据进一步判断。",
"citations": [{"document_id": "LAW-CIVIL-001"}],
},
audit={
"id": "run-1",
"status": "succeeded",
"provider_status": "succeeded",
"provider": "deepseek",
"model": "deepseek-chat",
"quality_labels": [],
},
latency_ms=100,
expected_boundary="不得直接判断个案效力。",
expected_severity=None,
)
assert result.technical_status == "passed"
assert result.legal_status == "needs_legal_review"
assert result.matched_source_ids == ["LAW-CIVIL-001"]
def test_provider_acceptance_rejects_fallback_audit() -> None:
result = provider_acceptance.evaluate_case(
row={"sample_id": "KBQA-2", "expected_citation_required": "false"},
suite="legal_qa",
response={"answer": "fallback answer", "citations": []},
audit={
"id": "run-2",
"status": "fallback",
"provider_status": "failed",
"provider_error": "provider unavailable",
"quality_labels": [{"code": "fallback_used"}],
},
latency_ms=50,
expected_boundary="",
expected_severity=None,
)
assert result.technical_status == "failed"
assert "provider_not_succeeded" in result.problems
assert "fallback_or_provider_failure_label" in result.problems
def test_provider_acceptance_requires_explicit_stable_source_ids() -> None:
observed = provider_acceptance._response_source_ids(
[
{"document_id": "doc-LAW-CIVIL-001-random"},
{"document_id": "doc-random", "reference": "LAW-CONTRACT-001 article 1"},
{"document_id": "doc-random-2", "source_ids": ["LAW-CIVIL-001", "not-stable"]},
]
)
assert observed == {"LAW-CIVIL-001", "LAW-CONTRACT-001"}
def test_provider_acceptance_loads_phase13_knowledge_cards_idempotently() -> None:
documents: list[dict[str, object]] = []
class Client:
def get(self, path: str):
assert path.startswith("/api/v1/knowledge-documents/search?")
return documents, 1
def post(self, path: str, payload: dict[str, object]):
assert path == "/api/v1/knowledge-documents"
documents.append({"id": f"doc-{len(documents)}", **payload})
return documents[-1], 1
client = Client()
assert provider_acceptance.load_phase13_knowledge_assets(client) == 10
assert provider_acceptance.load_phase13_knowledge_assets(client) == 0
assert len(documents) == 10
assert all(str(item["reference"]).startswith("LAW-") for item in documents)
assert all("不代表法务批准" in str(item["content"]) for item in documents)
def test_provider_acceptance_requires_complete_named_legal_approval(tmp_path: Path) -> None:
qa_rows = provider_acceptance.load_rows(provider_acceptance.QA_INVENTORY)
review_rows = provider_acceptance.load_rows(provider_acceptance.REVIEW_INVENTORY)
card_rows = provider_acceptance.load_rows(provider_acceptance.KNOWLEDGE_CARD_INVENTORY)
approval_file = tmp_path / "legal-approval.json"
approval_file.write_text(
json.dumps(
{
"status": "approved",
"reviewer": "Named legal reviewer",
"approved_at": "2026-08-10T08:00:00+08:00",
"evidence_ref": "https://legal.example.test/approvals/provider-phase13",
"evidence_sha256": "a" * 64,
"approved_qa_sample_ids": [row["sample_id"] for row in qa_rows],
"approved_review_sample_ids": [row["sample_id"] for row in review_rows],
"approved_knowledge_card_ids": [row["knowledge_card_id"] for row in card_rows],
},
ensure_ascii=False,
),
encoding="utf-8",
)
approval = provider_acceptance.load_legal_approval(
approval_file,
qa_sample_ids=[row["sample_id"] for row in qa_rows],
review_sample_ids=[row["sample_id"] for row in review_rows],
)
assert approval["legal_approval_status"] == "approved"
assert approval["legal_reviewer"] == "Named legal reviewer"
assert len(approval["approved_knowledge_card_ids"]) == 10
tampered = json.loads(approval_file.read_text(encoding="utf-8"))
tampered["approved_review_sample_ids"] = tampered["approved_review_sample_ids"][:-1]
approval_file.write_text(json.dumps(tampered), encoding="utf-8")
with pytest.raises(ValueError, match="all 8 contract review samples"):
provider_acceptance.load_legal_approval(
approval_file,
qa_sample_ids=[row["sample_id"] for row in qa_rows],
review_sample_ids=[row["sample_id"] for row in review_rows],
)
def test_provider_acceptance_registers_only_complete_10_plus_8_manifest() -> None:
qa_rows = provider_acceptance.load_rows(provider_acceptance.QA_INVENTORY)
review_rows = provider_acceptance.load_rows(provider_acceptance.REVIEW_INVENTORY)
card_rows = provider_acceptance.load_rows(provider_acceptance.KNOWLEDGE_CARD_INVENTORY)
cases = []
for suite, rows in (("legal_qa", qa_rows), ("contract_review", review_rows)):
for row in rows:
cases.append(
provider_acceptance.CaseResult(
sample_id=row["sample_id"],
suite=suite,
technical_status="passed",
legal_status="needs_legal_review",
latency_ms=1,
provider="openai-compatible",
model="runtime-model",
audit_run_id=f"run-{row['sample_id']}",
answer_non_empty=True,
citation_count=2,
expected_source_ids=[],
matched_source_ids=[],
expected_boundary="",
expected_severity=None,
observed_severity=None,
production_ready=False,
asset_status="LEGAL_REVIEW",
legal_reviewer="",
problems=[],
)
)
class Client:
payload: dict[str, object] | None = None
tenant_id = "default"
def post(
self,
path: str,
payload: dict[str, object],
*,
extra_headers: dict[str, str] | None = None,
):
assert path == "/api/v1/quality/provider-acceptance-runs"
assert extra_headers
assert extra_headers["X-AI-Platform-Legal-Attestation"] == payload["legal_approval_attestation"]
self.payload = payload
return {"id": "provider-acceptance-complete"}, 1
client = Client()
run_id = provider_acceptance.register_acceptance_manifest(
client,
provider_config={
"id": "provider-config-1",
"provider": "openai-compatible",
"model": "runtime-model",
},
qa_rows=qa_rows,
review_rows=review_rows,
cases=cases,
approval={
"legal_approval_status": "approved",
"legal_reviewer": "Named legal reviewer",
"legal_approved_at": "2026-08-10T08:00:00+08:00",
"legal_approval_evidence_ref": "https://legal.example.test/approval",
"legal_approval_evidence_sha256": "b" * 64,
"approved_knowledge_card_ids": [row["knowledge_card_id"] for row in card_rows],
},
legal_attestation_secret="independent-legal-attestation-secret-for-tests", # pragma: allowlist secret
)
assert run_id == "provider-acceptance-complete"
assert client.payload is not None
assert len(client.payload["qa_sample_ids"]) == 10
assert len(client.payload["review_sample_ids"]) == 8
assert len(client.payload["knowledge_card_ids"]) == 10
assert len(client.payload["audit_bindings"]) == 18
with pytest.raises(ValueError, match="exactly 10 QA and 8 review"):
provider_acceptance.register_acceptance_manifest(
client,
provider_config={"id": "p", "provider": "p", "model": "m"},
qa_rows=qa_rows[:-1],
review_rows=review_rows,
cases=cases[:-1],
approval={},
legal_attestation_secret="independent-legal-attestation-secret-for-tests", # pragma: allowlist secret
)
def _valid_provider_receipt_payload(
*,
run_id: str = "provider-acceptance-complete",
key_id: str = "staging-receipt-key-1",
target_release_id: str = "v2.0.0-rc.1",
target_image_digest: str = "sha256:" + "2" * 64,
) -> dict[str, object]:
qa_rows = provider_acceptance.load_rows(provider_acceptance.QA_INVENTORY)
review_rows = provider_acceptance.load_rows(provider_acceptance.REVIEW_INVENTORY)
card_rows = provider_acceptance.load_rows(provider_acceptance.KNOWLEDGE_CARD_INVENTORY)
audit_bindings = [
{
"suite": suite,
"sample_id": row["sample_id"],
"audit_run_id": f"audit-{index}",
"audit_snapshot_sha256": f"{index:064x}",
}
for index, (suite, row) in enumerate(
[*(('legal_qa', row) for row in qa_rows), *(('contract_review', row) for row in review_rows)],
start=1,
)
]
return {
"receipt_version": "provider-acceptance-receipt-v2",
"algorithm": "Ed25519",
"key_id": key_id,
"issuer": "shared_staging",
"audience": "yuqei-ai-platform-production",
"source_environment": "shared_staging",
"target_environment": "production",
"target_release_id": target_release_id,
"target_image_digest": target_image_digest,
"tenant_id": "default",
"acceptance_run": {
"source_environment": "shared_staging",
"acceptance_policy_version": provider_acceptance.ACCEPTANCE_POLICY_VERSION,
"provider_config_id": "provider-config-1",
"provider": "openai-compatible",
"model": "runtime-model",
"qa_sample_ids": [row["sample_id"] for row in qa_rows],
"review_sample_ids": [row["sample_id"] for row in review_rows],
"knowledge_card_ids": [row["knowledge_card_id"] for row in card_rows],
"audit_bindings": audit_bindings,
"suite_manifest_sha256": provider_acceptance._manifest_hash(
[provider_acceptance.QA_INVENTORY, provider_acceptance.REVIEW_INVENTORY]
),
"knowledge_manifest_sha256": provider_acceptance._manifest_hash(
[provider_acceptance.KNOWLEDGE_CARD_INVENTORY]
),
"legal_approval_status": "approved",
"legal_reviewer": "Named legal reviewer",
"legal_approved_at": "2026-08-10T08:00:00+08:00",
"legal_approval_evidence_ref": "https://legal.example.test/approval",
"legal_approval_evidence_sha256": "a" * 64,
"legal_approval_attestation": "b" * 64,
"id": run_id,
"tenant_id": "default",
"acceptance_manifest_sha256": "c" * 64,
"created_at": "2026-08-10T00:01:00+00:00",
},
"provider_runtime": {
"provider": "openai-compatible",
"model": "runtime-model",
"base_url": "https://provider.example.test/v1",
"wire_api": "chat_completions",
"temperature": 0.1,
"max_tokens": 4096,
"prompt_templates_sha256": "d" * 64,
"fingerprint_sha256": "e" * 64,
},
"quality_policy_sha256": "f" * 64,
"issued_at": "2026-08-10T00:02:00+00:00",
"not_before": "2026-08-10T00:01:30+00:00",
"expires_at": "2026-08-11T00:02:00+00:00",
}
def test_provider_acceptance_requires_all_receipt_options_and_legal_approval(tmp_path: Path) -> None:
values = {
"receipt_private_key_file": tmp_path / "receipt-key.pem",
"receipt_key_id": "staging-receipt-key-1",
"target_release_id": "v2.0.0-rc.1",
"target_image_digest": "sha256:" + "2" * 64,
"receipt_output": tmp_path / "receipt.json",
"legal_approval_file": tmp_path / "legal-approval.json",
}
assert provider_acceptance.validate_receipt_options(SimpleNamespace(**values)) is True
assert provider_acceptance.validate_receipt_options(
SimpleNamespace(**{key: None for key in values})
) is False
for missing in (
"receipt_private_key_file",
"receipt_key_id",
"target_release_id",
"target_image_digest",
"receipt_output",
):
with pytest.raises(ValueError, match="all receipt options"):
provider_acceptance.validate_receipt_options(
SimpleNamespace(**{**values, missing: None})
)
with pytest.raises(ValueError, match="named legal approval"):
provider_acceptance.validate_receipt_options(
SimpleNamespace(**{**values, "legal_approval_file": None})
)
with pytest.raises(ValueError, match="separate JSON"):
provider_acceptance.validate_receipt_output_path(
values["receipt_private_key_file"],
[values["receipt_private_key_file"]],
)
with pytest.raises(ValueError, match="separate JSON"):
provider_acceptance.validate_receipt_output_path(tmp_path / "receipt.txt", [])
def test_provider_acceptance_fetches_signs_and_writes_separate_receipt(tmp_path: Path) -> None:
payload = _valid_provider_receipt_payload()
requested_paths: list[str] = []
class Client:
tenant_id = "default"
def get(self, path: str):
requested_paths.append(path)
return payload, 1
private_key = Ed25519PrivateKey.generate()
key_file = tmp_path / "receipt-key.pem"
key_file.write_bytes(
private_key.private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption(),
)
)
receipt_path = tmp_path / "provider-acceptance-receipt.json"
metadata = provider_acceptance.create_signed_acceptance_receipt(
Client(),
acceptance_run_id="provider-acceptance-complete",
key_id="staging-receipt-key-1",
target_release_id="v2.0.0-rc.1",
target_image_digest="sha256:" + "2" * 64,
private_key_file=key_file,
output_path=receipt_path,
)
assert requested_paths == [
"/api/v1/quality/provider-acceptance-runs/provider-acceptance-complete/receipt-payload"
"?key_id=staging-receipt-key-1&target_release_id=v2.0.0-rc.1"
f"&target_image_digest=sha256%3A{'2' * 64}"
]
receipt = SignedProviderAcceptanceReceipt.model_validate_json(receipt_path.read_bytes())
assert receipt.payload == ProviderAcceptanceReceiptPayload.model_validate(payload)
signature = base64.urlsafe_b64decode(receipt.signature + "==")
private_key.public_key().verify(
signature,
RECEIPT_DOMAIN + canonical_receipt_payload(receipt.payload),
)
assert metadata == {
"receipt_id": receipt.receipt_id,
"sha256": hashlib.sha256(receipt_path.read_bytes()).hexdigest(),
}
provider_acceptance.write_evidence(
tmp_path,
provider_acceptance.build_evidence_summary(
status="passed",
provider="openai-compatible",
model="runtime-model",
cases=[],
),
)
assert receipt_path.exists()
assert receipt_path.name not in {
"ai-provider-acceptance-summary.json",
"ai-provider-acceptance-summary.md",
}
def test_provider_acceptance_rejects_unsafe_receipt_keys_without_leaking_material(tmp_path: Path) -> None:
payload = _valid_provider_receipt_payload()
class Client:
tenant_id = "default"
def get(self, _path: str):
return payload, 1
rsa_key = rsa.generate_private_key(public_exponent=65537, key_size=2048).private_bytes(
serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8,
serialization.NoEncryption(),
)
key_inputs = {
"invalid.pem": b"private-secret-marker-not-a-key",
"rsa.pem": rsa_key,
"oversized.pem": b"private-secret-marker" * 4096,
}
key_paths: list[Path] = [tmp_path / "missing-private-secret-marker.pem"]
for name, content in key_inputs.items():
path = tmp_path / name
path.write_bytes(content)
key_paths.append(path)
for index, key_path in enumerate(key_paths):
with pytest.raises(ValueError, match="unavailable or invalid") as raised:
provider_acceptance.create_signed_acceptance_receipt(
Client(),
acceptance_run_id="provider-acceptance-complete",
key_id="staging-receipt-key-1",
target_release_id="v2.0.0-rc.1",
target_image_digest="sha256:" + "2" * 64,
private_key_file=key_path,
output_path=tmp_path / f"receipt-{index}.json",
)
assert "private-secret-marker" not in str(raised.value)
assert not (tmp_path / f"receipt-{index}.json").exists()
def test_provider_acceptance_never_fetches_or_writes_receipt_without_acceptance_id(tmp_path: Path) -> None:
class Client:
tenant_id = "default"
def get(self, _path: str):
raise AssertionError("receipt payload must not be fetched")
receipt_path = tmp_path / "receipt.json"
with pytest.raises(ValueError, match="acceptance_run_id"):
provider_acceptance.create_signed_acceptance_receipt(
Client(),
acceptance_run_id="",
key_id="staging-receipt-key-1",
target_release_id="v2.0.0-rc.1",
target_image_digest="sha256:" + "2" * 64,
private_key_file=tmp_path / "missing.pem",
output_path=receipt_path,
)
assert not receipt_path.exists()
def test_provider_acceptance_excludes_deterministic_product_suites() -> None:
assert not hasattr(provider_acceptance, "GENERATION_INVENTORY")
assert not hasattr(provider_acceptance, "run_generation_case")
def test_contract_product_golden_runs_real_deterministic_product_paths() -> None:
results = contract_product_golden.run_product_golden()
summary = contract_product_golden.build_summary(results)
assert len(results) == 31
assert sum(item.suite == "contract_generation" for item in results) == 23
assert sum(item.suite == "clause_recommendation" for item in results) == 8
assert all(item.technical_status == "passed" for item in results)
assert all(item.legal_status == "needs_legal_review" for item in results)
assert summary["status"] == "needs_legal_review"
assert summary["counts"]["technical_passed"] == 31
assert summary["counts"]["legal_approved"] == 0
assert summary["counts"]["preserved_required_placeholders"] == 0
assert summary["problems"] == []
def test_contract_product_golden_rejects_inconsistent_expected_boundary() -> None:
row = contract_product_golden.load_rows()[0]
tampered = dict(
row,
expected_source_citations=row["expected_source_citations"] + ";LAW-NOT-IN-BOUNDARY-001",
)
result = contract_product_golden.evaluate_product_case(tampered)
assert result.technical_status == "failed"
assert "expected_boundary_missing_identifier" in result.problems
def test_contract_product_golden_does_not_approve_names_without_evidence() -> None:
row = contract_product_golden.load_rows()[0]
incomplete_approval = dict(
row,
status="APPROVED",
production_ready="true",
legal_reviewer="Named legal reviewer",
business_reviewer="Named business reviewer",
)
result = contract_product_golden.evaluate_product_case(incomplete_approval)
assert result.technical_status == "passed"
assert result.legal_status == "needs_legal_review"
def test_contract_product_golden_evidence_does_not_claim_legal_approval(
tmp_path: Path,
) -> None:
summary = contract_product_golden.build_summary(contract_product_golden.run_product_golden())
contract_product_golden.write_evidence(tmp_path, summary)
assert summary["status"] == "needs_legal_review"
assert "acceptance_run_id" not in summary
assert set(path.name for path in tmp_path.iterdir()) == {
"contract-product-golden-summary.json",
"contract-product-golden-summary.md",
}
def test_provider_acceptance_evidence_excludes_responses_and_identifiers(tmp_path: Path) -> None:
result = provider_acceptance.evaluate_case(
row={
"sample_id": "sensitive-sample-id",
"expected_citation_required": "true",
"expected_source_ids": "LAW-SECRET-001",
"production_ready": "false",
},
suite="legal_qa",
response={
"answer": "sensitive-provider-answer",
"citations": [{"document_id": "LAW-SECRET-001"}],
},
audit={
"id": "sensitive-audit-run-id",
"status": "succeeded",
"provider_status": "succeeded",
"provider": "deepseek",
"model": "deepseek-chat",
"quality_labels": [],
},
latency_ms=100,
expected_boundary="sensitive-legal-boundary",
expected_severity=None,
)
summary = provider_acceptance.build_evidence_summary(
status="needs_legal_review",
provider="deepseek",
model="deepseek-chat",
cases=[result],
)
provider_acceptance.write_evidence(tmp_path, summary)
assert set(summary) == {"provider", "model", "status", "counts", "latency_ms", "problems"}
serialized = json.dumps(summary, ensure_ascii=False)
for sensitive_value in (
"sensitive-sample-id",
"sensitive-provider-answer",
"LAW-SECRET-001",
"sensitive-audit-run-id",
"sensitive-legal-boundary",
):
assert sensitive_value not in serialized
assert not (tmp_path / "ai-provider-acceptance-responses.json").exists()
assert set(path.name for path in tmp_path.iterdir()) == {
"ai-provider-acceptance-summary.json",
"ai-provider-acceptance-summary.md",
}
def test_provider_acceptance_validates_safe_runtime_parameters() -> None:
valid_key = "service-key-that-is-long-enough-for-testing" # pragma: allowlist secret
with pytest.raises(ValueError, match="query/fragment"):
provider_acceptance.ApiClient(
"https://api.example.test/ai?key=unsafe",
service_key=valid_key,
tenant_id="default",
timeout_seconds=30,
)
with pytest.raises(ValueError, match="service key"):
provider_acceptance.ApiClient(
"https://api.example.test/ai",
service_key=f"{valid_key}\r\nInjected: true",
tenant_id="default",
timeout_seconds=30,
)
with pytest.raises(ValueError, match="Tenant ID"):
provider_acceptance.ApiClient(
"https://api.example.test/ai",
service_key=valid_key,
tenant_id="default\r\nInjected: true",
timeout_seconds=30,
)
with pytest.raises(ValueError, match="Timeout"):
provider_acceptance.ApiClient(
"https://api.example.test/ai",
service_key=valid_key,
tenant_id="default",
timeout_seconds=0,
)
def test_provider_acceptance_allows_explicit_isolated_memory_schema_warning() -> None:
class Client:
def get(self, path: str):
if path == "/api/v1/runtime/schema-check":
return {
"status": "warning",
"checks": [
{
"name": "repository_backend",
"status": "warning",
"details": {"repository_backend": "memory"},
},
{"name": "anti_abuse_runtime", "status": "warning", "details": {}},
],
}, 1
if path == "/api/v1/model-configs":
return [
{
"provider": "isolated-provider",
"model": "isolated-model",
"enabled": True,
"is_default": True,
"base_url": "https://provider.example.test",
"api_key_set": True,
}
], 1
raise AssertionError(path)
schema, provider_config = provider_acceptance.validate_runtime(Client())
assert schema["status"] == "warning"
assert provider_config["provider"] == "isolated-provider"
def test_provider_acceptance_allows_local_codex_development_evidence_only() -> None:
class Client:
def get(self, path: str):
if path == "/api/v1/runtime/schema-check":
return {
"status": "warning",
"checks": [
{
"name": "repository_backend",
"status": "warning",
"details": {"repository_backend": "memory"},
},
{"name": "anti_abuse_runtime", "status": "warning", "details": {}},
{
"name": "provider_runtime",
"status": "ok",
"details": {
"environment": "local",
"provider_call_mode": "codex_cli",
},
},
],
}, 1
if path == "/api/v1/model-configs":
return [
{
"id": "legacy-development-provider",
"provider": "legacy-development-config",
"model": "gpt-pro-development",
"enabled": True,
"is_default": True,
}
], 1
raise AssertionError(path)
schema, provider_config = provider_acceptance.validate_runtime(
Client(),
development_codex_cli=True,
)
assert schema["status"] == "warning"
assert provider_config["provider"] == "codex-cli-development"
assert provider_config["model"] == "gpt-5.6-sol"
assert provider_config["development_runtime_override"] is True
def test_provider_acceptance_never_promotes_development_codex_evidence() -> None:
with pytest.raises(RuntimeError, match="cannot be treated as shared-staging"):
provider_acceptance.validate_runtime(
object(),
require_shared_staging=True,
development_codex_cli=True,
)
summary = provider_acceptance.mark_development_evidence(
provider_acceptance.build_evidence_summary(
status="needs_legal_review",
provider=None,
model=None,
cases=[],
)
)
assert summary["provider"] == "codex-cli-development"
assert summary["model"] == "gpt-5.6-sol"
assert summary["evidence_scope"] == "local_development_codex_cli"
assert summary["production_eligible"] is False
assert summary["provider_acceptance_registration_allowed"] is False
assert summary["controlled_pilot_gate_effect"] == "none"
def test_provider_acceptance_reports_operational_quality_and_latency_separately() -> None:
result = provider_acceptance.evaluate_case(
row={
"sample_id": "QA-DEVELOPMENT-SLOW-001",
"expected_citation_required": "false",
"production_ready": "false",
"status": "LEGAL_REVIEW",
"legal_reviewer": "待法务复核",
},
suite="legal_qa",
response={"answer": "有内容的技术回答", "citations": []},
audit={
"id": "run-development-slow",
"status": "succeeded",
"provider_status": "succeeded",
"provider": "codex-cli-development",
"model": "gpt-5.6-sol",
"quality_status": "failed",
"quality_score": 60,
"quality_labels": [{"code": "latency_critical"}],
},
latency_ms=128_000,
expected_boundary="",
expected_severity=None,
)
summary = provider_acceptance.build_evidence_summary(
status="needs_operational_review",
provider=result.provider,
model=result.model,
cases=[result],
)
assert result.technical_status == "passed"
assert result.quality_status == "failed"
assert result.quality_score == 60
assert summary["counts"]["technical_passed"] == 1
assert summary["counts"]["quality_failed"] == 1
assert summary["latency_ms"] == {
"min": 128_000,
"median": 128_000,
"p95": 128_000,
"max": 128_000,
}
def test_provider_acceptance_encodes_chinese_request_as_utf8(monkeypatch) -> None:
captured: dict[str, object] = {}
class Response:
def __enter__(self):
return self
def __exit__(self, *_args):
return False
def read(self, _limit: int) -> bytes:
return b'{"status":"ok"}'
def fake_urlopen(request, *, timeout):
captured["body"] = request.data
captured["timeout"] = timeout
return Response()
monkeypatch.setattr(provider_acceptance, "urlopen", fake_urlopen)
client = provider_acceptance.ApiClient(
"https://api.example.test/ai",
service_key="service-key-that-is-long-enough-for-testing", # pragma: allowlist secret
tenant_id="default",
timeout_seconds=30,
)
payload, _ = client.post("/api/v1/legal/qa", {"question": "电子邮件能否作为合同证据?"})
assert payload == {"status": "ok"}
assert json.loads(captured["body"].decode("utf-8"))["question"] == "电子邮件能否作为合同证据?"
assert captured["timeout"] == 30
def test_provider_acceptance_runs_all_phase13_cases_against_isolated_http_service() -> None:
qa_rows = provider_acceptance.load_rows(provider_acceptance.QA_INVENTORY)
review_rows = provider_acceptance.load_rows(provider_acceptance.REVIEW_INVENTORY)
qa_by_question = {row["question"]: row for row in qa_rows}
review_by_id = {row["sample_id"]: row for row in review_rows}
audits: dict[str, dict[str, object]] = {}
class Handler(BaseHTTPRequestHandler):
def send_json(self, payload: object) -> None:
body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "application/json; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self) -> None: # noqa: N802
path = self.path.split("?", 1)[0]
if path == "/api/v1/runtime/schema-check":
self.send_json(
{
"status": "ok",
"checks": [{"name": "provider_runtime", "status": "ok"}],
}
)
return
if path == "/api/v1/model-configs":
self.send_json(
[
{
"id": "provider-isolated",
"provider": "isolated-provider",
"model": "isolated-model",
"enabled": True,
"is_default": True,
"base_url": "https://provider.invalid/v1",
"api_key_set": True,
}
]
)
return
if path == "/api/v1/audit/ai-runs":
self.send_json(list(reversed(list(audits.values()))))
return
run_id = path.removeprefix("/api/v1/audit/ai-runs/")
if run_id in audits:
self.send_json(audits[run_id])
return
self.send_error(404)
def do_POST(self) -> None: # noqa: N802
content_length = int(self.headers.get("Content-Length", "0"))
payload = json.loads(self.rfile.read(content_length).decode("utf-8"))
run_id = f"isolated-run-{len(audits) + 1}"
if self.path == "/api/v1/legal/qa":
row = qa_by_question[payload["question"]]
citations = [
{"document_id": f"doc-{index}", "source_ids": [source_id]}
for index, source_id in enumerate(provider_acceptance.split_ids(row["expected_source_ids"]))
]
operation = "legal_qa"
response = {"answer": "基于检索依据给出边界明确的答复。", "citations": citations}
elif self.path == "/api/v1/legal/contract-review":
row = review_by_id[payload["contract_title"]]
citations = [
{"document_id": f"doc-{index}", "source_ids": [source_id]}
for index, source_id in enumerate(provider_acceptance.split_ids(row["expected_source_citations"]))
]
cited_source_ids = provider_acceptance.split_ids(row["expected_source_citations"])
operation = "contract_review"
response = {
"summary": "已按约定审查重点完成审查。",
"citations": citations,
"risk_items": [
{
"severity": row["expected_severity"],
"citation_source_ids": cited_source_ids,
}
],
"audit_run_id": run_id,
}
else:
self.send_error(404)
return
audits[run_id] = {
"id": run_id,
"operation": operation,
"status": "succeeded",
"provider_status": "succeeded",
"provider": "isolated-provider",
"model": "isolated-model",
"quality_labels": [],
"created_at": datetime.now(timezone.utc).isoformat(),
}
self.send_json(response)
def log_message(self, _format: str, *_args: object) -> None:
return
server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
thread = Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
client = provider_acceptance.ApiClient(
f"http://127.0.0.1:{server.server_port}",
service_key="isolated-non-secret-service-key-for-tests", # pragma: allowlist secret
tenant_id="default",
timeout_seconds=10,
)
schema, provider_config = provider_acceptance.validate_runtime(client)
seen_run_ids: set[str] = set()
results = [
provider_acceptance.run_qa_case(client, row, seen_run_ids)[0]
for row in qa_rows
]
results.extend(
provider_acceptance.run_review_case(client, row, seen_run_ids)[0]
for row in review_rows
)
finally:
server.shutdown()
server.server_close()
thread.join(timeout=5)
assert len(qa_rows) == 10
assert len(review_rows) == 8
assert len(results) == 18
assert schema["status"] == "ok"
assert provider_config["provider"] == "isolated-provider"
assert all(result.technical_status == "passed" for result in results)
assert all(result.legal_status == "needs_legal_review" for result in results)
def test_production_tool_bandit_suppressions_are_exactly_allowlisted() -> None:
expected = {
"yuqei-infra/backup/run-production-backup.py": ["B404", "B603"],
"yuqei-infra/backup/verify-production-backup.py": ["B404", "B603", "B603"],
"yuqei-infra/observability/check-production-health.py": ["B310", "B310"],
"yuqei-infra/scripts/run-ai-provider-acceptance.py": ["B310"],
}
observed: dict[str, list[str]] = {}
for relative_path in expected:
lines = (REPO_ROOT / relative_path).read_text(encoding="utf-8").splitlines()
observed[relative_path] = [
line.split("# nosec", 1)[1].strip()
for line in lines
if "# nosec" in line
]
assert observed == expected