Sample report
This is what a readiness report looks like. Everything here describes a made-up app.
70 / 100 readiness
- Verified blockers
- 2
- Warnings
- 0
- Manual checks
- 0
- Passed
- 17
The readiness score summarises unresolved findings. It is not a prediction of Apple’s decision.
Checked with ruleset 2026.07.1 · scanner 0.2.0
Blockers 2
NSLocationWhenInUseUsageDescription is declared but empty
A usage-description key is present but its value is empty, whitespace only, or not a string. iOS shows this text in the permission prompt, and an empty value leaves the user with no explanation of why access is being requested. NSLocationWhenInUseUsageDescription (location when in use) is declared but the value is empty or whitespace only.
What to do
Write a specific sentence explaining what the app does with this data, and why the user benefits.
Edit the usage description in the native Info.plist. Capacitor plugin docs list which keys each plugin needs.
Evidence
Declared value type: str.
Payload/Sample.app/Info.plistNSLocationWhenInUseUsageDescription Why this is not a certainty
This checks the keys that are declared. Whether a key is missing for a resource the app actually uses cannot be determined from the binary alone.
Official source: Apple documentation · reviewed 2026-07-27
Alamofire has no privacy manifest
Apple lists specific third-party SDKs as requiring a privacy manifest when used in the stated submission cases. This embedded framework matched that list by name, and no PrivacyInfo.xcprivacy was found inside it. Alamofire appears on Apple's listed-SDK catalog (match confidence: exact) and no PrivacyInfo.xcprivacy was found inside it.
What to do
Update the SDK to a version that ships a privacy manifest, or ask its maintainer for one.
Update the plugin that vends this SDK, run flutter pub get and pod update, then rebuild.
Evidence
Embedded framework matched catalog entry Alamofire.
Payload/Sample.app/Frameworks/Alamofire.frameworkWhy this is not a certainty
Matching is by framework and bundle name against Apple's published list. A renamed or repackaged copy of a listed SDK may not be recognised.
Official source: Apple documentation · reviewed 2026-07-27
Warnings 0
No warnings.
Needs your answer or manual check 0
Nothing needs your confirmation.
Passed checks (17)
The archive was read successfully
An IPA is a ZIP archive. Every check in this report depends on reading its directory of entries. When the archive cannot be read, nothing about the app can be established.
What to do
Export the app again from Xcode or your build tool and upload the newly produced .ipa file.
Re-export the archive. Do not rename another file type to .ipa, and do not re-compress the contents of an existing IPA by hand.
Evidence
7 entries were read from the archive directory.
Official source: Apple documentation · reviewed 2026-07-27
The app was built with a currently required SDK
Apple requires apps uploaded to App Store Connect to be built with Xcode 26 or later using an iOS 26 SDK, in force since 28 April 2026. The SDK version is read from the binary's build-version load command.
What to do
Update to Xcode 26 or later, rebuild against the iOS 26 SDK, and re-export.
Update Xcode, then run flutter build ipa. Flutter builds with the installed Xcode's SDK.
Evidence
Architecture arm64 was built with SDK 26.
Why this is not a certainty
The SDK version is read from Mach-O build metadata. Where that metadata is absent or inconsistent across architectures, this check reports unable_to_verify.
Official source: Apple documentation · reviewed 2026-07-29
The declared executable is present in the bundle
Info.plist names an executable that does not exist as a file inside the app bundle. The app cannot launch. The file is located from the archive listing and is never opened or run.
What to do
Rebuild and re-export. The build product and the declared name have diverged.
Clean the build folder and re-export. If the product name was changed, confirm Info.plist was regenerated with the new name.
Evidence
The declared executable exists in the bundle listing.
Payload/Sample.app/SampleCFBundleExecutableOfficial source: Apple documentation · reviewed 2026-07-27
The executable name is declared
CFBundleExecutable names the binary the system launches. Without it the app cannot start.
What to do
Rebuild the app. This key is normally set automatically from the product name.
Confirm the target produces an executable and that Info.plist declares its name. A missing value usually indicates a corrupted build.
Evidence
The declared executable name. The file itself is never opened or run.
Payload/Sample.app/Info.plistCFBundleExecutableSampleOfficial source: Apple documentation · reviewed 2026-07-27
The bundle identifier is present
CFBundleIdentifier uniquely identifies the app. Uploads without one are rejected before review begins. This check does not verify that the identifier matches an App Store Connect record.
What to do
Set a bundle identifier in your target's settings and rebuild.
Set appId in the Capacitor config, run npx cap sync ios, then confirm the identifier in the Xcode target.
Evidence
The declared bundle identifier.
Payload/Sample.app/Info.plistCFBundleIdentifierinvalid.example.sampleWhy this is not a certainty
Whether this identifier matches your App Store Connect app record cannot be checked from the binary alone.
Official source: Apple documentation · reviewed 2026-07-27
The main app contains an Info.plist
Every app bundle must contain an Info.plist describing the app. Without it, the bundle identifier, versions, and permissions cannot be established.
What to do
Rebuild the app. A missing Info.plist points at a broken build or export rather than a configuration mistake.
Confirm the target has an Info.plist file configured and that it is copied into the built product.
Evidence
Info.plist is present (923 bytes).
Payload/Sample.app/Info.plistOfficial source: Apple documentation · reviewed 2026-07-27
The main Info.plist is a valid property list
The file exists but is not readable as a property list with a dictionary at its root. Its contents are unknown, which is not the same as empty.
What to do
Rebuild the app and confirm the Info.plist is valid XML or binary plist with a dictionary root.
Open the file in Xcode's property list editor. If it will not open, it is malformed. Restore it from version control and rebuild.
Evidence
Parsed as a xml property list.
Payload/Sample.app/Info.plistOfficial source: Apple documentation · reviewed 2026-07-27
The marketing version is present
CFBundleShortVersionString is the version users see on the App Store. Apple documents it as a period-separated numeric string.
What to do
Set a user-visible version number such as 1.0.0.
The part before the + in version: 1.0.0+1 becomes CFBundleShortVersionString.
Evidence
The declared marketing version.
Payload/Sample.app/Info.plistCFBundleShortVersionString1.0.0Official source: Apple documentation · reviewed 2026-07-27
The build version is present
CFBundleVersion is the build number. App Store Connect requires each upload to carry one, and rejects a build whose number is not higher than a previous upload for the same version.
What to do
Set a build number and increase it for every upload.
The number after the + in version: 1.0.0+1 becomes CFBundleVersion. Increment it, then run flutter build ipa.
Evidence
The declared build number.
Payload/Sample.app/Info.plistCFBundleVersion1Why this is not a certainty
Whether this build number is higher than your previously uploaded builds cannot be checked from the binary alone.
Official source: Apple documentation · reviewed 2026-07-27
Embedded frameworks were inventoried
The frameworks, dynamic libraries, and resource bundles embedded in this app, with any that match Apple's listed-SDK catalog identified. This is a record of what is in the build, not a problem to fix. 1 embedded component(s); 1 matched Apple's listed-SDK catalog. Listed: Alamofire.
What to do
No action required. Review the list to confirm you recognise every embedded component.
Confirm each embedded framework is one you intend to ship. An unfamiliar entry is worth investigating before submission.
Evidence
Alamofire (identified as Alamofire, exact)
Payload/Sample.app/Frameworks/Alamofire.frameworkWhy this is not a certainty
Frameworks are identified by name. A component this scanner cannot name is still listed, without a canonical identification.
Official source: Apple documentation · reviewed 2026-07-27
One main app bundle was identified
Every finding in this report is attributed to a specific target. With more than one top-level app bundle, the scanner cannot tell which one is the app being submitted, and attributing findings to the wrong target would be worse than reporting nothing.
What to do
Export a single application. Remove any additional .app bundle from the Payload directory.
Confirm the export contains one application. Watch companion apps and app clips belong inside the main app bundle, not beside it in Payload.
Evidence
Exactly one main app bundle was identified.
Payload/Sample.appOfficial source: Apple documentation · reviewed 2026-07-27
A Payload directory with an app bundle is present
An IPA places the app bundle inside a top-level Payload directory. An archive without one is not a valid iOS application package.
What to do
Export the app through Xcode's Distribute App flow rather than compressing a folder manually.
Use Xcode Organizer or your build tool's release export. Manually zipping an .app directory does not produce a valid IPA structure.
Evidence
The app bundle was found inside Payload.
Payload/Sample.appOfficial source: Apple documentation · reviewed 2026-07-27
The binary is built for iOS devices
A simulator build cannot run on a device and is rejected on upload. The binary's LC_BUILD_VERSION load command names the simulator platform, and Info.plist may also list iPhoneSimulator.
What to do
Build for a real device destination and export through the archive flow.
Use flutter build ipa, not flutter build ios --simulator.
Evidence
Architecture arm64 declares platform ios.
Official source: Apple documentation · reviewed 2026-07-27
Privacy manifest root keys use the documented types
NSPrivacyTracking must be a boolean, NSPrivacyTrackingDomains an array of strings, and NSPrivacyCollectedDataTypes and NSPrivacyAccessedAPITypes arrays of dictionaries. A wrong type means the declaration cannot be read as intended.
What to do
Correct the value types in the manifest to match Apple's documented structure.
In Xcode's property list editor, set NSPrivacyTracking to Boolean, NSPrivacyTrackingDomains to Array of String, and the collected-data and accessed-API keys to Array of Dictionary.
Evidence
All present root keys use the documented types.
Payload/Sample.app/PrivacyInfo.xcprivacyOfficial source: Apple documentation · reviewed 2026-07-27
Tracking declarations are internally consistent
The manifest lists NSPrivacyTrackingDomains while NSPrivacyTracking is false or absent. These two declarations contradict each other, and connections to a listed domain may fail at runtime when tracking is not declared.
What to do
Either set NSPrivacyTracking to true, or remove the tracking domains if the app does not track.
Decide which is correct. If the app or an embedded SDK performs tracking as Apple defines it, set NSPrivacyTracking to true. If it does not, remove the domains list.
Evidence
No tracking domains are declared.
Payload/Sample.app/PrivacyInfo.xcprivacyOfficial source: Apple documentation · reviewed 2026-07-27
The privacy manifest is a valid property list
A PrivacyInfo.xcprivacy file is present but is not readable as a property list. An invalid manifest can produce App Store Connect diagnostics, and its declarations cannot be read at all.
What to do
Open the manifest in Xcode's property list editor and correct or regenerate it.
If the file will not open in Xcode's editor it is malformed. Recreate it as a Property List file with a dictionary root and rebuild.
Evidence
Parsed as a xml property list.
Payload/Sample.app/PrivacyInfo.xcprivacyOfficial source: Apple documentation · reviewed 2026-07-27
Declared purpose strings have explanatory text
A usage-description key is present but its value is empty, whitespace only, or not a string. iOS shows this text in the permission prompt, and an empty value leaves the user with no explanation of why access is being requested.
What to do
Write a specific sentence explaining what the app does with this data, and why the user benefits.
Edit the usage description in the native Info.plist. Capacitor plugin docs list which keys each plugin needs.
Evidence
NSCameraUsageDescription has explanatory text.
Payload/Sample.app/Info.plistNSCameraUsageDescriptionScan receipts with the camera.Why this is not a certainty
This checks the keys that are declared. Whether a key is missing for a resource the app actually uses cannot be determined from the binary alone.
Official source: Apple documentation · reviewed 2026-07-27