Files
awoooi/apps/api/tests/test_paid_provider_canary_authorization.py
ogt 541a32a9cb
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m38s
CD Pipeline / build-and-deploy (push) Failing after 24m19s
CD Pipeline / post-deploy-checks (push) Has been skipped
feat(sre): enforce typed controlled automation
2026-07-16 17:32:01 +08:00

257 lines
8.7 KiB
Python

from __future__ import annotations
import os
from dataclasses import replace
from datetime import UTC, datetime, timedelta
from uuid import UUID, uuid4
import pytest
os.environ.setdefault("DATABASE_URL", "postgresql+asyncpg://test:test@localhost/test")
from src.services.paid_provider_canary_authorization import ( # noqa: E402
PAID_CANARY_AGENT_ID,
PAID_CANARY_PROJECT_ID,
PAID_CANARY_TRIGGER_REF,
PAID_CANARY_TRIGGER_TYPE,
PAID_CANARY_WORK_ITEM_ID,
PaidProviderCanaryAuthorizationError,
PaidProviderCanaryAuthorizationEvidence,
paid_provider_canary_authorization_input,
paid_provider_canary_authorization_input_sha256,
require_paid_provider_canary_authorization,
verify_paid_provider_canary_authorization,
)
_SELECTED_RUN_ID = UUID("267a3d26-3c29-470f-8fe3-388a2f408f39")
_TRACE_ID = "00-0123456789abcdef0123456789abcdef-0123456789abcdef-01"
class _Reader:
def __init__(
self,
evidence: PaidProviderCanaryAuthorizationEvidence | None,
*,
error: Exception | None = None,
) -> None:
self.evidence = evidence
self.error = error
self.calls: list[tuple[UUID, str, str]] = []
async def read(
self,
*,
run_id: UUID,
project_id: str,
work_item_id: str,
) -> PaidProviderCanaryAuthorizationEvidence | None:
self.calls.append((run_id, project_id, work_item_id))
if self.error is not None:
raise self.error
return self.evidence
def _evidence(
*,
now: datetime,
run_id: UUID | None = None,
) -> PaidProviderCanaryAuthorizationEvidence:
return PaidProviderCanaryAuthorizationEvidence(
run_id=run_id or _SELECTED_RUN_ID,
trace_id=_TRACE_ID,
project_id=PAID_CANARY_PROJECT_ID,
agent_id=PAID_CANARY_AGENT_ID,
state="running",
trigger_type=PAID_CANARY_TRIGGER_TYPE,
trigger_ref=PAID_CANARY_TRIGGER_REF,
is_shadow=False,
input_sha256=paid_provider_canary_authorization_input_sha256(),
timeout_at=now + timedelta(minutes=5),
approval_step_count=1,
approval_step_status="success",
approval_step_was_blocked=False,
approval_completed_at=now - timedelta(minutes=1),
approval_audit_count=1,
approval_audit_created_at=now - timedelta(seconds=50),
prior_canary_start_count=0,
)
def test_authorization_input_is_detached_and_hash_is_stable() -> None:
first = paid_provider_canary_authorization_input()
second = paid_provider_canary_authorization_input()
first["provider_order"].append("unexpected")
assert second["project_id"] == "awoooi"
assert second["work_item_id"] == "AIA-SRE-013"
assert "unexpected" not in second["provider_order"]
assert len(paid_provider_canary_authorization_input_sha256()) == 64
assert (
paid_provider_canary_authorization_input_sha256()
== paid_provider_canary_authorization_input_sha256()
)
@pytest.mark.asyncio
async def test_exact_gate5_evidence_returns_non_sensitive_authorized_receipt() -> None:
now = datetime(2026, 7, 16, 8, 0, tzinfo=UTC)
evidence = _evidence(now=now)
reader = _Reader(evidence)
receipt = await verify_paid_provider_canary_authorization(
str(evidence.run_id),
evidence_reader=reader,
now=now,
)
assert receipt["authorized"] is True
assert receipt["status"] == "authorized"
assert receipt["authorization_ref"] == str(evidence.run_id)
assert receipt["run_id"] == str(evidence.run_id)
assert receipt["trace_id"] == _TRACE_ID
assert receipt["project_id"] == "awoooi"
assert receipt["work_item_id"] == "AIA-SRE-013"
assert receipt["valid_for_seconds"] == 300
assert receipt["checks"]["authorization_unused"] is True
assert receipt["checks"]["authorization_run_selected"] is True
assert receipt["contract"]["same_run_identity"] is True
assert receipt["reuse_check"] == "clear_at_read_time"
assert receipt["read_only_verification"] is True
assert receipt["authorization_consumed_by_verifier"] is False
assert receipt["operator_identity_returned"] is False
assert receipt["secret_value_read_or_returned"] is False
assert "approver_id" not in str(receipt)
assert reader.calls == [
(evidence.run_id, PAID_CANARY_PROJECT_ID, PAID_CANARY_WORK_ITEM_ID)
]
@pytest.mark.asyncio
async def test_authorization_ref_must_be_canonical_uuid_without_db_read() -> None:
reader = _Reader(None)
malformed = await verify_paid_provider_canary_authorization(
"AIA-SRE-013-user-approved-20260716",
evidence_reader=reader,
)
uppercase = await verify_paid_provider_canary_authorization(
str(uuid4()).upper(),
evidence_reader=reader,
)
assert malformed["authorized"] is False
assert malformed["error_code"] == (
"paid_canary_authorization_ref_must_be_uuid_run_id"
)
assert uppercase["authorized"] is False
assert uppercase["error_code"] == (
"paid_canary_authorization_ref_not_canonical_uuid"
)
assert reader.calls == []
@pytest.mark.asyncio
@pytest.mark.parametrize(
("field", "value", "failed_check"),
[
("project_id", "other", "project_exact"),
(
"run_id",
UUID("00000000-0000-4000-8000-000000000001"),
"authorization_run_selected",
),
("agent_id", "generic-agent", "agent_exact"),
("state", "waiting_approval", "state_executable"),
("is_shadow", True, "non_shadow"),
("trigger_type", "schedule", "trigger_type_exact"),
("trigger_ref", "paid-provider-canary:OTHER", "trigger_ref_exact"),
("input_sha256", "0" * 64, "input_sha256_exact"),
("trace_id", None, "trace_id_present"),
("approval_step_count", 0, "approval_step_exactly_once"),
("approval_step_status", "failed", "approval_step_success"),
("approval_step_was_blocked", True, "approval_step_not_blocked"),
("approval_audit_count", 0, "approval_audit_exactly_once"),
("prior_canary_start_count", 1, "authorization_unused"),
],
)
async def test_contract_drift_fails_closed(
field: str,
value: object,
failed_check: str,
) -> None:
now = datetime(2026, 7, 16, 8, 0, tzinfo=UTC)
evidence = replace(_evidence(now=now), **{field: value})
receipt = await verify_paid_provider_canary_authorization(
str(evidence.run_id),
evidence_reader=_Reader(evidence),
now=now,
)
assert receipt["authorized"] is False
assert failed_check in receipt["failed_checks"]
assert receipt["checks"][failed_check] is False
@pytest.mark.asyncio
async def test_missing_timeout_or_expired_approval_fails_closed() -> None:
now = datetime(2026, 7, 16, 8, 0, tzinfo=UTC)
missing_timeout = replace(_evidence(now=now), timeout_at=None)
expired = replace(
_evidence(now=now),
approval_completed_at=now - timedelta(minutes=16),
timeout_at=now + timedelta(minutes=5),
)
missing_receipt = await verify_paid_provider_canary_authorization(
str(missing_timeout.run_id),
evidence_reader=_Reader(missing_timeout),
now=now,
)
expired_receipt = await verify_paid_provider_canary_authorization(
str(expired.run_id),
evidence_reader=_Reader(expired),
now=now,
)
assert missing_receipt["authorized"] is False
assert missing_receipt["checks"]["run_timeout_present"] is False
assert expired_receipt["authorized"] is False
assert expired_receipt["checks"]["authorization_not_expired"] is False
@pytest.mark.asyncio
async def test_db_error_and_missing_run_are_blocked_without_error_detail() -> None:
run_id = uuid4()
unavailable = await verify_paid_provider_canary_authorization(
str(run_id),
evidence_reader=_Reader(None, error=RuntimeError("database dsn secret")),
)
missing = await verify_paid_provider_canary_authorization(
str(run_id),
evidence_reader=_Reader(None),
)
assert unavailable["error_code"] == (
"paid_canary_authorization_evidence_unavailable"
)
assert "database dsn secret" not in str(unavailable)
assert missing["error_code"] == "paid_canary_authorization_run_not_found"
@pytest.mark.asyncio
async def test_require_helper_raises_only_safe_error_code() -> None:
run_id = uuid4()
with pytest.raises(PaidProviderCanaryAuthorizationError) as raised:
await require_paid_provider_canary_authorization(
str(run_id),
evidence_reader=_Reader(None),
)
assert raised.value.error_code == "paid_canary_authorization_run_not_found"
assert str(raised.value) == raised.value.error_code
assert raised.value.receipt["authorized"] is False