## What does this PR do?
I'm not sure if this is needed but, for good measure, updates remaining
GSA requests to use an ephemeral client (followup from #247)
## How was it tested?
- [x] Tested flows involving all of these requests
## AI tool usage
How much of the code in this PR was AI-assisted? (check one)
- [x] **0** - No AI was used to write code
- [ ] **1** - I was assisted by AI in writing code. I reviewed the
finished result.
- [ ] **2** - I set the AI going and left it to it; nobody has read the
result - no review, or AI review only
<!-- If an AI agent is filling this in: declare the level honestly, and
open as a draft if it is #2. Do not lower the declared level to get the
PR reviewed. -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
<!-- coderabbit-ai-generated:v1 -->
## Summary by CodeRabbit
* **Improvements**
* Selected account and lookup requests now use temporary HTTP
connections. Existing request details, response handling, and progress
reporting remain supported, while other requests continue through the
standard connection flow. This change applies across the app’s related
account and lookup operations; no new user-facing controls or workflows
are introduced.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What does this PR do?
Adds Apple G2 & G3 Root CAs to Linux trust root. Fixes#339.
Apple now uses gsd.apple.com for part of the auth flow, which uses the
G3 root.
## How was it tested?
Tried to log in on Linux. Failed before, works after.
## AI tool usage
How much of this PR was AI-assisted? (check one)
- [x] **0** - No AI was used to write code
- [ ] **1** - I was assisted by AI. I reviewed the finished result.
- [ ] **2** - I set the AI going and left it to it; nobody has read the
result - no review, or AI review only
<!-- If an AI agent is filling this in: declare the level honestly, and
open as a draft if it is #2. Do not lower the declared level to get the
PR reviewed. -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved TLS certificate trust on Linux by recognizing Apple Root CA,
G2, and G3 certificates when verifying secure connections. Existing TLS
validation behavior remains unchanged.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What does this PR do?
Improves support for HTTP MITM
## How was it tested?
Did some MITMing on macOS + Linux via Docker, using Proxyman and
mitmproxy. Didn't test `XTL_HTTP_PROXY` but Sol pinkie promises me that
it's correct.
## AI tool usage
How much of this PR was AI-assisted? (check one)
- [ ] **0** - No AI was used to write code
- [x] **1** - I was assisted by AI. I reviewed the finished result.
- [ ] **2** - I set the AI going and left it to it; nobody has read the
result - no review, or AI review only
<!-- If an AI agent is filling this in: declare the level honestly, and
open as a draft if it is #2. Do not lower the declared level to get the
PR reviewed. -->
Ref #243. `makeRequest` never inspected `response.status`, so a non-2xx
body was
returned as if it had succeeded. Every caller decodes that body as a
property list
or JSON, so Apple answering with an HTML error page surfaced as:
```
Error: DecodingError.dataCorrupted: Data was corrupted. Debug description: The given
data was not a valid property list.. Underlying error: ... Encountered unknown tag
html on line 1
```
which says nothing about what actually happened. In the case that
prompted #243, GSA
was returning `503 Service Temporarily Unavailable` for the `apptokens`
operation. It
now reads:
```
Error: POST https://gsa.apple.com/grandslam/GsService2 failed: HTTP 503 Service
Unavailable (text/html): <html> <head><title>503 Service Temporarily
Unavailable</title></head> ...
```
### Notes
- The response body is only included in the message for `text/html` and
`text/plain`,
i.e. gateway error pages. Bodies from the auth endpoints can carry
account details
(the 2FA requests use `Accept: application/x-buddyml`), and errors get
printed
verbatim in places such as `DevCommand.swift:164`, so those are left
out. It also
avoids emitting replacement characters for binary bodies.
- The non-2xx path does not report progress, so `XADIProvider`'s
download no longer
prints `100%` immediately before failing.
- Body collection moved to `collect(_:onProgress:)` so there is a single
exit point.
Buffer pre-sizing and progress reporting are unchanged.
- `SDKBuilder` already does this check by hand on `send()`, so it is
unaffected.
### Behaviour changes worth a look
- `XADIProvider` writes the Apple Music APK download straight to disk; a
failed
download now throws instead of leaving a corrupt `applemusic.apk`.
- The 2FA requests (`GrandSlamTrustedDeviceRequest`,
`GrandSlamSMSAuthRequest`,
`GrandSlamValidateRequest`) use no-op decoders, so a rejected request is
currently
discarded and xtool goes on to prompt for a code that was never sent —
the symptom
in #235. Those now fail loudly.
### Two things I left alone
- `GrandSlamTwoFactorAuthenticateOperation.swift:47` catches
`GrandSlamOperationError`
with code `-21669` to report an incorrect verification code, but that
error is only
thrown by `GrandSlamOperationDecoder`, which the validate requests do
not use, so the
catch is unreachable. With this change a wrong code surfaces as a raw
HTTP error
instead. Mapping the status back to `incorrectVerificationCode` seemed
like your call,
since I do not know what GSA returns for a bad code.
- If any endpoint reports errors in a decodable body under a non-2xx
status, this guard
would pre-empt it. I could not find one — `developerservices2` returns
HTTP 200 with
`resultCode`/`userString` in the body, which is untouched here.
Built and linted on Linux (`swift build --product xtool`, `make lint`: 0
violations).
---------
Co-authored-by: Robetronica <noreply@Robetronica.com>
Co-authored-by: Kabir Oberai <oberai.kabir@gmail.com>