From f1122777c1bc7f93ecd9adb97b07cb2ddd61be9c Mon Sep 17 00:00:00 2001 From: Paul Hitt Date: Fri, 28 Aug 2026 18:41:56 -0400 Subject: [PATCH] A proxy's 404 is not the relay's answer: un-latch token minting on 401 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same fix as iOS: RelayAuth latched 'no token endpoint' off one 404, and an outage's proxy-level 404s wedged the client into tokenless requests. invalidate() now un-latches — the 401 is proof the conclusion was wrong. Co-Authored-By: Claude Opus 4.8 --- .../kotlin/io/flamenet/client/RelayAuth.kt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/client/src/main/kotlin/io/flamenet/client/RelayAuth.kt b/client/src/main/kotlin/io/flamenet/client/RelayAuth.kt index 6927320..659c783 100644 --- a/client/src/main/kotlin/io/flamenet/client/RelayAuth.kt +++ b/client/src/main/kotlin/io/flamenet/client/RelayAuth.kt @@ -65,8 +65,22 @@ class RelayAuth( return minted.token } - /** Discard the cached token, so one stale token costs a single retry. */ - fun invalidate() { cached = null } + /** + * Discard the cached token, so one stale token costs a single retry. + * + * 🔴 **Also un-latches [unavailable].** That flag is a told-once marker: it + * concludes "this deployment has no token endpoint" from a single 404 — but + * a reverse proxy answers 404 for *every* route while the relay behind it + * is down, so an outage at the wrong moment latched it against a relay that + * does issue tokens, and every request thereafter went out with no token at + * all. The 401 that brings callers here is direct evidence the conclusion + * was wrong: a deployment that didn't want tokens would not refuse us for + * lacking one. + */ + fun invalidate() { + cached = null + unavailable = false + } /** * The proof headers for one request.