Matthias Nott
2026-03-25 0c119ca4727751c93cfa969d83312aed69ad27e6
fix: remove NSAllowsArbitraryLoads, add App Store readiness checklist
1 files added
1 files modified
changed files
TODO-appstore.md patch | view | blame | history
ios/Runner/Info.plist patch | view | blame | history
TODO-appstore.md
....@@ -0,0 +1,54 @@
1
+# PAILot App Store Readiness Checklist
2
+
3
+Date: 2026-03-25
4
+Source: Security & Code Quality Review
5
+
6
+## CRITICAL (Must fix before submission)
7
+
8
+- [ ] **C1: Remove NSAllowsArbitraryLoads** — ATS bypass, Apple will reject. Use NSAllowsLocalNetworking only, add TLS to MQTT or use NSExceptionDomains for specific hosts
9
+- [ ] **C2: Add TLS to MQTT** — All conversations and auth token travel in plaintext. Set `client.secure = true`, configure TLS on AIBroker broker
10
+- [ ] **C3: Remove debug log files in production** — `mqtt_debug.log` and `_chatLog` write truncated message content to Documents. Wrap in `kDebugMode` or remove entirely
11
+
12
+## HIGH (Should fix before submission)
13
+
14
+- [ ] **H1: Unbounded image cache** — `_imageCache` in message_bubble.dart grows without limit. Add LRU eviction (cap at 50)
15
+- [ ] **H2: Audio temp files never cleaned** — `_base64ToFile` creates .m4a files never deleted. Clean up after playback completes
16
+- [ ] **H3: TextEditingController leak** — Rename dialog in session_drawer.dart creates controller but never disposes it
17
+- [ ] **H4: Input validation on settings** — No validation on host IPs, port range, MAC format. Add regex validators
18
+- [ ] **H5: LifecycleObserver never removed** — AudioService.init() adds observer but dispose() doesn't remove it
19
+- [ ] **H6: MQTT token in memory** — Acceptable for personal use, document as known limitation
20
+
21
+## MEDIUM (Improve before submission)
22
+
23
+- [ ] **M1: Subnet scan hammers 254 hosts** — Could trigger IDS. Detect subnet mask or cap range
24
+- [ ] **M2: No loadMore debounce** — Scroll pagination fires repeatedly on iOS bounce. Add isLoading guard
25
+- [ ] **M3: NavigateNotifier global singleton** — Mutable static, stale reference risk. Move to Riverpod provider
26
+- [ ] **M4: Unbounded _seenSeqs set** — O(n log n) eviction. Use FIFO deque instead
27
+- [ ] **M5: Screenshots bloat iCloud backup** — Store images as files, not base64 in JSON. Or exclude from backup
28
+- [ ] **M6: Unused import** — `server_config.dart` import in chat_screen.dart suppressed with ignore comment
29
+- [ ] **M7: Silent error swallowing** — ServerConfig _load() catches all exceptions silently. Add debugPrint
30
+
31
+## LOW (Nice-to-haves)
32
+
33
+- [ ] **L1: PrivacyInfo.xcprivacy** — Required since 2024 for UserDefaults and FileTimestamp APIs
34
+- [ ] **L2: Privacy policy URL** — Required for microphone/camera access apps
35
+- [ ] **L3: Unused dependencies** — Remove `web_socket_channel` and `wakelock_plus` from pubspec.yaml
36
+- [ ] **L4: Unnecessary _http._tcp** — Remove from NSBonjourServices, only _mqtt._tcp needed
37
+- [ ] **L5: Typing indicator timeout** — Can get stuck if typing_end missed during background. Auto-clear after 10s
38
+- [ ] **L6: Version number** — Default 1.0.0+1, set correctly before submission
39
+- [ ] **L7: App icon** — Verify meets Apple guidelines (no alpha channel, correct sizes)
40
+
41
+## App Store Requirements
42
+
43
+| Requirement | Status | Action |
44
+|------------|--------|--------|
45
+| NSMicrophoneUsageDescription | PASS | - |
46
+| NSCameraUsageDescription | PASS | - |
47
+| NSPhotoLibraryUsageDescription | PASS | - |
48
+| NSLocalNetworkUsageDescription | PASS | - |
49
+| NSBonjourServices | PASS | Remove _http._tcp |
50
+| NSAppTransportSecurity | FAIL | Fix C1 |
51
+| UIBackgroundModes: audio | PASS | - |
52
+| Privacy Policy | FAIL | Fix L2 |
53
+| PrivacyInfo.xcprivacy | FAIL | Fix L1 |
54
+| TLS for network | FAIL | Fix C2 |
ios/Runner/Info.plist
....@@ -61,8 +61,6 @@
6161 <string>PAILot needs camera access to take photos</string>
6262 <key>NSAppTransportSecurity</key>
6363 <dict>
64
- <key>NSAllowsArbitraryLoads</key>
65
- <true/>
6664 <key>NSAllowsLocalNetworking</key>
6765 <true/>
6866 </dict>
....@@ -70,7 +68,6 @@
7068 <string>PAILot needs local network access to discover and connect to AIBroker</string>
7169 <key>NSBonjourServices</key>
7270 <array>
73
- <string>_http._tcp</string>
7471 <string>_mqtt._tcp</string>
7572 </array>
7673 <key>UISupportedInterfaceOrientations</key>