Privacy Manifest (PrivacyInfo.xcprivacy) — файлът, който всички приложения и SDK на трети страни са задължени да включат в компилацията за iOS от пролетта на 2024 г. Apple изисква деклариране на причините за използване на защитени API (Required Reason API) и типовете събирани данни. Според Apple Developer Documentation, всеки бинарен файл в състава на приложението — основна цел, рамки, Swift Package Manager зависимости — трябва да съдържа собствен Privacy Manifest.
Основни точки
Privacy Manifest е файлът PrivacyInfo.xcprivacy във формат property list (XML), който декларира какви типове данни събира приложението и защо използва определени API. Apple въведе манифестите в рамките на инициативата за повишаване на прозрачността на поверителността, подобно на Privacy Nutrition Label, но на ниво код и бинарен файл.
Основната цел на манифеста е документиране на използването на така наречените Required Reason API. Това са категории API, които могат да бъдат използвани за снемане на цифров отпечатък на устройството (fingerprinting), поради което всяко тяхно използване трябва да бъде придружено от декларация на конкретна причина от одобрения списък на Apple.
От 1 май 2024 г. Apple отхвърля компилации, които не съдържат Privacy Manifest. Това се отнася както за основните цели на приложението, така и за всички вградени SDK и зависимости. Според WWDC 2023 манифестът е задължителен за всички приложения, разпространявани чрез App Store.
Манифестът трябва да присъства във всеки бинарен файл — не само в основното приложение, но и във всяка рамка и статична библиотека. Ако SDK на трета страна не е предоставил манифест, разработчикът трябва да го добави ръчно или да се свърже с доставчика на SDK за актуализация.
Преди появата на манифестите разработчиците можеха да използват обширни системни API (достъп до файловата система, дата/час, системни журнали) без прозрачно обяснение на целта на използване. Това създаваше риск от изтичане на данни чрез SDK на трети страни, които можеха да събират информация без знанието на разработчика.
Според данни на Mysk Inc. (2023) много популярни SDK използваха API за снемане на отпечатък на устройството без видима необходимост — например четяха време на работа (uptime) за определяне на часовата зона или сканираха директории за събиране на метаданни. Privacy Manifest задължава деклариране на всяко подобно действие.
Освен Required Reason API, манифестът включва раздел NSPrivacyTracking — флаг, показващ дали приложението използва проследяване (изисква ATT) и NSPrivacyCollectedDataTypes — списък на типовете събирани данни във формат Privacy Nutrition Label.
Privacy Nutrition Label е удобен за потребителя изглед на страницата на приложението в App Store, който показва какви данни събира приложението. Privacy Manifest е технически файл вътре в бинарния файл, който се проверява автоматично от Apple. Ако данните в манифеста не съвпадат с етикетите в App Store Connect, Apple отхвърля компилацията.
Така манифестът е източник на истина за проверяващата система на Apple. На негова основа автоматично се генерират етикетите за поверителност, но разработчикът трябва да поддържа и двете представяния актуални. Промяна на манифеста след публикуване изисква изпращане на нова компилация за преглед.
Файлът PrivacyInfo.xcprivacy използва формат property list с коренен тип Dictionary. Основните ключове от най-високо ниво: NSPrivacyTracking (Boolean), NSPrivacyTrackingDomains (Array), NSPrivacyCollectedDataTypes (Array), NSPrivacyAccessedAPITypes (Array).
Ключът NSPrivacyTracking — булева стойност, показваща дали приложението използва проследяване (изисква ATT). Ако е true, трябва да се посочи и NSUserTrackingUsageDescription в Info.plist. Ключът NSPrivacyTrackingDomains — масив от домейни, на които се прилага проследяване.
Ключът NSPrivacyCollectedDataTypes — масив от речници, всеки от които описва типа събирани данни: категория (NSPrivacyCollectedDataType), задължителност (NSPrivacyCollectedDataTypeLinked), цел (NSPrivacyCollectedDataTypePurposes). Целите включват: маркиране на трети страни, аналитика, разработка на продукт и персонализация на съдържание.
Ключът NSPrivacyAccessedAPITypes — масив от речници за всяка категория Required Reason API: категория (NSPrivacyAccessedAPITypeReasons) — конкретна причина от одобрения списък на Apple и NSPrivacyAccessedAPIType — идентификатор на категорията API.
<!-- PrivacyInfo.xcprivacy -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
</array>
</dict>
</plist>
Типовете данни се разделят на няколко категории: контактна информация (име, имейл, телефон), финанси (платежни данни), идентификатори (IDFA, User ID), данни за използване (журнали, кликвания), диагностика (crash logs) и потребителско съдържание (снимки, видеа, файлове). Всяка категория допълнително се маркира като „свързана с потребителя" (linked) или „несвързана" (not linked).
Linked означава, че данните са свързани с потребителския акаунт; not linked — данните са агрегирани или анонимизирани. От това маркиране зависи как Apple показва етикета за поверителност: linked данните се маркират в жълто, not linked — в зелено.
Apple отдели няколко категории API, всяко използване на които трябва да бъде придружено от конкретна причина от одобрения списък. Причината е уникален код, например C617.1 или 35F9.1, който съответства на конкретна цел, разрешена от Apple.
Категорията NSPrivacyAccessedAPICategoryFileTimestamp включва API за достъп до времеви клейма на файлове (creationDate, modificationDate). Причини: C617.1 (синхронизация на файлове), 3B52.1 (резервно копие), 0A2A.1 (антиизмама).
Категорията NSPrivacyAccessedAPICategoryDiskSpace включва API за проверка на свободно място на диска (NSFileManager. Проверки (NSFileManager). Причини: E174.1 (управление на кеш), 85F4.1 (изтегляне на съдържание), B728.1 (диагностика).
Категорията NSPrivacyAccessedAPICategorySystemBootTime включва API за достъп до времето за стартиране на системата (uptime). Има само една причина: 35F9.1 (измерване на времето на сесия за аналитика). Всяко друго използване се счита за fingerprinting.
Всяка категория има от 1 до 5 одобрени причини. Разработчикът е длъжен да избере причината, която най-точно съответства на реалното използване на API. Предоставянето на невярна причина може да доведе до отхвърляне на компилацията или блокиране на акаунта.
От 1 май 2024 г. всички SDK на трети страни — както бинарни, така и с отворен код — са задължени да включат Privacy Manifest в своя пакет. Apple проверява манифестите за всички зависимости и ако поне един SDK няма манифест, компилацията ще бъде отхвърлена.
Големите SDK (Firebase, Adjust, AppsFlyer, Facebook SDK) вече актуализираха пакетите си. Ако вашият проект използва по-малко познат SDK, проверете неговата версия и ако е необходимо актуализирайте го или се свържете с разработчика. Временно решение е ръчно добавяне на манифест за SDK в проекта, но не се препоръчва поради несъответствия при актуализации.
Privacy Info.xcprivacy може да бъде създаден чрез вградения шаблон на Xcode 15+ или ръчно. Ще разгледаме и двата варианта.
В Xcode 15 е добавен шаблонът Privacy Manifest: File → New → File → Resource → Privacy Manifest. Xcode създава файл с основна структура и попълва NSPrivacyTracking и празни масиви за API и данни. След създаването трябва ръчно да посочите причините за всяко използвано Required Reason API.
Шаблонът автоматично добавя файла към основната цел. Ако проектът има няколко цели (Extensions, Watch app), трябва да добавите манифеста към всяка от тях. Xcode не проверява наличието на манифест в зависимостите на етапа на компилация — само на етапа на архивиране.
// AppDelegate: проверка на манифеста на етапа на разработка
import Foundation
func validatePrivacyManifest() {
guard let path = Bundle.main.path(
forResource: "PrivacyInfo", ofType: "xcprivacy"
) else {
print("PrivacyInfo.xcprivacy not found")
return
}
guard let dict = NSDictionary(contentsOfFile: path)
else { return }
print("Privacy manifest loaded: \(dict.count) keys")
}
Можете да създадете PrivacyInfo.xcprivacy ръчно като обикновен XML property list файл. За целта създайте файл с име PrivacyInfo.xcprivacy, напишете стандартното заглавие на plist и добавете коренен речник с необходимите ключове. Уверете се, че файлът е добавен към целта (Target Membership).
Ръчният метод е полезен, когато трябва да добавите манифест към статична библиотека или зависимост Package Manager без да използвате интерфейса на Xcode. След компилация проверете дали файлът е попаднал в бинарния файл чрез командата nm или архивиране.
Преди да изпратите компилацията в App Store, трябва да проверите дали Privacy Manifest е коректен и пълен. Apple предоставя няколко инструмента за проверка.
При архивиране на проекта (Product → Archive) Xcode извършва проверка на манифестите. Ако бъде открита грешка — липса на манифест, невярна причина, празна категория — архивирането завършва с грешка. Журналът с грешки се показва в Issue navigator с посочване на проблемния SDK и категорията API.
Допълнителна проверка се извършва от App Store Connect при качване на компилацията. Ако валидирането не успее, компилацията се отхвърля с автоматичен имейл, съдържащ идентификатора на проблемния API и препоръчителната корекция.
За автоматизиране на проверката използвайте скриптове, които анализират бинарния файл за използване на Required Reason API. Apple предоставя инструмента libtool и скриптове за проверка на символи, но общността е разработила по-удобни помощни програми.
# Търсене на използване на FileTimestamp API в бинарния файл
nm MyApp.app/MyApp | grep "NSFileCreationDate"
# Проверка за наличие на PrivacyInfo.xcprivacy в приложението
find MyApp.app -name "*.xcprivacy"
Най-честата грешка — липса на манифест в един от SDK. Дори ако основната цел съдържа манифест, Apple проверява всички бинарни файлове поотделно. Втората по честота — неверен код на причина: използване на причина за една категория API с API от друга категория.
Третата грешка — прекомерно деклариране на API, които всъщност не се използват. Разработчиците добавят всички възможни причини „за всеки случай", което тревожи рецензентите на Apple. Добавяйте само категориите, които реално се използват. Използвайте статичния анализатор на Xcode за проверка.
Често задавани въпроси
От 1 май 2024 г. Apple отхвърля всяка компилация без манифест. Грешката възниква на етапа на качване в App Store Connect. Старите приложения не се блокират, но актуализациите изискват задължително включване на манифеста.
Да, манифестът е задължителен за всички платформи на Apple: iOS, iPadOS, macOS, tvOS, watchOS и visionOS. Изискванията за Required Reason API са единни за всички платформи, въпреки че наборите от API могат леко да се различават.
Ако SDK не е предоставил манифест, създайте отделен файл PrivacyInfo.xcprivacy и го добавете към групата на SDK в проекта. Посочете причини за API, които този SDK използва, въз основа на документацията на SDK.
Да. При автоматична проверка Apple сравнява декларираните причини с действителните извиквания на API. Несъответствието води до отхвърляне. При ръчна проверка рецензентът може да поиска обяснение.
Да, Apple проверява манифестите за всички зависимости, включително SPM. Доставчиците на пакети са задължени да включат PrivacyInfo.xcprivacy в своите хранилища. Xcode предупреждава за липсващи манифести при архивиране.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също