Every 401/403 was answered by signing in again on the spot. For a login that
works but may not list the account's venues (media@waters.church at North
Attleboro got 403 on /venues), that was a successful sign-in on every 1s poll
-- the pattern that had just got another Resi account locked.
- A refusal straight after signing in is a permission, not an expired
session: it is held off like a failed login, with the message "This Resi
login isn't allowed to see its venues (403) — ask a Resi admin for access".
Only a session over a minute old is renewed.
- 429 on any request holds off too, not only on the login.
- The players cache-bust fallback no longer drops the parameter for good on a
401/403/429, which are about the login rather than the parameter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A failed login left no session, so the next 1s poll signed in again, and the
next, for ever. Resi answers that with 429s, and since the retries never let
up the account never got out of them: at North Attleboro the decoder picker
stayed empty with "Resi login failed (429)". The picker made it worse by
building a fresh client -- and signing in -- on every admin page load.
- After a failed login, further attempts wait 15s, doubling to 5min (or as
long as Resi's Retry-After asks); calls in between fail at once with the
reason and how long until the next try.
- The status says what happened: rate-limited, password rejected, or Resi
unreachable.
- The decoder picker reuses the running module's client when the login
matches, otherwise one client per login, so it shares the hold-off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a Resi that publishes every ~30s, the board could start a few seconds
before a publish and learn a 2s cadence from that partial first gap. Every
honest 30s gap after that was thrown out as a pause, so playback read as
paused 15s into every update: the countdown froze, and the next cue -- and
the name on the Timers card -- stopped moving on.
- The partial gap right after startup is no longer learned, and one outlier
gap can no longer lock out the real cadence.
- Until a cadence is measured, a pause is only called after 45s, not 15s.
- The Timers card is titled with the cue's name; its status line now says
"Next cue" / "Held" instead of repeating the name.
- server.test.js awaited nothing, so an async test raced the next one and
failed on main; tests now run one at a time.
Same fix as the Resi -> ProPresenter bridge and the Companion module 0.1.2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>