ionic-team / ionic-team/capacitor
[Bug]: capacitor-swift-pm has no Mac Catalyst slice, so Catalyst apps must self-build and are then rejected with ITMS-91065
- Dominant language
- TypeScript
- Stars
- 16.7k
- Forks
- 1.3k
- Avg merge
- 3d 15h
- Merged PRs (30d)
- 10
Description
### Capacitor Version
Capacitor 8.4.1 (@capacitor/ios, @capacitor/core, @capacitor/cli)
capacitor-swift-pm 8.4.1 (2231987d85b8b0b289320b1d0947b4ae8345cde4)
### Other API Details
```Shell
Xcode 26.6 (17F113)
macOS (build host) 26.5.2 (25F84) release build, not a beta
macOS SDK 26.5 (25F70)
iOS SDK 26.5 (23F81a)
Mac Catalyst target MACCATALYST minos 17.0, LSMinimumSystemVersion 14.0
iOS target MinimumOSVersion 17.0
```
### Platforms Affected
- [x] iOS
- [ ] Android
- [ ] Web
### Current Behavior
`capacitor-swift-pm` ships `ios-arm64` and `ios-arm64_x86_64-simulator` only. There is no `ios-arm64-maccatalyst` slice, so a Mac Catalyst target cannot link the official binary and has to build Capacitor and Cordova from source. The resulting frameworks carry no Drifty Co signature, and Apple rejects the macOS submission with **ITMS-91065** for both frameworks.
The same app's **iOS** build, same Capacitor version, same dependency, passes. So this is not a project misconfiguration — it is a direct consequence of the missing slice.
Related but distinct: #8537 hits ITMS-91065 after self-rebuilding to escape a stale SDK. We have no stale-SDK problem; we self-build **only** because there is no Catalyst slice to link. We are also not on a macOS beta — build machine is macOS 26.5.2 (25F84), a release build.
### Slices, 8.4.1 and 8.5.2
```
Capacitor.xcframework/_CodeSignature/
Capacitor.xcframework/ios-arm64/
Capacitor.xcframework/ios-arm64_x86_64-simulator/
```
Checked 8.4.1 (in use) and the published 8.5.2 zip. No Catalyst slice in either.
### The controlled comparison
One app, one Capacitor version (8.4.1), two platforms. Both embed the frameworks identically — dynamic frameworks in `Frameworks/`, linked `@rpath` — so bundle structure is not the variable. The only difference is which binary is embedded:
```
PASSES on iOS
official ios-arm64 slice LC_UUID 13CCF5B7-219A-3563-8309-544DA1541DEB
iOS app's embedded Capacitor LC_UUID 13CCF5B7-219A-3563-8309-544DA1541DEB
REJECTED ITMS-91065 on macOS
our Catalyst build LC_UUID D3E3FCF4-C979-38AA-ACB8-0D6D90EF7B65
Mac app's embedded Capacitor LC_UUID D3E3FCF4-C979-38AA-ACB8-0D6D90EF7B65
```
Your signature is at the xcframework level, `Developer ID Application: Drifty Co. (9YN2HU59K8)`. Our locally-assembled xcframework has none — `code object is not signed at all`.
### The part we think is diagnostic
**Your signature does not reach the shipped app bundle on iOS either.** Xcode re-signs embedded frameworks on the way in, so in our passing iOS archive:
```
App.app/Frameworks/Capacitor.framework
Authority = Apple Development:
TeamIdentifier =
grep -rl "Drifty\|9YN2HU59K8" App.app -> 0 hits
```
So whatever App Store validation matches on, **it is not a vendor signature read out of the submitted bundle** — there isn't one there in the passing case. That implies it keys on the binary itself (hash/identity of your published build) rather than on anything a developer can add locally. If that is right, no amount of local signing can fix a self-built slice, and the missing Catalyst slice is the only thing that can be fixed.
Both frameworks do carry `PrivacyInfo.xcprivacy`, byte-identical to yours, so the privacy manifest is not the issue.
### Expected Behavior
`capacitor-swift-pm` ships an `ios-arm64-maccatalyst` slice in the signed xcframeworks, so a Mac Catalyst target can link the official Drifty-signed binary rather than building from source — and the resulting app passes App Store validation the way the iOS build already does.
### Project Reproduction
Not reproducible from a sample repo — this is a packaging gap, not runtime behaviour. Reproduce by adding a Mac Catalyst target to any Capacitor app: the official xcframework has no Catalyst slice to link.
### Additional Information
Two questions:
1. Is a `ios-arm64-maccatalyst` slice planned for the signed xcframeworks? The Catalyst request (#5855) was closed some time ago, but the signature requirement gives it a new consequence: without a slice, Catalyst apps cannot ship to the Mac App Store at all.
2. Do you know what the validator keys on? If it is the published binary's identity rather than a signature in the bundle, that determines whether any workaround exists — and would be worth stating publicly, since #8537 and this issue are both people guessing at it.
Contributor guide
Research direction
Start by locating the capacitor-swift-pm xcframework packaging and release configuration that produces the signed Capacitor and Cordova binaries. Verify how existing iOS and simulator slices are built, then determine how an ios-arm64-maccatalyst slice can be included in the signed artifacts; done means a Catalyst app links the official slice and passes App Store validation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ios, swift
- Domain
- build-system, mobile-dev, release
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100