Missing Compliance TestFlight: cách sửa dứt điểm
Bởi Mehdi Azizi
Đăng ngày , 9 phút
Missing Compliance nghĩa là Apple đang chờ bạn khai báo mã hóa. Hãy mở khóa build trong App Store Connect, rồi đặt khóa để không gặp lại.
Missing Compliance không phải là lỗi: đó là một build đang chờ bạn trả lời về mã hóa. Chừng nào bạn chưa trả lời, build vẫn bị chặn với tester. Với build này, bạn trả lời các câu hỏi trong tab TestFlight của App Store Connect. Với các build sau, bạn đặt khóa ITSAppUsesNonExemptEncryption trong Info.plist, hoặc ios.config.usesNonExemptEncryption trong app.json nếu dùng Expo, và trạng thái này sẽ không quay lại nữa.
Các app iOS của mình đều làm bằng Expo. Trong app.json của Solys, khóa này có giá trị false, đặt ở hai chỗ: trong ios.config và trong ios.infoPlist. Bài này dựa trên các trang của Apple về trạng thái build và về tuân thủ xuất khẩu cho build beta, mình đọc lại ngày 6 tháng 11 năm 2026.
Missing Compliance nghĩa là gì
Danh sách trạng thái build của Apple định nghĩa nó trong một câu: thiếu tài liệu tuân thủ xuất khẩu, và Apple đang chờ bạn hành động. Apple hiển thị nó màu vàng, màu của một quy trình đang diễn ra phụ thuộc vào bạn hoặc Apple, và phần mô tả nói rõ là cần bạn hành động.
Vì sao Apple hỏi? Trang về quy định xuất khẩu mã hóa giải thích: khi bạn gửi build lên TestFlight hoặc App Store, bạn gửi nó lên một máy chủ ở Mỹ. Nếu app được phân phối ngoài Mỹ và Canada, nó chịu luật xuất khẩu của Mỹ, bất kể công ty bạn ở nước nào. Và hễ app sử dụng, chứa hoặc tích hợp mã hóa, Apple coi đó là xuất khẩu phần mềm mã hóa.
Kết quả: với mỗi phiên bản mới, App Store Connect sẽ hỏi bạn các câu hỏi tuân thủ, trừ khi Info.plist đã trả lời sẵn. Đó là lý do build Expo đầu tiên gần như luôn rơi vào Missing Compliance.
Mở khóa build đang chờ
Các bước lấy từ trang của Apple về tuân thủ xuất khẩu cho build beta. Bạn cần vai trò Account Holder, Admin hoặc App Manager.
- Trong Apps, mở app của bạn, rồi vào tab TestFlight.
- Ở thanh bên, dưới Builds, chọn nền tảng.
- Ở cột Build, bấm vào biểu tượng hoặc số của build liên quan.
- Bấm Provide Export Compliance Information, rồi trả lời các câu hỏi.
- Nếu Apple yêu cầu tài liệu, bấm Go to App Encryption Page để gửi. Nếu không, bấm Save.
Apple cũng mô tả lối tắt: cạnh build, liên kết Manage mở cùng các câu hỏi đó, và Choose File cho phép đính kèm tài liệu đã được duyệt. Khi đã lưu, build chuyển sang Ready to Submit, hoặc thẳng sang Testing nếu gửi cho nhóm nội bộ. Ready to Test chỉ xuất hiện sau khi duyệt beta cho tester bên ngoài.
Liên kết Manage không bấm được? Trước hết hãy kiểm tra vai trò của bạn trong team: Apple chỉ cho phép vai trò Account Holder, Admin và App Manager trả lời, tài khoản Developer hay Marketing thì không. Apple không ghi nhận nguyên nhân nào khác. Nếu build vừa được gửi, hãy chờ email báo xử lý xong, được nói chi tiết trong bài về số build và phiên bản, rồi tải lại trang.
Không bao giờ phải trả lời nữa: khóa trong dự án
Apple nói rõ trên trang build beta: bạn có thể khai báo trong Info.plist rằng app không dùng mã hóa, hoặc được miễn, và sẽ không phải trả lời ở mỗi lần gửi nữa. Khóa này tên là ITSAppUsesNonExemptEncryption. Xcode hiển thị nó với tên App Uses Non-Exempt Encryption.
| Công cụ của bạn | Tệp | Ở đâu | Giá trị |
|---|---|---|---|
| Expo (EAS Build) | app.json | expo.ios.config | false |
| Expo, cách khác | app.json | expo.ios.infoPlist | false |
| React Native thuần | Info.plist | App Uses Non-Exempt Encryption | NO |
| Xcode, Swift | Info.plist | App Uses Non-Exempt Encryption | NO |
Với Expo, khóa tên là usesNonExemptEncryption, và tài liệu cấu hình nói rõ nó ghi khóa của Apple vào Info.plist của build, và ios.config chỉ dùng cho build: nó không xuất hiện trong manifest production.
{
"expo": {
"ios": {
"config": {
"usesNonExemptEncryption": false
}
}
}
}
Với Expo, ios.infoPlist cũng nhận khóa theo tên của Apple, cùng giá trị: đó là dòng thứ hai trong app.json của Solys. Trong dự án native, cùng khai báo đó chỉ là một dòng trong Info.plist: khóa App Uses Non-Exempt Encryption, tên mà Xcode hiển thị, với giá trị NO. Giá trị là boolean, không phải chuỗi.
Khóa có hiệu lực từ build tiếp theo. Build đã gửi vẫn ở Missing Compliance cho đến khi bạn trả lời trong App Store Connect: hai việc này không thay thế nhau, chúng bổ sung cho nhau.
false hay true: quyết định thế nào
Apple định nghĩa giá trị NO như sau: app của bạn, kể cả thư viện bên thứ ba, không dùng mã hóa nào, hoặc chỉ dùng mã hóa được miễn nghĩa vụ nộp tài liệu. Nếu không, là YES.
Theo trang về quy định xuất khẩu, thứ thường được miễn: mã hóa tích hợp sẵn trong hệ thống, như kết nối HTTPS qua URLSession. Thứ không được miễn: mã hóa độc quyền, do bạn tự viết hoặc nhúng vào. Tổng quan về tuân thủ xuất khẩu thêm một lưu ý quan trọng: chính bạn chịu trách nhiệm về cách diễn giải, và hậu quả của nó, nếu bạn nhận miễn trừ sai.
Với một app Expo gọi API qua HTTPS, lưu tùy chọn và bán gói đăng ký, false là câu trả lời thông thường. Với app tự mã hóa tin nhắn, tệp hoặc một kho bảo mật, câu trả lời là true, và Apple sẽ chờ tài liệu.
Đừng đặt
falsetheo phản xạ. Hãy xem lại các dependency: một thư viện mã hóa đầu cuối hay một kho lưu trữ mã hóa tự làm sẽ đẩy bạn sang phía phải nộp tài liệu.
Nếu app dùng mã hóa không được miễn
Trang về tài liệu mã hóa mô tả quy trình. Trong App Information, cạnh App Encryption Documentation, nút thêm sẽ mở các câu hỏi, rồi Choose File cho tài liệu, rồi Save. Apple yêu cầu bạn điền mô tả app và thiết lập phạm vi phát hành trước, để đánh giá tài liệu có đủ không. Apple nhắm khoảng hai ngày làm việc khi hồ sơ đầy đủ.
Khi tài liệu được duyệt, Apple cung cấp một giá trị để đặt vào khóa ITSEncryptionExportComplianceCode trong Info.plist. Có nó rồi, bạn không bị hỏi ở mỗi lần gửi nữa. Trong lúc xét duyệt, build hiển thị Waiting for Export Compliance Review hoặc In Compliance Review: bạn không cần làm gì.
Hai điểm Apple lưu ý, một trên trang quy định xuất khẩu, một trong phần tổng quan về tuân thủ:
- Ngay cả với mã hóa được miễn, bạn vẫn có thể phải nộp báo cáo tự phân loại hằng năm cho chính phủ Mỹ. Không cần nếu bạn dùng mã hóa không được miễn và đã nộp tài liệu cho Apple.
- Pháp cũng kiểm soát việc nhập và xuất app mã hóa. Phần tổng quan của Apple nêu lưu trữ bảo mật, liên lạc bảo mật và phần mềm diệt virus là các lĩnh vực liên quan, với miễn trừ cho app ngân hàng và y tế, và dẫn đến ANSSI.
Chuyện gì xảy ra tiếp theo trong TestFlight
Build đã mở khóa đi theo vòng đời bình thường của một build TestFlight, được mô tả trong bài TestFlight để test app iPhone: tester nội bộ dùng được ngay, tester bên ngoài sau khi duyệt beta, và hết hạn sau 90 ngày, theo danh sách trạng thái build. Những chỗ khác có thể làm kẹt việc gửi từ Expo, như số build đã dùng hay tệp bị từ chối, nằm trong các lỗi gửi EAS lên App Store Connect, còn toàn bộ quy trình ở đăng app Expo lên App Store với EAS.
iOS & Android Kit có code khởi đầu Expo của mình, với khóa này đã được đặt sẵn, và lộ trình từ build đầu tiên đến trang App Store. Nếu bạn muốn biết điều gì còn chặn việc đăng app, bài chẩn đoán miễn phí sẽ trả lời bạn sau vài câu hỏi và gửi bạn checklist chống bị Apple từ chối của mình. Các bước đầy đủ có trong đăng ứng dụng lên App Store.
Câu hỏi thường gặp
Missing Compliance trên TestFlight nghĩa là gì?
Build đang chờ bạn khai báo tuân thủ xuất khẩu, tức là câu trả lời về việc dùng mã hóa. Apple xếp nó vào các trạng thái cần bạn hành động. Build không đến tay tester cho đến khi bạn trả lời.
Vì sao liên kết Manage của Missing Compliance không bấm được?
Hãy kiểm tra vai trò: Apple chỉ cho phép vai trò Account Holder, Admin và App Manager trả lời. Apple không ghi nhận nguyên nhân nào khác. Nếu build vừa đến, hãy tải lại trang sau khi nhận email báo xử lý xong.
App mình chỉ dùng HTTPS, có phải trả lời có về mã hóa không?
Apple cho biết mã hóa tích hợp trong hệ thống, như kết nối HTTPS qua URLSession, thường được miễn nghĩa vụ nộp tài liệu. Khi đó, khóa ITSAppUsesNonExemptEncryption có giá trị NO, với điều kiện không có thư viện bên thứ ba nào thêm mã hóa độc quyền.
Có phải trả lời câu hỏi mã hóa ở mỗi build không?
Có, chừng nào Info.plist chưa có khóa ITSAppUsesNonExemptEncryption. Có khóa này, App Store Connect sẽ không hỏi nữa. Với Expo, bạn đặt nó trong app.json qua ios.config.usesNonExemptEncryption.
Khai báo mã hóa ở đâu trong app.json với Expo?
Trong app.json, dưới expo.ios.config, với "usesNonExemptEncryption": false nếu app không dùng mã hóa không được miễn nào. EAS Build ghi khóa này vào Info.plist của build. Nó có hiệu lực từ build tiếp theo, không áp dụng cho build đã gửi.
Missing Compliance có chặn cả việc gửi lên App Store không?
Các câu hỏi tuân thủ xuất khẩu được đặt ra cho mọi phiên bản mới, beta hay App Store. Một build chưa trả lời thì không thể phân phối. Khóa trong Info.plist giải quyết cả hai trường hợp cùng lúc.
Mình có phải nộp báo cáo tự phân loại hằng năm không?
Apple lưu ý rằng dùng mã hóa được miễn vẫn có thể bắt buộc nộp báo cáo tự phân loại hằng năm cho chính phủ Mỹ, và dẫn đến quy trình chính thức. Nếu app dùng mã hóa không được miễn và bạn đã nộp tài liệu cho Apple, báo cáo này không cần thiết.

