Add privacy manifests and fix stale bundle metadata - #107
Merged
Conversation
App Store submissions require a per-app PrivacyInfo.xcprivacy declaring required-reason API usage. Only the pods shipped one so far, so uploads trigger ITMS-91053 for our own UserDefaults usage. Both manifests have to land at the bundle root under the exact same name, so they live in per-flavor folders and each configuration excludes the other one. Full declares no tracking, Lite declares tracking because it requests ATT and serves personalized ads. Also: - UIRequiredDeviceCapabilities said armv7 on a 64-bit-only app - the README build badge pointed at the old repo and a workflow name that no longer exists - upload-symbols.sh hardcoded ~/Downloads paths from someone's machine; the fastlane uploadSymbols lane already does this properly
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6884238b17
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
andiwand
added a commit
that referenced
this pull request
Aug 3, 2026
Build 43 of the Lite app came back ITMS-91064 Invalid Binary: its PrivacyInfo.xcprivacy set NSPrivacyTracking to true while NSPrivacyTrackingDomains was empty, which App Review rejects. The Pro manifest passed the same upload with false and an empty list. The manifests only landed in #107, after 1.35 shipped, so this file had never been through App Store validation before. Listing the AdMob endpoints would satisfy the rule but cost more than it buys: iOS blocks the domains named here whenever ATT authorization is missing, so it would also cut off the non-personalized ads served to users who decline. The Google SDKs ship no domains of their own for that reason, and GoogleMobileAds already marks DeviceID as tracking in its own manifest, which Apple aggregates with this one. Also corrects the 1.37 release notes to the copy actually submitted: 1.36 was tagged but never went to the store, so the store jumps 1.35 to 1.37 and the notes have to cover the 1.36 work. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of a stack of modernization PRs.
Privacy manifests
App Store uploads require a per-app
PrivacyInfo.xcprivacy. Only the pods shipped one, so our ownUserDefaultsusage (StoreReviewHelper, ConfigurationManager, onboarding) is undeclared and trips ITMS-91053.Both flavors need a manifest at the bundle root under the exact same filename, so they live in
OpenDocumentReader/Privacy/{Full,Lite}/and each build configuration excludes the other folder viaEXCLUDED_SOURCE_FILE_NAMES.NSPrivacyTracking = falseNSPrivacyTracking = true(requests ATT, serves personalized ads)Both declare
NSPrivacyAccessedAPICategoryUserDefaultswith reasonCA92.1.Other fixes
UIRequiredDeviceCapabilitiessaidarmv7in both Info.plists — the app has been 64-bit-only for years.TomTasche/OpenDocument.iosand a workflow namedbuildthat no longer exists.upload-symbols.sh: it hardcoded~/Downloads/appDsyms.zipand~/Downloads/appDsyms (1).zip. TheuploadSymbolsfastlane lane already does this properly.Verification
Built
ODR Full(Debug) andODR Lite(Debug Lite) for the arm64 simulator and confirmed each.appbundles the right manifest:NSPrivacyTracking => falseNSPrivacyTracking => trueUIRequiredDeviceCapabilities => [arm64]Not included
The Full target's
GADApplicationIdentifieris Google's public sample app ID. Removing it is only safe once Full stops linking the ads SDK, which needs the Lite/Full target split — deferred to the SPM PR later in this stack.