fix(telegram): pin durable provider destination proof
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 3m15s
CD Pipeline / build-and-deploy (push) Successful in 15m54s
CD Pipeline / post-deploy-checks (push) Successful in 2m17s

This commit is contained in:
Your Name
2026-07-18 16:17:15 +08:00
parent c528189ecf
commit 77bd6687dc
7 changed files with 927 additions and 68 deletions

View File

@@ -21,6 +21,28 @@ from src.models.agent99_completion import Agent99TelegramLifecycleRequest
from src.services import agent99_telegram_lifecycle as lifecycle_service
from src.services import telegram_gateway as gateway_service
DESTINATION_BINDING = "a" * 64
PROVIDER_DESTINATION_BINDING = "b" * 64
PROVIDER_DESTINATION_VERIFICATION_METHOD = (
"requested_chat_id_matches_provider_chat_id"
)
def provider_destination_context(
*,
destination_binding: str = DESTINATION_BINDING,
provider_destination_binding: str = PROVIDER_DESTINATION_BINDING,
) -> dict[str, object]:
return {
"destination_binding": destination_binding,
"provider_destination_binding": provider_destination_binding,
"provider_destination_verification_method": (
PROVIDER_DESTINATION_VERIFICATION_METHOD
),
"provider_destination_identity_verified": True,
"destination_binding_verified": True,
}
def payload() -> dict:
return {
@@ -356,7 +378,7 @@ def test_lifecycle_endpoint_202_retry_is_db_only_and_returns_200(
monkeypatch,
) -> None:
monkeypatch.setattr(settings, "AGENT99_SRE_ALERT_RELAY_TOKEN", "expected")
destination_binding = "a" * 64
destination_binding = DESTINATION_BINDING
calls = {"deliver": 0, "reconcile": 0}
async def pending_delivery(request):
@@ -397,6 +419,10 @@ def test_lifecycle_endpoint_202_retry_is_db_only_and_returns_200(
"delivery_status": "sent_reused",
"provider_message_id": "8124",
"destination_binding": destination_binding,
"provider_destination_binding": PROVIDER_DESTINATION_BINDING,
"provider_destination_verification_method": (
PROVIDER_DESTINATION_VERIFICATION_METHOD
),
"durable_outbound_acknowledged": True,
"destination_binding_verified": True,
"provider_send_performed": False,
@@ -421,6 +447,14 @@ def test_lifecycle_endpoint_202_retry_is_db_only_and_returns_200(
assert first.status_code == 202
assert first.headers["retry-after"] == "2"
assert set(first.json()["reconcile_receipt"]) == {
"schema_version",
"delivery_id",
"incident_id",
"state_key",
"provider_message_id",
"destination_binding",
}
retry_payload = {
**payload(),
"reconcile_receipt": first.json()["reconcile_receipt"],
@@ -508,12 +542,17 @@ async def test_lifecycle_durable_readback_binds_exact_identity_without_egress(
monkeypatch,
) -> None:
gateway = object.__new__(gateway_service.TelegramGateway)
destination_binding = "a" * 64
destination_binding = DESTINATION_BINDING
reconcile = AsyncMock(
return_value={
"status": "sent",
"provider_message_id": "8124",
"destination_binding": destination_binding,
"provider_destination_binding": PROVIDER_DESTINATION_BINDING,
"provider_destination_verification_method": (
PROVIDER_DESTINATION_VERIFICATION_METHOD
),
"provider_destination_identity_verified": True,
"visual_requested": True,
}
)
@@ -529,6 +568,10 @@ async def test_lifecycle_durable_readback_binds_exact_identity_without_egress(
state_key=payload()["state_key"],
expected_provider_message_id="8124",
expected_destination_binding=destination_binding,
expected_provider_destination_binding=PROVIDER_DESTINATION_BINDING,
expected_provider_destination_verification_method=(
PROVIDER_DESTINATION_VERIFICATION_METHOD
),
)
assert result["ok"] is True
@@ -537,6 +580,11 @@ async def test_lifecycle_durable_readback_binds_exact_identity_without_egress(
assert result["_awooop_durable_readback_performed"] is True
assert result["_awooop_delivery_context"] == {
"destination_binding": destination_binding,
"provider_destination_binding": PROVIDER_DESTINATION_BINDING,
"provider_destination_verification_method": (
PROVIDER_DESTINATION_VERIFICATION_METHOD
),
"provider_destination_identity_verified": True,
"destination_binding_verified": True,
"durable_exact_row_readback": True,
}
@@ -550,6 +598,10 @@ async def test_lifecycle_durable_readback_binds_exact_identity_without_egress(
},
expected_provider_message_id="8124",
expected_destination_binding=destination_binding,
expected_provider_destination_binding=PROVIDER_DESTINATION_BINDING,
expected_provider_destination_verification_method=(
PROVIDER_DESTINATION_VERIFICATION_METHOD
),
)
@@ -588,6 +640,10 @@ async def test_lifecycle_reconcile_destination_mismatch_never_finalizes(
},
expected_provider_message_id="8124",
expected_destination_binding="b" * 64,
expected_provider_destination_binding=PROVIDER_DESTINATION_BINDING,
expected_provider_destination_verification_method=(
PROVIDER_DESTINATION_VERIFICATION_METHOD
),
)
assert result["status"] == "destination_binding_mismatch"
@@ -598,7 +654,7 @@ async def test_lifecycle_reconcile_destination_mismatch_never_finalizes(
async def test_lifecycle_reconcile_service_never_enters_provider_sender(
monkeypatch,
) -> None:
destination_binding = "a" * 64
destination_binding = DESTINATION_BINDING
calls: list[dict] = []
class Gateway:
@@ -614,8 +670,9 @@ async def test_lifecycle_reconcile_service_never_enters_provider_sender(
"_awooop_delivery_status": "sent_reused",
"_awooop_provider_send_performed": False,
"_awooop_delivery_context": {
"destination_binding": destination_binding,
"destination_binding_verified": True,
**provider_destination_context(
destination_binding=destination_binding
),
"durable_exact_row_readback": True,
},
}
@@ -672,9 +729,7 @@ async def test_lifecycle_service_uses_durable_canonical_sender(monkeypatch) -> N
"_awooop_outbound_mirror_acknowledged": True,
"_awooop_delivery_status": "sent",
"_awooop_provider_send_performed": True,
"_awooop_delivery_context": {
"destination_binding_verified": True,
},
"_awooop_delivery_context": provider_destination_context(),
}
monkeypatch.setattr(
@@ -696,6 +751,49 @@ async def test_lifecycle_service_uses_durable_canonical_sender(monkeypatch) -> N
assert "raw_log" not in calls[0]["text"]
@pytest.mark.asyncio
async def test_lifecycle_repeat_after_success_reuses_provider_pinned_receipt(
monkeypatch,
) -> None:
calls = 0
class Gateway:
async def send_agent99_lifecycle_receipt(self, **_kwargs):
nonlocal calls
calls += 1
return {
"ok": True,
"result": {"message_id": 9123},
"_awooop_outbound_mirror_acknowledged": True,
"_awooop_delivery_status": (
"sent" if calls == 1 else "sent_reused"
),
"_awooop_provider_send_performed": calls == 1,
"_awooop_delivery_context": provider_destination_context(),
}
monkeypatch.setattr(
lifecycle_service,
"get_telegram_gateway",
lambda: Gateway(),
)
request = Agent99TelegramLifecycleRequest.model_validate(payload())
first = await lifecycle_service.deliver_agent99_telegram_lifecycle(request)
repeated = await lifecycle_service.deliver_agent99_telegram_lifecycle(
request
)
assert first["ok"] is True
assert first["provider_send_performed"] is True
assert repeated["ok"] is True
assert repeated["delivery_status"] == "sent_reused"
assert repeated["provider_send_performed"] is False
assert repeated["provider_destination_binding"] == (
PROVIDER_DESTINATION_BINDING
)
@pytest.mark.asyncio
async def test_lifecycle_reconciles_pending_send_without_duplicate_provider_message(
monkeypatch,
@@ -710,10 +808,7 @@ async def test_lifecycle_reconciles_pending_send_without_duplicate_provider_mess
"_awooop_delivery_status": "pending_unknown",
"_awooop_provider_send_performed": True,
"_awooop_visual_delivery_verified": True,
"_awooop_delivery_context": {
"destination_binding_verified": True,
"destination_binding": "a" * 64,
},
"_awooop_delivery_context": provider_destination_context(),
}
reconciled_response = {
"ok": True,
@@ -722,6 +817,7 @@ async def test_lifecycle_reconciles_pending_send_without_duplicate_provider_mess
"_awooop_delivery_status": "sent_reused",
"_awooop_provider_send_performed": False,
"_awooop_visual_delivery_verified": True,
"_awooop_delivery_context": provider_destination_context(),
}
class Gateway:
@@ -765,7 +861,13 @@ async def test_lifecycle_reconciles_pending_send_without_duplicate_provider_mess
"state_key": payload()["state_key"],
"project_id": "awoooi",
"expected_provider_message_id": "9126",
"expected_destination_binding": "a" * 64,
"expected_destination_binding": DESTINATION_BINDING,
"expected_provider_destination_binding": (
PROVIDER_DESTINATION_BINDING
),
"expected_provider_destination_verification_method": (
PROVIDER_DESTINATION_VERIFICATION_METHOD
),
}
@@ -787,10 +889,7 @@ async def test_lifecycle_reconciles_provider_sent_pending_ack_without_resend(
"provider_sent_durable_receipt_pending"
),
"_awooop_provider_send_performed": True,
"_awooop_delivery_context": {
"destination_binding_verified": True,
"destination_binding": "a" * 64,
},
"_awooop_delivery_context": provider_destination_context(),
}
async def reconcile_agent99_lifecycle_receipt(self, **kwargs):
@@ -801,9 +900,7 @@ async def test_lifecycle_reconciles_provider_sent_pending_ack_without_resend(
"_awooop_outbound_mirror_acknowledged": True,
"_awooop_delivery_status": "sent_reused",
"_awooop_provider_send_performed": False,
"_awooop_delivery_context": {
"destination_binding_verified": True,
},
"_awooop_delivery_context": provider_destination_context(),
}
async def no_sleep(_delay: float) -> None:
@@ -827,7 +924,20 @@ async def test_lifecycle_reconciles_provider_sent_pending_ack_without_resend(
assert len(send_calls) == 1
assert len(reconcile_calls) == 1
assert reconcile_calls[0]["expected_provider_message_id"] == "9129"
assert reconcile_calls[0]["expected_destination_binding"] == "a" * 64
assert (
reconcile_calls[0]["expected_destination_binding"]
== DESTINATION_BINDING
)
assert (
reconcile_calls[0]["expected_provider_destination_binding"]
== PROVIDER_DESTINATION_BINDING
)
assert (
reconcile_calls[0][
"expected_provider_destination_verification_method"
]
== PROVIDER_DESTINATION_VERIFICATION_METHOD
)
@pytest.mark.asyncio
@@ -856,7 +966,7 @@ async def test_lifecycle_follower_only_reads_inflight_durable_delivery(
"_awooop_delivery_status": "sent_reused",
"_awooop_provider_send_performed": False,
"_awooop_delivery_context": {
"destination_binding_verified": True,
**provider_destination_context(),
"durable_exact_row_readback": True,
},
}
@@ -882,6 +992,15 @@ async def test_lifecycle_follower_only_reads_inflight_durable_delivery(
assert len(reconcile_calls) == 1
assert reconcile_calls[0]["expected_provider_message_id"] is None
assert reconcile_calls[0]["expected_destination_binding"] is None
assert (
reconcile_calls[0]["expected_provider_destination_binding"] is None
)
assert (
reconcile_calls[0][
"expected_provider_destination_verification_method"
]
is None
)
@pytest.mark.asyncio
@@ -901,10 +1020,7 @@ async def test_lifecycle_reconciliation_fails_closed_after_bounded_readbacks(
"_awooop_outbound_mirror_acknowledged": False,
"_awooop_delivery_status": "pending_unknown",
"_awooop_provider_send_performed": True,
"_awooop_delivery_context": {
"destination_binding_verified": True,
"destination_binding": "a" * 64,
},
"_awooop_delivery_context": provider_destination_context(),
}
async def reconcile_agent99_lifecycle_receipt(self, **kwargs):
@@ -946,7 +1062,17 @@ async def test_lifecycle_reconciliation_fails_closed_after_bounded_readbacks(
for call in reconcile_calls
)
assert all(
call["expected_destination_binding"] == "a" * 64
call["expected_destination_binding"] == DESTINATION_BINDING
for call in reconcile_calls
)
assert all(
call["expected_provider_destination_binding"]
== PROVIDER_DESTINATION_BINDING
for call in reconcile_calls
)
assert all(
call["expected_provider_destination_verification_method"]
== PROVIDER_DESTINATION_VERIFICATION_METHOD
for call in reconcile_calls
)
@@ -965,9 +1091,7 @@ async def test_visual_lifecycle_uses_one_durable_send_photo_receipt(monkeypatch)
"_awooop_delivery_status": "sent",
"_awooop_provider_send_performed": True,
"_awooop_visual_delivery_verified": True,
"_awooop_delivery_context": {
"destination_binding_verified": True,
},
"_awooop_delivery_context": provider_destination_context(),
}
monkeypatch.setattr(
@@ -1016,7 +1140,7 @@ async def test_reused_legacy_text_receipt_does_not_claim_visual_delivery(
receipt = await lifecycle_service.deliver_agent99_telegram_lifecycle(request)
assert receipt["ok"] is True
assert receipt["ok"] is False
assert receipt["visual_requested"] is True
assert receipt["visual_sent"] is False
assert receipt["visual_delivery_status"] == "sent_reused"