Skip to content

Add privacy manifests and fix stale bundle metadata - #107

Merged
andiwand merged 1 commit into
mainfrom
modernize/01-compliance
Jul 26, 2026
Merged

Add privacy manifests and fix stale bundle metadata#107
andiwand merged 1 commit into
mainfrom
modernize/01-compliance

Conversation

@andiwand

Copy link
Copy Markdown
Member

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 own UserDefaults usage (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 via EXCLUDED_SOURCE_FILE_NAMES.

  • Full: NSPrivacyTracking = false
  • Lite: NSPrivacyTracking = true (requests ATT, serves personalized ads)

Both declare NSPrivacyAccessedAPICategoryUserDefaults with reason CA92.1.

Other fixes

  • UIRequiredDeviceCapabilities said armv7 in both Info.plists — the app has been 64-bit-only for years.
  • README build badge pointed at TomTasche/OpenDocument.ios and a workflow named build that no longer exists.
  • Deleted upload-symbols.sh: it hardcoded ~/Downloads/appDsyms.zip and ~/Downloads/appDsyms (1).zip. The uploadSymbols fastlane lane already does this properly.

Verification

Built ODR Full (Debug) and ODR Lite (Debug Lite) for the arm64 simulator and confirmed each .app bundles the right manifest:

  • Full bundle: NSPrivacyTracking => false
  • Lite bundle: NSPrivacyTracking => true
  • Info.plist: UIRequiredDeviceCapabilities => [arm64]

Not included

The Full target's GADApplicationIdentifier is 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.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread OpenDocumentReader/Privacy/Lite/PrivacyInfo.xcprivacy
@andiwand
andiwand merged commit 33ade5b into main Jul 26, 2026
1 check failed
@andiwand
andiwand deleted the modernize/01-compliance branch July 26, 2026 07:57
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant