Skip to content

Assign all of an app's groups to its App ID in one request - #403

Open
dreinecke wants to merge 1 commit into
xtool-org:mainfrom
dreinecke:app-groups-in-one-request
Open

dreinecke wants to merge 1 commit into
xtool-org:mainfrom
dreinecke:app-groups-in-one-request

Conversation

@dreinecke

@dreinecke dreinecke commented Oct 25, 2026 •

Copy link
Copy Markdown

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.ai/code/session_01UKzxgxaLwK7Ap5LMwj9MxH

… request

assignApplicationGroupToAppId replaces the App ID's groups with the ones in the request, and
DeveloperServicesAssignAppGroupsOperation sent one request per group, concurrently. An app whose
entitlements name two groups therefore ended with one group in its profile (whichever request
Apple handled last), and the device refused to install it (ApplicationVerificationFailed).

The operation now creates any missing groups as before, then sends a single 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.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UKzxgxaLwK7Ap5LMwj9MxH
@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 0cbec3b7-9ec5-49c7-930e-8cb113c887c8
Commits

Reviewing files that changed from the base of the PR and between 7f7d5b7 and 49b17bc.

Files selected for processing: 2
  • Sources/XKit/DeveloperServices/App Groups/DeveloperServicesAssignAppGroupRequest.swift
  • Sources/XKit/DeveloperServices/App Groups/DeveloperServicesAssignAppGroupsOperation.swift

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

The assignment request now accepts multiple app-group IDs. The operation upserts the requested groups, restores their input order, assigns them in one request when nonempty, and returns their IDs in that order.

Changes: App-group assignment

Layer / File(s) Summary
Multi-group assignment request
Sources/XKit/DeveloperServices/App Groups/DeveloperServicesAssignAppGroupRequest.swift
The request accepts an array of app-group IDs and documents that each assignment replaces the App ID’s existing groups.
Ordered upsert and assignment
Sources/XKit/DeveloperServices/App Groups/DeveloperServicesAssignAppGroupsOperation.swift
The operation upserts groups, restores input order, sends one assignment request when the result is nonempty, and returns the IDs in that order.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: kabiroberai

Merge Risk: Minimal · up to 49b17

No actionable merge-blocking issue was established. The change is ready for normal merge checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the primary change: assigning all of an app's groups to its App ID in one request.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant