PAILot App Store Readiness Checklist
Date: 2026-03-25
Source: Security & Code Quality Review
CRITICAL (Must fix before submission)
- [ ] C1: Remove NSAllowsArbitraryLoads — ATS bypass, Apple will reject. Use NSAllowsLocalNetworking only, add TLS to MQTT or use NSExceptionDomains for specific hosts
- [ ] C2: Add TLS to MQTT — All conversations and auth token travel in plaintext. Set
client.secure = true, configure TLS on AIBroker broker
- [ ] C3: Remove debug log files in production —
mqtt_debug.log and _chatLog write truncated message content to Documents. Wrap in kDebugMode or remove entirely
HIGH (Should fix before submission)
- [ ] H1: Unbounded image cache —
_imageCache in message_bubble.dart grows without limit. Add LRU eviction (cap at 50)
- [ ] H2: Audio temp files never cleaned —
_base64ToFile creates .m4a files never deleted. Clean up after playback completes
- [ ] H3: TextEditingController leak — Rename dialog in session_drawer.dart creates controller but never disposes it
- [ ] H4: Input validation on settings — No validation on host IPs, port range, MAC format. Add regex validators
- [ ] H5: LifecycleObserver never removed — AudioService.init() adds observer but dispose() doesn't remove it
- [ ] H6: MQTT token in memory — Acceptable for personal use, document as known limitation
MEDIUM (Improve before submission)
- [ ] M1: Subnet scan hammers 254 hosts — Could trigger IDS. Detect subnet mask or cap range
- [ ] M2: No loadMore debounce — Scroll pagination fires repeatedly on iOS bounce. Add isLoading guard
- [ ] M3: NavigateNotifier global singleton — Mutable static, stale reference risk. Move to Riverpod provider
- [ ] M4: Unbounded _seenSeqs set — O(n log n) eviction. Use FIFO deque instead
- [ ] M5: Screenshots bloat iCloud backup — Store images as files, not base64 in JSON. Or exclude from backup
- [ ] M6: Unused import —
server_config.dart import in chat_screen.dart suppressed with ignore comment
- [ ] M7: Silent error swallowing — ServerConfig _load() catches all exceptions silently. Add debugPrint
LOW (Nice-to-haves)
- [ ] L1: PrivacyInfo.xcprivacy — Required since 2024 for UserDefaults and FileTimestamp APIs
- [ ] L2: Privacy policy URL — Required for microphone/camera access apps
- [ ] L3: Unused dependencies — Remove
web_socket_channel and wakelock_plus from pubspec.yaml
- [ ] L4: Unnecessary _http._tcp — Remove from NSBonjourServices, only mqtt.tcp needed
- [ ] L5: Typing indicator timeout — Can get stuck if typing_end missed during background. Auto-clear after 10s
- [ ] L6: Version number — Default 1.0.0+1, set correctly before submission
- [ ] L7: App icon — Verify meets Apple guidelines (no alpha channel, correct sizes)
App Store Requirements
| Requirement | Status | Action |
|------------|--------|--------|
| NSMicrophoneUsageDescription | PASS | - |
| NSCameraUsageDescription | PASS | - |
| NSPhotoLibraryUsageDescription | PASS | - |
| NSLocalNetworkUsageDescription | PASS | - |
| NSBonjourServices | PASS | Remove http.tcp |
| NSAppTransportSecurity | FAIL | Fix C1 |
| UIBackgroundModes: audio | PASS | - |
| Privacy Policy | FAIL | Fix L2 |
| PrivacyInfo.xcprivacy | FAIL | Fix L1 |
| TLS for network | FAIL | Fix C2 |