G7.6: fix the alert path — urllib UA was rejected 403 by Resend
All checks were successful
check / gate (push) Successful in 18s
canary / probe (push) Successful in 22s

Caught by TESTING the alert path instead of assuming it. Without an explicit
User-Agent, urllib sends 'Python-urllib/3.x' and Resend rejects it 403, while
the identical request via curl succeeds.

The failure mode this avoids is the worst one a canary has: it would have
detected every outage correctly and told nobody. Same bot-filtering trap as the
Gitea migrate call earlier today — worth recognising on sight.

Also prints the HTTP body on failure. '403 Forbidden' alone sends you hunting
for a bad key; the body names the real cause.

Verified: alert sent (200).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Grant Whitmer
2026-08-12 13:44:00 -04:00
parent 9a7030351b
commit fc1937560c
2 changed files with 22 additions and 0 deletions

View File

@@ -537,3 +537,13 @@ def test_g76_canary_has_two_independent_signals():
had one signal and nothing watched the watcher."""
src = (ROOT / "scripts" / "canary.py").read_text()
assert "return 1 if any" in src, "canary must exit non-zero so CI goes red"
def test_g76_alert_path_sets_a_user_agent():
"""Without an explicit User-Agent, urllib sends 'Python-urllib/3.x' and
Resend rejects it 403 while the identical curl succeeds. Caught by testing
the alert path: the canary would have detected every outage correctly and
told nobody."""
src = (ROOT / "scripts" / "canary.py").read_text()
send = src[src.index("def send_alert") : src.index("def main(")]
assert "User-Agent" in send