Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

UMSH for iOS

Build the local Rust/Swift package before opening the project:

scripts/ios/build-mobile-core.sh
open apps/ios/UMSH.xcodeproj

The initial target is iPhone-only (TARGETED_DEVICE_FAMILY = 1) on iOS 18 or later. iPad is deliberately excluded: iPadOS requires all four interface orientations for multitasking, and the UI is portrait-only. Signing is automatic against team 2ZEL2X74K7; override DEVELOPMENT_TEAM locally if you build under a different account.

TestFlight

make ios-archive
make ios-upload

ios-archive rebuilds the xcframework first (Artifacts/*.xcframework/ is gitignored, so a clean checkout has none), then archives into ~/Library/Developer/Xcode/Archives/<date>/UMSH-<build>.xcarchive. That path is deliberate: Xcode's Organizer lists only archives under that directory, so an archive written anywhere else — a local build/, say — uploads fine but never appears in Window → Organizer → Archives. ios-upload uploads the most recent UMSH*.xcarchive found there, including ones made by Xcode's own Product → Archive; pass IOS_UPLOAD_ARCHIVE=<path> to send an older one.

The build number is not stored in the project. CURRENT_PROJECT_VERSION — which GENERATE_INFOPLIST_FILE turns into CFBundleVersion — is passed on the xcodebuild command line as the repository's commit count, so every upload gets a distinct number that points back at a commit, and App Store Connect never sees the duplicate it would reject under the same MARKETING_VERSION. That count only increases while you keep landing on main; archiving from a shorter side branch reuses a number. Override it there, or for any one-off:

make ios-archive IOS_BUILD_NUMBER=$(date -u +%s)

MARKETING_VERSION is still a deliberate edit in the project — bump it in Xcode when you want a new user-visible version.

Archiving from Xcode's UI instead (Product → Archive) bypasses all of that and uses the project's own CURRENT_PROJECT_VERSION, which stays at 1. Use make ios-archive for anything headed to App Store Connect.

ExportOptions.plist sets destination = upload, so ios-upload sends the archive straight to App Store Connect; that is why it is a separate target from ios-archive rather than a step inside it. It also sets testFlightInternalTestingOnly; drop that key when you're ready to submit a build for external Beta App Review.

ITSAppUsesNonExemptEncryption is declared false in Info.plist, which stops App Store Connect asking the encryption questions on every upload. UMSH implements its own AES-128/AES-CMAC/HKDF/Ed25519 rather than calling CryptoKit, but these are all published standard algorithms (FIPS 197, RFC 4493, RFC 5869, RFC 8032) — not proprietary ones. Apple requires no US documentation for that case, so the key stays false regardless of which territories are enabled.

Two separate obligations sit outside this key and are not implied by it:

  • France. Distributing on the App Store in France requires a French encryption declaration. That stems from French rules on cryptographic means — an import-side requirement, not a US export exemption — so it does not change the value above. Note that a false declaration skips App Store Connect's encryption questionnaire, which is where that form would otherwise be requested; handle it directly if France is added to availability.
  • BIS. Standard-algorithm mass-market software is generally self-classified under License Exception ENC 740.17(b)(1), which carries an annual self-classification report due February 1. App Store Connect never asks about it.