Fix iOS app icon and extension bundle version validation

Declare XSAppIconAssets in the app manifest so actool receives --app-icon
and the bundle carries CFBundleIconName, and always pass both Xcode version
placeholders to the ReplayKit extension so an empty build number cannot
drop CFBundleVersion and fail installd.
This commit is contained in:
2026-09-23 21:36:34 +02:00
parent ea76d5157a
commit 1487f2673b
5 changed files with 94 additions and 15 deletions
+36 -5
View File
@@ -162,8 +162,10 @@ Before packaging, confirm:
- both entitlements contain the shared App Group;
- both have `get-task-allow=false` and `beta-reports-active=true`;
- the bundle identifiers are the stable identifiers above;
- both version pairs match; and
- both executables contain `arm64`.
- both version pairs match;
- both executables contain `arm64`; and
- the host `Info.plist` contains `CFBundleIconName` and the bundle contains both
`AppIcon60x60@2x.png` (120x120) and `AppIcon76x76@2x~ipad.png` (152x152).
Also decode each embedded profile and verify its name, UUID, application identifier, and
`get-task-allow` value:
@@ -232,6 +234,34 @@ Xcode command-line builds can report a missing `Xcode-Token` even when the GUI d
account. Manual App Store Connect profiles avoid that dependency and make the two-target signing
inputs explicit.
### Missing app icon or `CFBundleIconName`
App Store Connect rejects uploads with errors 90022, 90023, and 90713 when the host bundle has
no `CFBundleIconName`. Local `codesign` cannot catch this; only upload validation does.
The asset catalog alone is not enough. `Info.plist` must name it:
```xml
<key>XSAppIconAssets</key><string>Assets.xcassets/AppIcon.appiconset</string>
```
This is an **app-manifest key**, not an MSBuild property. The `ReadAppManifest` task reads
`XSAppIconAssets` out of `Info.plist` and passes `--app-icon` to `actool`; setting a csproj
property of the same name has no effect. The build strips the key from the shipped manifest.
Without it, `actool` still compiles the catalog but emits an empty
`obj/<config>/<tfm>/<rid>/actool/partial-info.plist`, so no icon keys reach the app. Verify the
build inputs rather than the bundle, since stale intermediates can leave icon PNGs from an
earlier build in place while the manifest has no icon keys:
```bash
cat clients/apple/VoiceCat.iOS/obj/Release/net10.0-ios27.0/ios-arm64/actool/partial-info.plist
```
A correct build writes `CFBundleIcons` and `CFBundleIcons~ipad` there. A single 1024x1024
universal entry in `AppIcon.appiconset` is sufficient; `actool` derives the 120x120 and 152x152
variants.
### App and extension versions differ
Apple validates nested bundle metadata. Confirm the host does not hard-code version keys, the
@@ -240,8 +270,9 @@ clean build regenerated the app manifests.
## Last verified release build
On 2026-09-22, version `0.0.1`, build `2026092202` was built with .NET 10.0.401 and Xcode 27.0.
On 2026-09-22, version `0.0.1`, build `2026092203` was built with .NET 10.0.401 and Xcode 27.0.
The host and ReplayKit extension passed strict nested-signature validation with App Store Connect
profiles, matching distribution identities, matching versions, the shared App Group, and
`get-task-allow=false`. The resulting IPA was packaged locally; Apple server-side upload
validation remains a separate gate.
`get-task-allow=false`. The host carries `CFBundleIconName` with the 120x120 and 152x152 icons.
The resulting IPA was packaged locally; Apple server-side upload validation remains a separate
gate.