446 Commits

  • anisette: fix crash in date formatter (#422)
    ## What does this PR do?
    
    Password login can terminate with an illegal-instruction crash on Linux,
    leaving the user logged out. Anisette client time was formatted with
    DateFormatter and an explicitly assigned Gregorian calendar. That
    formatting path reaches Foundation’s NSCalendar bridging code, where the
    reported crash occurs.
    
    AnisetteData now formats client time with Date.ISO8601FormatStyle,
    avoiding the DateFormatter calendar bridge. The header retains its UTC
    timestamp format with whole seconds and a trailing Z. New parameterized
    tests check the complete header dictionary for the Unix epoch, a year
    boundary, leap day, and a timestamp with fractional seconds.
    
    Fixes #184
    
    ## How was it tested?
    
    Ran `swift test` locally on macOS for the xtool AnisetteData change; it
    fails the same way on the base branch, so the failure predates this
    change (it fails the same way on upstream/main).
    `swift build` failed because an async call in a defer body prevented
    compilation.
    `swift test` failed during compilation with the same async-in-defer
    error, so the tests did not run.
    `repo_lint` ran without reported output.
    `make lint SWIFTLINT_FLAGS='--reporter=github-actions-logging' | tee
    swiftlint.log` ran with no lint diagnostics shown in the transcript.
    
    The tests in `Tests/XToolTests/AnisetteDataTests.swift` fail without the
    fix in the xtool AnisetteData change (checked by reverting the source
    changes).
    
    ## AI tool usage
    
    How much of the code in this PR was AI-assisted? (check one)
    
    - [ ] **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
    
    AI was used for assistance.
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
    * Client timestamps now use a consistent UTC ISO 8601 format with dashed
    dates, colon-separated times, and no fractional seconds. This applies to
    timestamps with or without fractional seconds in the source date.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    ---------
    
    Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
  • ds: fix profile creation conflicts (#430)
    ## What does this PR do?
    
    Fixes issues with missing devices and duplicate names when creating new
    profiles. Supersedes #427 and #428.
    
    Fixes #425, fixes #426
    
    ## How was it tested?
    
    - [x] Ran locally
    - [x] Confirmed that free accounts also support multiple profiles as
    long as the names are different.
    
    ## 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
    
    * **Bug Fixes**
    * Profile creation now uses only enabled devices that support iOS apps.
    * Existing profiles with the exact generated profile name are removed
    before a replacement is created, including when multiple matches exist.
      * Profile handling now stops when the operation is canceled.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    Co-authored-by: Valentin Brosseau <c4software@gmail.com>
  • build: update to Swift 6.4.2 (#421)
    ## What does this PR do?
    
    Build with Swift 6.4.2 on Linux
    
    ## How was it tested?
    
    CI
    
    ## 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. -->
  • utils: support forwarding Subprocess output (#413)
    ## What does this PR do?
    
    When spawning a subprocess,
    `currentStandardOutput`/`currentStandardError` bypass `d.out`. Add
    `.xtoolOutput()` and `.xtoolError()` which respect the dependency.
    
    ## How was it tested?
    
    Tested in a downstream PR to ensure that forwarding works
    
    ## 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
    -->
    
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **New Features**
    * Subprocess output can now be routed directly to XTool’s standard
    output or standard error.
    * Added a way to create a writable output descriptor that forwards data
    to a selected stream.
    * Asynchronous input reading is now available through a public
    interface, including configurable read sizes and explicit closing.
    
    * **Compatibility**
      * Existing input-reading behavior and parameters remain unchanged.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • gsa: make more reqs ephemeral (#417)
    ## 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 -->
  • gsa: more SMS 2FA fixes (#416)
    ## What does this PR do?
    
    Applies the 2FA SMS login fixes from #405
    
    ## How was it tested?
    
    - [x] 2FA SMS arrives
    - [x] Can log in with SMS code
    
    ## AI tool usage
    
    How much of the code in this PR was AI-assisted? (check one)
    
    - [ ] **0** - No AI was used to write code
    - [x] **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**
    * SMS verification requests now use an updated phone verification format
    and numeric phone-number IDs.
    * Code validation also uses numeric phone-number IDs, keeping the
    identifier format consistent across SMS authentication steps. The
    verification request and code-validation request now follow the same
    updated format.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    Co-authored-by: Corne Steenhuis <cornesteenhuis@hotmail.com>
  • gsa: GrandSlamMethod -> GrandSlamRequestContent (#415)
    ## What does this PR do?
    
    Renames GrandSlamMethod to GrandSlamRequestContent and adds support for
    json & PUT requests
    
    ## How was it tested?
    
    - [x] Still compiles
    - [x] `xtool auth`
    
    ## 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
    
    * **New Features**
    * Requests can now send either JSON or XML bodies using POST or PUT. GET
    requests are sent without a body.
    * **Improvements**
    * Authentication and verification requests now use a consistent request
    format while retaining their existing behavior.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • signer: replace zsign with RCodesign (#389)
    ## What does this PR do?
    
    Replaces zsign with the
    [apple-codesign](https://github.com/indygreg/apple-platform-rs/tree/0ebbd2ef3b96d5adccc30b1cad4deea38cd735c4/apple-codesign)
    Rust crate. It's much more usable as a library (while zsign has bare
    prints all over the place + we had to fork it to maintain a public
    interface), it supports macOS-style bundles, and also has other features
    that we would've needed to further patch zsign for.
    
    ## How was it tested?
    
    - [x] Ran an ad-hoc signed app on the simulator (with a subsequent PR)
    - [x] Ran an app with App Groups on device, confirmed that the app group
    is present
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Updated Signing**
    * App signing now uses an updated signing engine and supports
    certificate-based and ad hoc signing.
    * Entitlement data, including data provided through entitlement files,
    is passed through during signing.
      * Deep signing is enabled in the development command.
    * **Validation**
    * Signing rejects invalid app or entitlement file paths and duplicate
    entitlement paths.
    * **Compatibility**
      * Signing contexts can be created without selecting a signer.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • meta: update readme and agents.md (#412)
    ## What does this PR do?
    
    Updates readme & agents guidance
    
    ## How was it tested?
    
    i read it back with mine own eyes
    
    ## 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
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Documentation**
    * Clarified how to consume xtool as a Swift Package and that CLI
    stability guarantees do not apply to Swift interfaces.
    * Updated Swift development conventions with dependency-injection
    examples, concurrency guidance, and commit-message formatting.
    * **Chores**
    * Updated the pull request template to ask how much code was AI-assisted
    and note that the completed work was reviewed.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • ds: allow one app group on free teams (#284)
    ## What does this PR do?
    
    Resolves the FIXME in `DeveloperServicesCapability`: App Groups are no
    longer filtered out on free teams, and
    `DeveloperServicesAddAppOperation` assigns at most one group per app on
    a free team (the constraint the FIXME mentioned).
    
    Free teams can register and assign app groups through the Xcode
    DeveloperServices API (as AltStore/SideStore do), so a widget and its
    app can share `UserDefaults(suiteName:)` with a free Apple ID.
    
    ## How was it tested?
    
    Built on Linux from `main` (4d0c429). Installed a Flutter app with a
    WidgetKit extension on an iPhone (iOS 27.2) with a free Apple ID: the
    app gets `group.XTL-<team>.<id>` in its entitlements and the widget
    reads the app's data through it. `make lint` not run (no SwiftLint on
    this machine).
    
    ## 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
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
      * App Groups are now available to free teams.
    * Apps assigned to multiple App Groups are rejected with a clear error
    message.
    * Invalid app errors now include the app’s URL path, making it easier to
    identify which app could not be added.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    ---------
    
    Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
    Co-authored-by: Kabir Oberai <oberai.kabir@gmail.com>
  • ds: fix assigning multiple app groups (#403)
    ## The bug
    
    `DeveloperServicesAssignAppGroupsOperation` sends one
    `assignApplicationGroupToAppId` request per app group, concurrently.
    That endpoint replaces the App ID's groups with the ones in the request,
    so an app whose entitlements list two or more groups ends up with only
    one of them on the App ID: whichever request Apple handles last. The
    provisioning profile then carries one group while the signed binary
    claims two, and the device refuses the install with
    `ApplicationVerificationFailed`.
    
    Setting the groups by hand in the developer portal does not help,
    because the next `xtool dev build --sign` sends the per-group requests
    again.
    
    ## The fix
    
    - `DeveloperServicesAssignAppGroupRequest` takes `groupIDs:
    [DeveloperServicesAppGroup.ID]` and sends `applicationGroups` as an
    array. The endpoint accepts an array; it was being given a single string
    before.
    - `DeveloperServicesAssignAppGroupsOperation.perform()` still finds or
    creates each group concurrently, then sends a single assign request
    carrying every group ID, and returns the group IDs in the order the
    entitlements listed them, so the rewritten entitlement is stable between
    builds.
    
    The only caller, `DeveloperServicesAddAppOperation`, is unchanged.
    
    ## Related
    
    #324 would report the resulting mismatch between the entitlements and
    the profile as a clear error at signing time; this change removes the
    cause, so an app with several groups gets a profile that grants all of
    them.
    
    ## Checked
    
    Built on Linux with the Swift 6.4 toolchain and used to sign an iOS app
    whose main target has two app groups and a Share extension. The app's
    `embedded.mobileprovision` now carries both groups and the device
    installs the app. The same app signed with the unpatched build got one
    group in the profile and `ApplicationVerificationFailed` on install.
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    https://claude.ai/code/session_01UKzxgxaLwK7Ap5LMwj9MxH
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **New Features**
    * Apps can now be assigned multiple app groups in a single operation.
    The assignment replaces the app’s existing group associations with the
    selected groups, so any groups not included in the new assignment are no
    longer associated with the app.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    ---------
    
    Co-authored-by: David Reinecke <david.reinecke@gmail.com>
    Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
    Co-authored-by: Kabir Oberai <oberai.kabir@gmail.com>
  • xcode: track paths on XcodeProject (#388)
    ## What does this PR do?
    
    An XcodeProject/XcodeWorkspace now knows its own location on disk, which
    is important when we start using these types to build PIF.
    
    ## How was it tested?
    
    - [x] Used in future PRs to build various Xcode projects
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Improvements**
    * Projects and workspaces now retain their associated locations and save
    directly to those locations.
    * Generated project files preserve the configured project directory
    path, helping keep file references consistent when projects are written
    or reopened.
    * Projects and workspaces can be associated with a new location while
    retaining their existing contents.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • utils: better XToolCache location (#409)
    ## What does this PR do?
    
    Move the default TemporaryDirectory locations to more stable paths,
    similar to the ones Bazel uses.
    
    - on macOS we now default to `\(URL.cachesDirectory)/sh.xtool` (usually
    `~/Library/Caches/sh.xtool`)
    - on Linux we (continue to) default to
    `${XDG_CACHE_HOME:-~/.cache}/xtool`
    - we no longer respect `$TMPDIR`. One can still use `$XTL_TMPDIR` to
    override.
    
    ## How was it tested?
    
    - [x] Cache directory locations are as expected
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
    * Temporary-directory selection now ignores empty `XTL_TMPDIR` values
    and no longer falls back to `TMPDIR`.
    * Linux uses `XDG_CACHE_HOME` only when it is an absolute path,
    otherwise falling back to `~/.cache`.
    * **Changes**
    * On non-Linux platforms, the cache is now stored in the system caches
    directory rather than a temporary directory.
    * **Documentation**
      * Updated the documented temporary-directory settings.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • utils: tweaks (#387)
    ## What does this PR do?
    
    Small utils refactors to make subsequent PRs cleaner.
    
    - Minor tweaks to how we determine / handle the xtool build version
    - Factor out TemporaryDirectory cache location
    
    ## How was it tested?
    
    - [x] Cache directory logic is unchanged
    - [x] Checked `xtool --version`
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **New Features**
    * Version information now distinguishes clean builds from builds with
    uncommitted changes, displaying a `-dirty` suffix when applicable.
    * Nonblocking file-locking operations are now available to external
    consumers.
    * **Changes**
    * Version reporting uses `XTOOL_VERSION` when set; otherwise, it uses
    available Git tag or commit information.
    * Temporary files now use the tool’s cache directory, honoring
    `XTL_TMPDIR` and platform cache settings. On Linux, the location follows
    `XDG_CACHE_HOME` when it is an absolute path; otherwise, the user cache
    directory is used.
      * `TMPDIR` is no longer used to select the temporary-file location.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • cli: better IO (#375)
    ## What does this PR do?
    
    Adds `Dependency`s for console IO. Also fixes #268 by explicitly
    handling non-pipe input.
    
    ## How was it tested?
    
    Ran on macOS + Linux in Docker. I have a future PR that overrides the
    dependencies in certain cases, which also appears to work correctly.
    
    ## 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
    
    Did not scrutinize the tests too much tbh but they look reasonable. Easy
    enough to update/remove them in the future if needed.
    
    <!-- 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
    
    * **New Features**
    * Added support for reading command-line input, including asynchronous
    prompts, line-based responses, and graceful handling of end-of-input.
      * Added coordinated cleanup when commands finish.
    * **Improvements**
    * Command messages across authentication, device management,
    installation, SDK, and other workflows now use consistent output
    handling; displayed messages and command behavior remain unchanged.
    * Improved handling of complete output when the system temporarily
    cannot accept more data.
    * **Tests**
    * Added coverage for command input and output, including stream
    behavior, cancellation, and shutdown.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • gsa: update user agent (#406)
    ## What does this PR do?
    
    Fixes the latest source of HTTP 503s during Apple ID login
    
    ## How was it tested?
    
    - [x] `xtool auth login`
    
    ## 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
    -->
    
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Improvements**
    * Requests now use the user-agent value provided with device
    information, rather than a fixed value.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • pack: link edited dependencies into the builder package (#390)
    ## What does this PR do?
    
    SwiftPM looks for edited dependencies in the root package's Packages
    directory. The builder package becomes the root when building, so
    dependencies edited with `swift package edit` were ignored and SwiftPM
    fetched them again instead.
    
    <!-- Focus on *what* the PR does in essence. The *how* should come
    second, if it's relevant. -->
    
    ## How was it tested?
    
    Without this change, the build of `xtool/.xtool-tmp` tries to clone all
    15 dependencies and fails.
    
    * With `Packages` linked into `.xtool-tmp`, it builds without fetching
    anything and produces `DemoTCA.app`
    * `Examples/DemoSimple`, which has no `Packages` directory, still builds
    * `swift test` passes
    
    <!-- e.g. Ran locally on macOS and added unit tests -->
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Build Improvements**
    * Builds now include access to the working directory’s `Packages` folder
    when it exists. If the folder is absent, builds proceed without it. This
    can make packages in that folder available during the build.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    Signed-off-by: Anish Pallati <i@anish.land>
  • deps: force OpenCombine in the DemoTCA lockfile (#391)
    ## What does this PR do?
    
    Applies the workaround from #288 to `Examples/DemoTCA`
    
    ## How was it tested?
    
    Ran `swift package resolve` in `Examples/DemoTCA` on Linux
    
    ## 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. -->
    
    Signed-off-by: Anish Pallati <i@anish.land>
  • sdk: accept directories for tarball overrides (#385)
    ## What does this PR do?
    
    XTL_TOOLSET_TARBALL and XTL_OAM_TARBALL can now point at an unpacked
    directory, so package managers can use tools they already provide
    without repacking them into tarballs.
    
    <!-- Focus on *what* the PR does in essence. The *how* should come
    second, if it's relevant. -->
    
    ## How was it tested?
    
    Tested on Linux with Swift 6.2.4: 
    * `xtool sdk build` with both overrides set to directories in the Nix
    store
    * `xtool dev` flags the SDK as out of date after an override path
    changes
    
    <!-- e.g. Ran locally on macOS and added unit tests -->
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **New Features**
    * SDK setup now accepts a directory as a package source, recursively
    copying its contents and adding owner write permission.
    * Archive files continue to be supported as package sources and are
    extracted as before.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    Signed-off-by: Anish Pallati <i@anish.land>
  • entitlements: support Sign in with Apple (#377)
    ## What does this PR do?
    
    Hi! xtool didn't know about the `com.apple.developer.applesignin`
    entitlement, so every time I installed my app, the capability sync
    removed Sign in with Apple from the App ID. The new provisioning profile
    didn't have it, and the device refused the app ("A valid provisioning
    profile for this executable was not found").
    
    This maps the entitlement to the `APPLE_ID_AUTH` capability, as a
    primary App ID, so the capability stays and the profile includes it.
    
    ## How was it tested?
    
    I built xtool from this branch on macOS and installed my app (a SwiftPM
    app with `entitlementsPath` and the Sign in with Apple entitlement) on
    an iPhone with a paid team. The App ID kept the capability, the install
    worked, and native Sign in with Apple works in the app. Before the
    change the same install failed every time.
    
    ## 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
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **New Features**
      * Added support for configuring the Apple Sign In entitlement.
    * Apple Sign In is now available as a supported entitlement type,
    including serialization and configuration support.
      * Configures Apple ID app consent as the primary app consent option.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • build: update to Xcode 27.1, Swift 6.4.1 (#382)
    ## What does this PR do?
    
    Updates the Xcode and Swift versions used to build xtool on macOS/Linux
    respectively
    
    ## How was it tested?
    
    CI
    
    ## 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
    -->
    
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    - **Updates**
    - Updated the Xcode version used by the build action to 27.1.0 and the
    Swift version used in build environments to 6.4.1.
    - **Documentation**
    - Updated the Linux installation guide to reference Xcode 27.1 and the
    matching `Xcode_27.1.xip` download filename. These updates align the
    documented installation steps with the current tool versions.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • deps: bump dependencies (#381)
    ## What does this PR do?
    
    Updates dependencies, including xtool-core 1.5.1. Un-restricts
    swift-collections (see the removed comment) and Yams (which was pinned
    to 5.x by XcodeProj, which we no longer use).
    
    ## How was it tested?
    
    - [x] `xtool --help` runs on macOS
    - [x] Can build `Examples/DemoSimple`
    - [x] Can run `xtool ds certificates`
    
    ## 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
    -->
    
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Chores**
    * Updated the project’s underlying package version requirements. These
    maintenance changes do not add or remove user-facing features, and no
    changes to the app’s visible behavior are noted.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • gsa: use macOS Omnisette (#380)
    ## What does this PR do?
    
    Fixes #378, solving error -80046. Seems Apple now blocks
    Android-identifying clients from using gsa (at least the 2fa bits). Use
    Mac Anisette instead. cf
    https://github.com/nab138/iloader/commit/902597564315442f00ab299dcc758ee0e13b8fa8
    
    Alas, this does mean we have to retire xadi and switch back to
    Omnisette.
    
    ## How was it tested?
    
    - [x] Ran locally on macOS
    
    ## 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
    -->
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
      * Two-factor requests now use the device’s configured User-Agent.
    * **Updates**
    * Anisette requests now use the Omnisette provider and a new default
    server. The optional server URL override remains available.
    * The password-login warning now explains the virtual Mac and
    third-party service involved, clarifies that credentials are sent only
    to Apple, and recommends considering a secondary Apple ID.
    * **Behavior Changes**
      * The Android-specific ADI provider is no longer available.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • sdk: support env overrides for tarballs (#372)
    ## What does this PR do?
    
    When building the sdk, allows you to set
    `XTL_TOOLSET_TARBALL`/`XTL_OAM_TARBALL` to use local tarballs instead of
    fetching them remotely. Supersedes
    https://github.com/xtool-org/xtool/pull/319.
    
    ## How was it tested?
    
    Honestly didn't bother but I think it works. Fairly safe to land.
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    ## Summary by CodeRabbit
    
    - **New Features**
    - Added support for installing the Toolset and OpenAppleMacros from
    locally provided tarball files.
    - Existing HTTP download behavior remains available when local tarballs
    are not configured.
    
    - **Chores**
      - Improved handling of lengthy installation logic.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    Co-authored-by: Mathieu Post <mathieupost@gmail.com>
  • sdk: update OpenAppleMacros to v1.4.1 (#371)
    ## What does this PR do?
    
    Updates OpenAppleMacros to v1.4.1. It now includes an info.json that
    lists supported modules, so we don't need to hardcode them.
    
    ## How was it tested?
    
    Built a project that uses `@State` on Linux
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    ## Summary by CodeRabbit
    
    - **New Features**
    - Updated the DemoSimple example with a SwiftUI app window, interactive
    counter, and button-based incrementing.
    - The example now runs its demonstration action when the content view
    loads.
    
    - **Bug Fixes**
    - Improved SDK component downloads with clearer progress reporting and
    validation.
    - Improved plugin setup across supported platforms for more consistent
    availability.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • gsa: fall back to a trusted-device code when SMS 2FA fails (#349)
    `secondaryAuth` can't finish logging in: GSA rejects POST
    /auth/verify/phone/put?mode=sms with HTTP 403 ("Could not connect to
    iCloud"). The JSON flavor of those endpoints (GET /auth, PUT
    /auth/verify/phone/) answers 401 as well.
    
    GsService2/validate still accepts a code generated on a trusted device
    (Settings > Sign-In & Security > Get Verification Code), so ask for one
    instead of failing. Tested on WSL (Ubuntu 26.04) with an iOS 27 device.
    
    ## What does this PR do?
    
    <!-- Focus on *what* the PR does in essence. The *how* should come
    second, if it's relevant. -->
    
    ## How was it tested?
    
    <!-- e.g. Ran locally on macOS and added unit tests -->
    
    ## AI tool usage
    
    How much of this PR was AI-assisted? (check one)
    
    - [ ] **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**
    * Two-factor authentication can fall back to a trusted device when an
    SMS request returns HTTP 403.
    * If trusted-device authentication also returns HTTP 403, users receive
    instructions for manually generating a verification code, and code
    validation can continue. Other errors are still reported.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    ---------
    
    Co-authored-by: Kabir Oberai <oberai.kabir@gmail.com>
  • auth: clean up Anisette handling (#367)
    ## What does this PR do?
    
    Simplifies the Anisette handling code. Removes some unnecessary fields
    (including hard-coded Mac serial numbers, cf #348) from our http
    requests amongst other things.
    
    ## How was it tested?
    
    Tested on macOS:
    
    - [x] Can log in after resetting provisioning
    - [x] Can run `xtool ds teams`
    - [x] Can run `xtool ds certificates`
    
    ## 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
    
    * **Updates**
    * Anisette-backed requests now use device information provided with
    Anisette data, including an Android 14 device identity.
    * Developer service requests no longer include client-information and
    device-ID headers.
    * The Anisette command now displays fetched details in sorted order and
    uses the configured Anisette provider instead of prompting for
    provisioning data.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • sdk: fix cross-import overlays with SwiftBuild (#361)
    ## What does this PR do?
    
    Fixes #360 cross-import overlays on Linux for builds with swift 6.4+. 
    
    This PR adds "-Xfrontend", "-enable-cross-import-overlays" to
    `toolchan-swb.json` as it was added to `toolchan.json`.
    Also bumps sdkEpoch so SDK will rebuild after update.
    
    ## How was it tested?
    
    Build was tested locally with branch built from sources.
    
    `xtool new example`, then replace the app file
    
    Fix was tested on this example:
    ```Swift
    import SwiftUI
    import PhotosUI
    
    @main
    struct exampleApp: App {
        @State private var item: PhotosPickerItem?
    
        var body: some Scene {
            WindowGroup {
                PhotosPicker("Pick a photo", selection: $item)
            }
        }
    }
    ```
    
    It fails on version 1.22.2, but builds normally when xtool built from
    this branch.
    
    ## 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
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    ## Summary by CodeRabbit
    
    * **Configuration Updates**
    * Generated Swift toolchain settings no longer explicitly select the LLD
    linker. Existing frontend and cross-import overlay options remain
    unchanged. This affects linker selection for generated toolsets; no
    public API changes are included.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • certs: match certificates whose serial starts with 0 (#306)
    ## What does this PR do?
    
    Fixes #305 (thanks @0x53 for the detailed diagnosis).
    
    `Certificate.serialNumber()` stripped leading `0` *characters* from the
    hex string, so a serial like `0337…` became `337…` and never matched the
    `serialNumber` returned by the API. xtool then treated its stored
    certificate as missing: free teams are prompted to revoke a valid
    certificate on every run, and paid teams take the same path and try to
    create another certificate, which @McoreD confirmed fails with `409 …
    You already have a current Development certificate or a pending
    certificate request.`
    
    The character-level `drop` predates b6a40ca, which switched to
    fixed-width `%02hhX` formatting; since then it removes the significant
    zero of any first byte below `0x10`. swift-certificates already strips
    leading zero bytes (including DER sign padding) when parsing, so the
    `drop` isn't needed for padding.
    
    - `serialNumber()` now drops only leading zero *bytes*, matching the API
    and `openssl x509 -serial`.
    - The stored-certificate lookup uses a new
    `Certificate.hasSerialNumber(_:)`, which compares serials numerically
    (ignoring case and leading zeros), so it doesn't depend on Apple's exact
    formatting.
    - Profile creation no longer finds the signing certificate with
    `filter[serialNumber]`. The API lists serials with the leading zero
    (`0E41…`), but the filter only matches them without it (`E41…`), so once
    `serialNumber()` kept the zero the filter matched nothing and profile
    creation failed with a 409
    ([details](https://github.com/xtool-org/xtool/pull/306#issuecomment-6181157860)).
    It now fetches all pages of certificates and matches them with
    `hasSerialNumber(_:)`. Fix by @McoreD, with pagination added so a
    certificate on a later page isn't missed.
    
    ## How was it tested?
    
    - Added `Tests/XToolTests/CertificateTests.swift`: builds a cert with
    the serial from #305, round-trips it through DER, and checks
    `serialNumber()` and `hasSerialNumber(_:)`, plus a high-bit serial so
    DER sign padding doesn't leak into the string. The leading-zero test
    fails on `main` (returns `33742570D6F9684A23311711956A084`) and passes
    with this change.
    - `swift test` (17 tests) and `make lint` pass on macOS (Xcode 27, Swift
    6.4, `XTL_CI=1`).
    - @McoreD tested on Linux (Arch, Swift 6.4.1, Xcode 27 SDK, on top of
    1.22.2) with a paid team whose certificate serial starts with `0`: the
    stored certificate is reused, and provisioning, signing and install to
    an iPhone (iOS 27) succeed end to end (tested before pagination was
    added). `CertificateTests` also pass on Linux.
    - Not tested with a free team.
    
    To generate test certificates, the test target now depends on `Crypto`
    and `X509`, which XKit already uses.
    
    ## 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
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
    * Certificate serial numbers now preserve leading zero nibbles while
    omitting unnecessary padding.
    * Certificate matching now ignores letter case and leading zeros, and
    profile lookups find matching certificates even when the API’s
    serial-number filter treats leading-zero values differently.
    * Certificate lookups continue to use the existing fallback when no
    matching certificate is found.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    ---------
    
    Co-authored-by: McoreD <McoreD@users.noreply.github.com>
    Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
  • fix: strip trailing carriage return in console prompt on crlf terminals (#328)
    ### Summary
    In `Console.prompt`, incoming line input from standard input is split on
    `\n` without stripping any preceding carriage return (`\r`). On Windows
    environments or CRLF terminals, user input terminates with `\r\n`,
    leaving a trailing `\r` on decoded input strings.
    
    When downstream helper methods such as `Console.chooseNumber` attempt to
    parse numerical selections using `Int(prompt(...))`, the trailing `\r`
    (e.g., `"1\r"`) causes the conversion to return `nil`, trapping the
    terminal in an infinite prompt loop.
    
    ### Changes
    - In `Console.prompt` (`Sources/XToolSupport/Console.swift`), stripped
    any trailing `\r` from the decoded string before returning.
    - Verified that all interactive helper methods (`promptRequired`,
    `getPassword`, `chooseNumber`, `choose`, and `confirm`) delegate their
    standard input reading to `Console.prompt`, ensuring all input paths are
    protected against CRLF leakages.
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
    * Console input no longer includes a trailing carriage return; all other
    input remains unchanged.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • http: add newer Apple Root CAs (#340)
    ## 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 -->
  • build: fix xcodegen install (#338)
    ## What does this PR do?
    
    Fix CI maybe
    
    ## How was it tested?
    
    Praying for the best
    
    ## 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. -->
  • gsa: fix login using mismatched client-info (#337)
    ## What does this PR do?
    
    Fixes #329 (error `-80045` on gsa login).
    
    We were sending client info generated from Android Anisette, but
    claiming to be a Mac. Seems like GrandSlam no longer likes this
    mismatch.
    
    ## How was it tested?
    
    - [x] Run `xtool ds certificates` after updating -> logged out,
    provisioning reset
    - [x] Re-auth works
    
    ## 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
    
    * **Updates**
    * Authentication now identifies the client as a Pixel 7 running Android
    14 rather than using a macOS-style client description.
    * The provider ID is now consistent across platforms. Existing
    provisioning may be reset if its saved provider ID differs.
    * Before password login, a notice explains the emulated device and
    environment, recommends considering a secondary Apple ID, and says
    credentials are sent only to Apple.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • packer: custom SwiftVersion parser (#303)
    ## What does this PR do?
    
    Drops `mxcl/Version` in favour of a lighter parser that's specifically
    designed to parse the Swift version.
    
    ## How was it tested?
    
    - [x] Unit tests
    - [x] CI
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    ## Summary by CodeRabbit
    
    * **New Features**
    * Swift versions can now be compared by major, minor, and patch number,
    and displayed in a consistent three-part format.
    * Version parsing now accepts two- or three-number versions, including
    supported compiler-output formats with optional prefixes or a `-dev`
    suffix.
    * Versions with an omitted patch number are treated as equivalent to the
    same version with patch `0`.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • tests: add example project fixtures (#301)
    ## What does this PR do?
    
    Adds integration tests in the form of example apps that we can build and
    run.
    
    ## How was it tested?
    
    Ran builds on Linux, tests on macOS. Will also add this to CI later.
    
    ## 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. -->
  • packer: use XcodeProjectFormat for generate-xcode-project (#300)
    ## What does this PR do?
    
    Improves `xtool dev generate-xcode-project`. Instead of constructing an
    XcodeGen project, we directly construct an xcodeproj (with the new
    xcproj format) using
    [apple/xcode-project-format](https://github.com/apple/xcode-project-format).
    For now, we still rely on
    [Tuist/XcodeProj](https://github.com/tuist/XcodeProj) to translate it
    back into a pbxproj for maximal compatibility, but this is treated as an
    implementation detail.
    
    Also adds support for resources and icons in the generated Xcode project
    
    ## How was it tested?
    
    - [x] Generated a simple project, opened it, and ran the app
    
    ## 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. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    ## Summary by CodeRabbit
    
    * **New Features**
    * Added support for creating and saving Xcode projects and workspaces in
    `.pbxproj` and `.xcproj` formats.
    * Added tools for opening, converting, and writing project and workspace
    files, including workspace contents.
    * Project generation can target a specified directory, and the command
    reports where the project was created.
      * Project generation is available on non-macOS platforms.
    * Generated projects include product settings and references for
    packages, resources, icons, and app extensions.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • planner: skip macro targets (#208)
    Currently, when using a package with macros like TCA the build fails
    with the following message.
    ```
    Error: Could not find package containing product 'SwiftSyntaxMacros'
    ```
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
    * Package planning now skips macro targets when collecting resources and
    resolving dependencies. This prevents dependencies belonging to macro
    targets from being traversed as part of planning, while leaving
    dependency handling for other target types unchanged.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    Co-authored-by: Kabir Oberai <oberai.kabir@gmail.com>
  • deps: update swiftlint (#299)
    ## What does this PR do?
    
    Updates SwiftLint to v0.65.1
    
    ## How was it tested?
    
    CI
    
    ## 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
    
    * **Chores**
    * Removed inactive legacy networking implementations; active app
    behavior and user-facing capabilities are unchanged.
    * Updated the configured SwiftLint version and improved selection of its
    Linux download for supported processor architectures. macOS continues to
    use its existing download.
    * No changes to app features or user workflows are included in this
    update.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • deps: bump xadi to 0.4.2 (#298)
    ## What does this PR do?
    
    Updates xadi for https://github.com/NixOS/nixpkgs/pull/548520
    
    ## How was it tested?
    
    - [ ] CI
    
    ## 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. -->
  • build: compile xtool with Swift 6.4 (#272)
    ## What does this PR do?
    
    Updates workflows to build with Swift 6.4. Blockers:
    
    - [x] ~~GitHub's macos-26 runners don't yet support Xcode 27~~ They've
    moved to a new nomenclature where the runner tracks the Xcode major
    version. The new runner is `xcode-27`.
    - [x] ~~Linux AppImage builds are failing due to
    https://github.com/swiftlang/swift-build/issues/1764 (will be fixed in
    6.4.1)~~ Switched to dynamic linking
    
    ## How was it tested?
    
    - [x] Built locally with Xcode 27 and confirmed it runs
    - [x] Built locally with `swift:6.4.0` docker image and confirmed it
    runs
    
    ## 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 swiftlang/swift-package-manager#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
    
    * **Build & Release**
      * macOS and iOS builds and macOS releases now use Xcode 27.
    * Swift has been updated to version 6.4.0 for Docker and Netlify builds.
    
    * **Bug Fixes**
    * Linux packaging no longer copies `.resources` files into the AppDir,
    which may affect packaged app resources.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • build: link xtool dynamically inside AppImage (#296)
    ## What does this PR do?
    
    We don't really need `--static-swift-stdlib` when building the AppImage,
    since we can bundle the stdlib.
    
    Static linking _can_ theoretically save space & squeeze out a little
    more perf, but statically linking Swift is buggy (for example
    https://github.com/swiftlang/swift-build/issues/1764 wasn't caught until
    days after 6.4.0 released, and months after the beta) and prevents using
    dynamic Swift libraries.
    
    ## How was it tested?
    
    - [x] Ran appimage in docker
    - [x] Verified that the appimage contains `libswift[...].so`
    - [x] Compared size on disk (<1MB increase)
    - [x] Compared performance (no statistically significant change)
    
    ## 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. -->
  • tests: derive CFBundleSupportedPlatforms from the build triple (#289)
    ## What does this PR do?
    
    Application packing now sets CFBundleSupportedPlatforms from
    Packer.cfBundleSupportedPlatforms(for:). The helper splits the triple on
    hyphens, takes the OS token after apple with any numeric version
    stripped, and returns iPhoneSimulator for an ios triple that also
    contains simulator, iPhoneOS for other ios triples, MacOSX for macos or
    macosx, and iPhoneOS when the triple is missing or unrecognized.
    PackerTests covers those triples. Package.resolved drops the
    swift-issue-reporting pin and adds xctest-dynamic-overlay 1.13.1.
    
    Application builds aimed at the iOS simulator still ship an Info.plist
    whose CFBundleSupportedPlatforms value is iPhoneOS. Hosts that read that
    key treat the archive as a physical-device build and refuse to launch it
    on a simulator. While packing an application, Packer assigns
    CFBundleSupportedPlatforms the fixed array iPhoneOS. The build triple is
    already available on buildSettings, but that assignment never reads it,
    so a simulator triple is packed the same way as a device triple.
    
    Fixes #191
    
    ## How was it tested?
    
    The package builds successfully.
    
    ## AI tool usage
    
    How much of this PR was AI-assisted? (check one)
    
    - [ ] **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
    
    AI was used for assistance.
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
    * Application metadata now reports the supported platform based on the
    build target, including iOS devices, iOS simulators, and macOS. Unknown
    targets retain the iOS device platform as a fallback.
    * **Tests**
    * Added coverage for platform metadata across supported and unknown
    build targets.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
  • deps: force OpenCombine in the lockfile (#288)
    ## What does this PR do?
    
    Fixes https://github.com/xtool-org/xtool/issues/286 (Package.resolved
    changes depending on host OS) by forcing OpenCombine into the dependency
    graph even on macOS.
    
    ## How was it tested?
    
    Ran `swift package resolve`
    
    ## 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
    
    * **Chores**
    * Updated package resolution configuration. This change does not alter
    app features or user-facing behavior.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • build: use SwiftBuild for xtool workspace LSP (#282)
    ## What does this PR do?
    
    Configure SourceKit-LSP to use SwiftBuild when working on xtool itself.
    The legacy build system has trouble with xcframeworks.
    
    ## How was it tested?
    
    Confirmed that it fixes highlighting of error diagnostics
    
    ## 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. -->
  • package: bump deps (#281)
    ## What does this PR do?
    
    Bumps pointfree deps and explicitly disables OpenCombine so that we
    don't have different dependency graphs when building xtool on Darwin vs
    Linux hosts.
    
    ## How was it tested?
    
    A bunch of `swift package resolve`s
    
    ## 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
    
    * **Chores**
    * Updated supporting package versions and refreshed command-line and
    file-operation handling.
    * These changes do not add or remove app features or alter its public
    interface. No action is needed to continue using the app.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • sdk: prune Xcode when installing from xip (#280)
    ## What does this PR do?
    
    We only need `Xcode.app/Contents/{Info.plist,version.plist,Developer}`
    for the SDK (and expect that to continue being the case). We already
    delete other directories when using `xtool sdk install Xcode.app` but we
    weren't doing this on `xtool sdk install Xcode.xip`. Prune on the xip
    path as well.
    
    Also prune on update (and bump the SDK epoch) so that existing users
    benefit from this.
    
    ## How was it tested?
    
    - [x] Install SDK from xip, confirm `Xcode.app/Contents` only contains
    those three things
    - [x] Install SDK from app, confirm `Xcode.app/Contents` only contains
    those three things + we don't modify the original app
    - [x] Build SDK from app (`xtool sdk build Xcode.app`), confirm we don't
    clobber the input Xcode app
    - [x] Update SDK, confirm that extra contents are removed
    - [x] SDK auto-updates after updating xtool binary
    
    ## 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**
    * SDK builds from Xcode app and XIP inputs now check for required Xcode
    components before installation. Missing components produce an error.
    * Extra direct items in Xcode’s `Contents` folder are removed during XIP
    builds and app updates. Slim builds remain unchanged.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • package: bump Darwin deployment targets to Fall2023 (#277)
    ## What does this PR do?
    
    Bumps Darwin deployment targets.
    
    In order to better integrate with SwiftBuild we need to pull in
    swift-tools-protocols which
    [requires](https://github.com/swiftlang/swift-tools-protocols/blob/4345e69c5572ec3d1f737fba90bca024b32da5cf/Package.swift#L210)
    macOS 14 / iOS 17.
    
    ## How was it tested?
    
    - [x] CI
    - [x] Did a local smoke test to ensure `xtool` still runs
    
    ## 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
    
    * **Chores**
      * Updated minimum supported versions to iOS 17 and macOS 14.
      * macOS project configuration now requires macOS 14 or later.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • fastlane: update Ruby and gems (#278)
    ## What does this PR do?
    
    Updates Ruby and gems
    
    ## How was it tested?
    
    - [x] `bundle exec fastlane package`
    
    ## 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
    
    - **Chores**
    - Updated the macOS environment to use Ruby 4.0.7, keeping local
    development and maintenance workflows aligned with the supported runtime
    version.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • zsign: update to v1.9.0 (#271)
    ## What does this PR do?
    
    Updates to zsign 1.9.0 which incorporates the latest upstream changes
    
    ## How was it tested?
    
    Built and ran an app on my phone
    
    ## 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. -->
  • docker: add SWIFT_VERSION arg (#276)
    ## What does this PR do?
    
    Adds a `SWIFT_VERSION` arg to the Dockerfile
    
    ## How was it tested?
    
    Ran on macOS
    
    ## 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
    
    * **Chores**
    * Updated the build and runtime environments to use Swift 6.3.3
    consistently.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->