fix(client): replace an expired proof-of-work challenge - #49
Merged
Conversation
The widget fetched a challenge when it loaded and never replaced it: _solve asked for one only when it held none at all. A page open longer than the server's five-minute window therefore submitted a solution to a challenge the server had already dropped, which it refused — withholding the token while scoring the visitor as human and recommending allow. The checkbox reported "Verification failed" to someone who had done nothing wrong. _showFailure then left the spent challenge in place, so every retry repeated the same refusal until the page was reloaded. _solve now replaces a challenge at or inside a 15s margin of its expiry, and a failed attempt drops the spent one and fetches a replacement so the retry has something to work with. Browser tests cover the expired case, the still-live case that must not throw a good challenge away, and the retry. Found running a real Statamic site against the server: a contact form filled in slowly failed on the first click and every click after it.
cport1
force-pushed
the
fix/client-challenge-refresh
branch
from
August 30, 2026 15:33
0acecd6 to
5701476
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The widget fetched a PoW challenge on load and never replaced it, so a page open
longer than the server's five-minute window submitted a solution to a challenge
the server had already dropped. The server refused the proof and withheld the
token while scoring the visitor as human — the checkbox showed "Verification
failed".
_showFailurekept the spent challenge, so retries repeated the samerefusal until a reload.
_solvenow replaces a challenge at or inside a 15s margin of its expiry, and afailed attempt fetches a replacement.
Tests:
test/browser/tests/challenge-refresh.spec.ts(expired challengereplaced, live challenge kept, retry gets a fresh one). Full browser suite: 41
passed.