Flutter — Releasing to the App Store

How to ship a Sankofa Deploy–enabled Flutter app to the Apple App Store. Covers the release archive flow, the one Xcode checkbox that breaks patches, App Store privacy compliance, and encryption export.

This guide walks through releasing a Flutter app that uses Sankofa Deploy to the Apple App Store. The most important step — easy to miss, hard to recover from — is the Xcode checkbox in §3.

1. Build the release

Bump your pubspec.yaml version (e.g. version: 1.0.4+1), then run:

bash
sankofa release ios

# Flavored app (gradle flavors + per-flavor entrypoint):
sankofa release ios --flavor production -t lib/main_production.dart

This produces a signed .ipa at build/ios/ipa/ (plus the .xcarchive at build/ios/archive/Runner.xcarchive) and registers the release with Sankofa under the version + build number from your pubspec.yaml. The .ipa is the binary you submit to App Store Connect — Sankofa stores only the release record and serves your patches. The version + build number ARE the patch addressing key, so any later patch must target the same 1.0.4+1 you set here.

For uncodesigned builds (CI farms that sign elsewhere), pass --no-codesign — it builds just the .xcarchive for you to sign + export in Xcode.

2. Upload to App Store Connect

Three equivalent options — pick whichever your workflow already uses.

3. The Xcode checkbox that breaks patches

The Sankofa CLI prints this same warning at the end of every sankofa release ios run; it is duplicated here because the upload step is where customers actually hit the dialog.

4. App Store Connect — privacy and encryption answers

App Store Connect will ask you two questions during the listing. Both have the same answers for every Sankofa Deploy–enabled Flutter app:

4.1 Encryption export compliance

Add this to your ios/Runner/Info.plist:

xml
<key>ITSAppUsesNonExemptEncryption</key>
<false/>

Sankofa uses only TLS (built into iOS) and signature verification (authentication, not encryption — categorically exempt under US export rules). Setting this key to false bypasses the annual self-classification questionnaire on every upload.

If your app uses additional encryption beyond what Sankofa adds, set this to true and complete the classification flow per Apple's instructions.

4.2 Privacy Manifest

The sankofa_flutter package ships a Privacy Manifest (PrivacyInfo.xcprivacy) declaring exactly two Required-Reason API categories:

CategoryWhy we use itReason code
NSPrivacyAccessedAPICategoryUserDefaultsNative crash bridge persists captured crashes across hard process terminationCA92.1
NSPrivacyAccessedAPICategoryFileTimestampPatch updater verifies downloaded file sizes via stat()C617.1

The Sankofa SDK's bundled framework also ships a slice-level manifest covering only FileTimestamp. Apple's App Store Connect validator (ITMS-91061 / ITMS-90683) will pass on a clean Sankofa-only app.

If you add other SDKs that use Required-Reason APIs (analytics, advertising, etc.), each one ships its own manifest — your app's combined manifest is the union.

5. Submit for review

In App Store Connect, attach the uploaded build to your release, fill in screenshots and metadata, and submit.

Sankofa Deploy patches are not reviewed by Apple — they update the Dart layer of your already-reviewed app under the over-the-air update provisions Apple's guidelines permit. What you submit for review is the base binary; patches modify the Dart layer of the already-reviewed app. As long as your patches don't change the app's primary purpose (no new categories of feature, no covert storefront), this is the same compliance posture over-the-air update tools have shipped under for years.

6. Ship a patch

Once your release is approved and in production:

bash
# Edit Dart code, then:
sankofa patch ios

Devices on the matching release version (1.0.4+1 in this example) will pick up the patch on the next app launch. No App Store review, no waiting period, no version bump.

Troubleshooting

SymptomAlmost-certainly the cause
Upload rejected with ITMS-91061Missing or stale Privacy Manifest somewhere in the build — confirm sankofa_flutter is at the latest version that bundles it.
Upload rejected with ITMS-90683A Required-Reason API was used without declaring the right 4-char reason code. Check which third-party SDK is missing it.
Patch shows uploaded in Sankofa console but devices don't see itYou almost certainly left "Manage Version and Build Number" checked in Xcode. See §3. The build that shipped has a different build number from the one Sankofa recorded.
App Store Connect asks the encryption questionnaire on every uploadITSAppUsesNonExemptEncryption is not set in Info.plist. See §4.1.
A patch uploaded fine but isn't applying on some devicesFirst confirm the device's app version matches the release's target version (see §3). If it still doesn't apply, open a support ticket with the release version + patch label.

See also

Edit this page on GitHub