Record what was actually checked for TestFlight

Verified against the built product rather than the source tree, which is what
caught the one blocker: no PrivacyInfo.xcprivacy. Apple requires it for any app
touching a required-reason API and this one uses UserDefaults in five files, so
the upload would have come back ITMS-91053 before reaching TestFlight. The first
archive silently omitted the file because it was added after the project was
generated — hence the note to check the bundle, not the repo.

Also green: archive for generic/platform=iOS, 38 unit tests, launch screen,
usage strings, 1024 icon, ATS with no leftover dev exception, WebRTC's own
manifest, and no tracking SDKs (grepped, not assumed).

Two items left for a human: the collected-data declaration is a legal statement
that must match the ASC privacy label, and versionCode 1 needs bumping after the
first upload.

And a warning that cost an archive: plutil -extract writes back in place without
-o -, so using it to inspect a plist destroys it. Use plutil -p.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Paul Hitt
2026-08-25 18:16:09 -04:00
co-authored by Claude Opus 5
parent 02e5c45cd4
commit e8d566b3f2
+38
View File
@@ -507,3 +507,41 @@ peer q1.json poll; peer q2.json poll
peer q1.json send <h2> c; peer q2.json send <h1> d # the exchange that used to die
peer q1.json poll; peer q2.json poll
```
## iOS TestFlight readiness, checked 2026-08-25
Verified against the BUILT PRODUCT, not the source tree — the difference matters,
and caught one thing that would have bounced the upload.
| | |
|---|---|
| `xcodebuild archive`, `generic/platform=iOS` | ✅ succeeded, arm64, WebRTC embedded |
| Unit tests | ✅ 38 passed, 0 failures |
| `PrivacyInfo.xcprivacy` | ✅ added, **confirmed present in the .app bundle** |
| `UILaunchScreen` | ✅ present (empty dict is the modern form) |
| Bundle / version / min OS | `net.flamenet.messenger`, 0.1.0 (1), iOS 16.0 |
| Usage strings | mic + Face ID; no camera use, so none required |
| App icon | 1024×1024 |
| ATS | fully on — no dev exception left behind |
| Third-party SDK manifest | WebRTC ships its own (no ITMS-91061) |
| Trackers | none — grepped for firebase/analytics/crashlytics/sentry/etc. |
🔴 **The privacy manifest was a hard blocker.** Apple requires one for any app
touching a "required reason" API, and this app uses `UserDefaults` in five files
— mute and pin flags, the push toggle, the chosen relay. Without it the upload is
rejected **ITMS-91053 before it ever reaches TestFlight**. ⚠️ The first archive
silently omitted it because the file was added after the project was generated:
**check the bundle, not the repo.**
⚠️ Two things a human must settle before submitting:
- `NSPrivacyCollectedDataTypes` is a legal declaration and must match the privacy
label in App Store Connect. Written from what the code sends; confirm it.
- `CURRENT_PROJECT_VERSION` is `1`. Fine once; every later upload needs a bump.
⚠️ **`plutil -extract` WRITES BACK IN PLACE** unless given `-o -`. Using it to
"inspect" an archive destroyed that archive's `Info.plist` down to 3 bytes. Use
`plutil -p` to read.
Still unproven: the feature surface end-to-end on a device — voice notes, calls,
groups, stories. Unit tests and an archive do not cover those, and testers will
be the first to exercise them.