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