Files
channel-exit/tests/test_reconcile.py
T
Nirav PatelandClaude Opus 5 349f03015f
CI / test (push) Successful in 5s
Ask the carrier what actually happened
A provider 2xx means it accepted the message, not that anyone received
it. Twilio answers 201 Created and the carrier may refuse seconds later,
and nothing watching HTTP status codes will ever know.

That is not hypothetical: the ledger shows 48 consecutive messages to
one number, every one undelivered, going back to January - including a
daily send for seven weeks. Each was recorded upstream as a success, and
each was billed.

Two decisions worth keeping. We poll rather than take a StatusCallback,
because this relay binds to loopback on purpose and no carrier can reach
it - polling costs one API call per run and keeps that property. And we
reconcile against the provider's ledger rather than our own record,
because our own record is exactly what was wrong, and it only knows
about messages we sent; Twilio's knows about the ones another service
sent too, which is how those 48 would have been caught.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-18 20:43:11 -04:00

102 lines
3.7 KiB
Python

"""Reconciliation.
These exist because the estate spent seven months treating "the provider
accepted it" as "the person got it". Every test here is about telling those two
apart.
"""
from __future__ import annotations
import json
from datetime import datetime, timezone
import pytest
from app.providers import Response
from app.reconcile import Message, describe, fetch, reconcile, window_start
def ledger(*rows) -> Response:
return Response(status=200, body=json.dumps({"messages": list(rows)}), headers={})
def row(sid="SM1", to="+15550001111", status="delivered", error=None):
return {"sid": sid, "to": to, "status": status, "error_code": error,
"date_sent": "Tue, 19 Aug 2026 00:00:00 +0000"}
def test_an_accepted_message_the_carrier_refused_is_a_failure_not_a_success():
"""The whole point. Twilio said 201 at send time for every one of these."""
report = reconcile([
Message("SM1", "+15550001111", "delivered", None, None),
Message("SM2", "+15550002222", "undelivered", "30032", None),
Message("SM3", "+15550003333", "failed", "30006", None),
])
assert report.delivered == 1
assert [m.sid for m in report.failed] == ["SM2", "SM3"]
assert report.ok is False
def test_sent_is_not_delivered():
"""Twilio's `sent` means it left Twilio, not that a handset received it —
counting it as success is the same mistake one layer down."""
report = reconcile([Message("SM1", "+15550001111", "sent", None, None)])
assert report.delivered == 0
assert report.in_flight == 1
assert report.ok is True # not yet a failure, but not a delivery either
def test_a_clean_window_is_ok():
report = reconcile([Message("SM1", "+1555", "delivered", None, None)])
assert report.ok and not report.failed
def test_an_unrecognised_status_is_surfaced_rather_than_assumed_good():
report = reconcile([Message("SM1", "+1555", "carrier_shrugged", None, None)])
assert report.unknown == ["carrier_shrugged"]
assert report.delivered == 0
def test_the_report_groups_by_reason_and_never_prints_a_full_number():
report = reconcile([
Message("SM1", "+17066762576", "undelivered", "30032", None),
Message("SM2", "+17066762576", "undelivered", "30032", None),
Message("SM3", "+15551230000", "failed", "30006", None),
])
text = describe(report)
assert "2x error 30032" in text.replace(" ", " ")
assert "***2576" in text
assert "+17066762576" not in text, "a report that leaks full numbers cannot be pasted anywhere"
assert "unverified toll-free" in text
def test_the_ledger_query_reads_every_sender_not_just_ours():
"""Reconciling against our own record would have missed the failures that
started this, because a different service sent them."""
captured = {}
def fake_get(url, *, headers, timeout):
captured["url"] = url
return ledger(row(sid="SMx", status="undelivered", error="30032"))
found = fetch(account_sid="AC123", auth_token="secret",
since=datetime(2026, 8, 12, tzinfo=timezone.utc), get=fake_get)
assert "Messages.json" in captured["url"]
assert "2026-08-12" in captured["url"]
assert "secret" not in captured["url"], "credentials belong in the header, not the query"
assert [m.status for m in found] == ["undelivered"]
assert found[0].error_code == "30032"
def test_a_refused_ledger_query_is_loud():
def refuse(url, *, headers, timeout):
return Response(status=401, body="unauthorized", headers={})
with pytest.raises(RuntimeError):
fetch(account_sid="AC1", auth_token="bad", since=window_start(24), get=refuse)
def test_window_start_looks_backwards():
assert window_start(24) < datetime.now(timezone.utc)