Say when a 401 means only that the proof was spent #189

Merged
paulhitt merged 2 commits from fix/replayed-proof-code into main 2026-09-10 13:33:53 +00:00
paulhitt commented 2026-09-10 12:35:00 +00:00 (Migrated from gitlab.com)

Every AuthError but one collapsed into the same unauthorized code, so
a client that got a 401 had nothing to go on but the prose, and the
sensible reading of "unauthorized" is that the token is bad. It usually
isn't.

A proof of possession is single use, and the request that spends one is
frequently not a request the app made at all: URLSession replays an
idempotent GET onto a new interface when a phone moves between wi-fi
and cellular, headers and all. The relay refuses the replay, correctly.
The client then throws away a perfectly good token and mints another
before it can carry on, and during a call that round trip lands in
front of the signalling. Seen in production: an iPhone flapped between
wi-fi and cellular twice while a call was being set up, and paid for it
each time.

So a spent proof gets its own code, and says what to do about it. Still
a 401, because the request was not authorised.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

Every AuthError but one collapsed into the same `unauthorized` code, so a client that got a 401 had nothing to go on but the prose, and the sensible reading of "unauthorized" is that the token is bad. It usually isn't. A proof of possession is single use, and the request that spends one is frequently not a request the app made at all: URLSession replays an idempotent GET onto a new interface when a phone moves between wi-fi and cellular, headers and all. The relay refuses the replay, correctly. The client then throws away a perfectly good token and mints another before it can carry on, and during a call that round trip lands in front of the signalling. Seen in production: an iPhone flapped between wi-fi and cellular twice while a call was being set up, and paid for it each time. So a spent proof gets its own code, and says what to do about it. Still a 401, because the request was not authorised. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
paulhitt commented 2026-09-10 12:35:00 +00:00 (Migrated from gitlab.com)

assigned to @paulhitt

assigned to @paulhitt
paulhitt commented 2026-09-10 12:48:56 +00:00 (Migrated from gitlab.com)

added 3 commits

  • 35ed1967...80c828bb - 2 commits from branch main
  • eaf5e122 - Say when a 401 means only that the proof was spent

Compare with previous version

added 3 commits <ul><li>35ed1967...80c828bb - 2 commits from branch <code>main</code></li><li>eaf5e122 - Say when a 401 means only that the proof was spent</li></ul> [Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/126/diffs?diff_id=2017330249&start_sha=35ed19678fe61400a66a1387631908992dd2565e)
paulhitt commented 2026-09-10 12:52:35 +00:00 (Migrated from gitlab.com)

added 1 commit

  • 4488e67b - Stop a proof-of-work test failing once every few thousand runs

Compare with previous version

added 1 commit <ul><li>4488e67b - Stop a proof-of-work test failing once every few thousand runs</li></ul> [Compare with previous version](/paulhitt/flamenet-relay/-/merge_requests/126/diffs?diff_id=2017341795&start_sha=eaf5e122277ac8db87432ea311308420d586a9d2)
paulhitt commented 2026-09-10 13:33:53 +00:00 (Migrated from gitlab.com)

mentioned in commit 545470dffa

mentioned in commit 545470dffa5d348c60dae0b8e693ac7a4c1da9e0
paulhitt (Migrated from gitlab.com) merged commit 545470dffa into main 2026-09-10 13:33:53 +00:00
paulhitt commented 2026-09-12 01:23:04 +00:00 (Migrated from gitlab.com)

mentioned in issue #62

mentioned in issue #62
Sign in to join this conversation.