From c81de9023596eb9fe078a757d2d44b22846792de Mon Sep 17 00:00:00 2001 From: Nic Date: Tue, 21 Jul 2026 11:10:15 +0100 Subject: [PATCH] fix(packaging): iOS privacy manifest in every xcframework slice + JNA >=5.15 + plist version truth - V2-642: PrivacyInfo.xcprivacy embedded into each framework slice by build-swift.sh (flat bundles: root; macOS: Versions/A/Resources). The binary links required-reason APIs (stat/fstat -> FileTimestamp C617.1, statvfs -> DiskSpace 85F4.1) so consumer App Store uploads would be rejected with ITMS-91053 without it. No data collection, no tracking. - V2-652: JNA 5.14.0 -> 5.17.0 (android @aar + kotlin JVM) -- 5.14's x86_64 libjnidispatch.so is 4KB-aligned and crashes 16KB-page targets. - V2-658 residual: Info.plist CFBundleShortVersionString now derived from the ant-ffi crate version instead of hardcoded 0.2.0. Validated: bash -n, plutil -lint on the manifest, version extraction, jna-5.17.0.aar confirmed present on Maven Central. Full artifact validation happens at the 0.0.8 release build. Co-Authored-By: Claude Fable 5 --- ffi/android/build.gradle.kts | 4 ++- ffi/kotlin/AntFfi/build.gradle.kts | 4 +-- ffi/scripts/PrivacyInfo.xcprivacy | 45 ++++++++++++++++++++++++++++++ ffi/scripts/build-swift.sh | 13 ++++++++- 4 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 ffi/scripts/PrivacyInfo.xcprivacy diff --git a/ffi/android/build.gradle.kts b/ffi/android/build.gradle.kts index ea0cd3a3..892b3954 100644 --- a/ffi/android/build.gradle.kts +++ b/ffi/android/build.gradle.kts @@ -75,7 +75,9 @@ dependencies { // The `:android-aarch64` etc. variants aren't needed because we ship // the JNI libs directly via `jniLibs.srcDirs` above; consumers only // need the JVM-side JNA jar. - api("net.java.dev.jna:jna:5.14.0@aar") + // >= 5.15 required: 5.14's x86_64 libjnidispatch.so is 4KB-aligned and + // crashes on 16KB-page devices/emulators (Play compliance). + api("net.java.dev.jna:jna:5.17.0@aar") // Required for the `suspend fn` wrappers uniffi generates for async Rust. api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") } diff --git a/ffi/kotlin/AntFfi/build.gradle.kts b/ffi/kotlin/AntFfi/build.gradle.kts index 8cd58ecb..90dcd325 100644 --- a/ffi/kotlin/AntFfi/build.gradle.kts +++ b/ffi/kotlin/AntFfi/build.gradle.kts @@ -10,8 +10,8 @@ repositories { } dependencies { - // JNA for UniFFI native bindings - implementation("net.java.dev.jna:jna:5.14.0") + // JNA for UniFFI native bindings (kept in lockstep with ffi/android) + implementation("net.java.dev.jna:jna:5.17.0") // Kotlin coroutines (for async UniFFI bindings) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") diff --git a/ffi/scripts/PrivacyInfo.xcprivacy b/ffi/scripts/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..1c73449b --- /dev/null +++ b/ffi/scripts/PrivacyInfo.xcprivacy @@ -0,0 +1,45 @@ + + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryDiskSpace + NSPrivacyAccessedAPITypeReasons + + 85F4.1 + + + + + diff --git a/ffi/scripts/build-swift.sh b/ffi/scripts/build-swift.sh index ef6f2976..6a4dd78a 100755 --- a/ffi/scripts/build-swift.sh +++ b/ffi/scripts/build-swift.sh @@ -27,6 +27,11 @@ RUST_DIR="$FFI_DIR/rust" BUILD_DIR="$FFI_DIR/build" XCF_DIR="$BUILD_DIR/AntFfi.xcframework" +# Framework version string comes from the crate version (which tracks the +# released SDK version) instead of a hardcoded value drifting out of date. +ANT_FFI_VERSION="$(sed -n 's/^version = "\(.*\)"/\1/p' "$RUST_DIR/ant-ffi/Cargo.toml" | head -1)" +[ -n "$ANT_FFI_VERSION" ] || { echo "failed to read version from ant-ffi/Cargo.toml" >&2; exit 1; } + # Deployment targets — must match Package.swift's .iOS(.v16) / .macOS(.v13) # declarations in ant-swift. Setting these silences "built for newer X version" # warnings at consumer link time. iOS<13 also fails to link due to missing @@ -108,7 +113,7 @@ write_plist() { CFBundleInfoDictionaryVersion6.0 CFBundleName$FW_NAME CFBundlePackageTypeFMWK - CFBundleShortVersionString0.2.0 + CFBundleShortVersionString$ANT_FFI_VERSION CFBundleVersion1 $minkey$minver @@ -129,6 +134,9 @@ prepare_framework() { cp "$GEN_DIR/$FW_NAME.h" "$V/Headers/" write_modulemap "$V/Modules/module.modulemap" write_plist "$V/Resources/Info.plist" "$platform" + # Required-reason-API privacy manifest (ITMS-91053); macOS bundles + # keep resources under Versions/A/Resources. + cp "$SCRIPT_DIR/PrivacyInfo.xcprivacy" "$V/Resources/PrivacyInfo.xcprivacy" ln -s "A" "$fw/Versions/Current" ln -s "Versions/Current/$FW_NAME" "$fw/$FW_NAME" ln -s "Versions/Current/Headers" "$fw/Headers" @@ -142,6 +150,9 @@ prepare_framework() { cp "$GEN_DIR/$FW_NAME.h" "$fw/Headers/" write_modulemap "$fw/Modules/module.modulemap" write_plist "$fw/Info.plist" "$platform" + # Required-reason-API privacy manifest (ITMS-91053); flat frameworks + # carry it at the bundle root. + cp "$SCRIPT_DIR/PrivacyInfo.xcprivacy" "$fw/PrivacyInfo.xcprivacy" fi }