Show how long Apple asked to wait after a refused sign-in - #200
Merged
Merged
Conversation
AppleServiceUnavailableError gains retry_after (None when Apple did not say, which is every refusal seen so far), and a refusal now logs the request headers minus the secrets and the response headers in full. Its message no longer promises the refusal clears on its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A refusal carrying Retry-After now names the wait, rounded up, in place of "try again shortly". Without the header - every refusal observed so far - the message is unchanged and names no number. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The bridge carries retryAfterSeconds only when Apple sent Retry-After, and the screen replaces "try again shortly" with the wait, rounded up and worded by ICU for the locale. Absent stays absent all the way across: zero would read as "retry now". The loginSync failure harness moves to conftest.py so the new bridge tests can drive it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This branch was successfully deployed
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.
Reads
Retry-Afteron a refused sign-in and shows the wait, in the app and the exporter. When the header is absent, nothing changes.No refusal from Grand Slam has been observed carrying
Retry-After, including the 503s and the 429 seen on 2026-09-13. So the case users actually hit is the one without it, and that path invents no number.FindMy.py fork,
bcb0787(pinned in all four places)AppleServiceUnavailableError.retry_after: seconds fromRetry-After, in either RFC 9110 form, looked up case-insensitively because HTTP/2 lowercases header names.Nonewhen absent or unreadable.X-Apple-I-MD,X-Apple-I-MD-M, the identity token and the GS token removed, plus the response headers in full.Exporter
describe_apple_decliningnames the wait, rounded up, and drops "try again shortly" when Apple gave one.App
loginSyncsendsretryAfterSecondsonly when present;PythonAccountLoginException.getRetryAfterSeconds()is null otherwise.login_failed_apple_asked_to_waitwith the wait formatted byandroid.icu.text.MeasureFormatfor the locale, which is available from API 24, the app'sminSdk. It's a new string in all ten locales.Tests
test_service_unavailable.pytest_apple_asked_to_wait.pyretryAfterSeconds, including 0test_apple_declining.pyHowLongToWaitTest(JVM)AppleLoginFlowTestaWaitAppleNamedIsShownRoundedUpappleDecliningIsNotBlamedOnThePasswordOrTheNetworkThe fork tests were checked by breaking the code: turning off the redaction, making the lookup case-sensitive, and ignoring the header each turned the matching tests red. Java compilation, the JVM suite and the emulator suite run only in CI here.
Not covered: the iCloud list's
APPLE_DECLINEDpath (icloud_bridge) still shows its fixed sentence and doesn't carry the wait.🤖 Generated with Claude Code