Files

139 lines
5.2 KiB
Python
Raw Permalink Normal View History

2026-08-18 20:43:11 -04:00
"""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)
# --------------------------------------------------------------- email
from app.reconcile import EmailReport, describe_email, email_bounces # noqa: E402
def test_a_key_that_cannot_read_bounces_says_so_instead_of_reporting_clean():
"""The estate's key is send-only. Skipping the check quietly is how a
channel nobody can see becomes a channel nobody checks."""
def forbidden(url, *, headers, timeout):
return Response(status=403, body='{"errors":[{"message":"access forbidden"}]}', headers={})
report = email_bounces(api_key="SG.x", since=window_start(24), get=forbidden)
assert report.checked is False
assert report.bounces == []
assert "suppression.read" in report.reason
assert "NOT VERIFIED" in describe_email(report)
def test_bounces_are_reported_without_publishing_addresses():
def ledger_of_bounces(url, *, headers, timeout):
return Response(status=200, headers={}, body=json.dumps([
{"email": "[email protected]", "reason": "550 5.1.1 user unknown"}]))
report = email_bounces(api_key="SG.x", since=window_start(24), get=ledger_of_bounces)
text = describe_email(report)
assert report.checked and len(report.bounces) == 1
assert "***@example.test" in text
assert "[email protected]" not in text
def test_no_key_is_reported_as_unverified_not_as_healthy():
report = email_bounces(api_key="", since=window_start(24))
assert report.checked is False and "no SendGrid key" in report.reason