Як тримати політику конфіденційності узгодженою зі збіркою
Політику конфіденційності пишуть раз, і вона застаріває, щойно pull request додає SDK. Як помітити це в самому pull request безкоштовною перевіркою, що читає лише файли збірки.
Зафіксуйте, на основі яких SDK, типів даних і дозволів написано ваші сторінки, а потім порівнюйте з цим записом файли збірки в кожному pull request. Коли з’являється залежність або дозвіл, яких у записі немає, pull request покаже це раніше за реліз — поки політику конфіденційності і форми магазинів ще легко оновити.
Зробіть це за кілька хвилин
AppFoyer розміщує сторінки, про які цей посібник, — політику конфіденційності, умови, підтримку, видалення акаунта та app-ads.txt — на власному піддомені, без вашого домену й сервера. Один застосунок — безкоштовно, і ніщо з того, чого вимагає магазин, ніколи не буває за платним доступом.
Перевірено 30 вересня 2026 р.. Політики магазинів змінюються, іноді без попередження. Усе нижче посилається на офіційну документацію, і авторитетом є та сторінка, а не ця. Якщо вони розходяться, правий магазин. Цей посібник перекладено з англійської; цитати з документації магазинів наведено в англійському оригіналі.
Написати політику конфіденційності — разова робота. Тримати її правдивою — ні: політика описує збірку, яка була у вас, коли ви її писали, а збірка постійно змінюється. Pull request додає звіти про збої, бібліотеку підписок або дозвіл на геолокацію, застосунок виходить, а політика, форма Data safety і відомості App Privacy все ще описують старий застосунок.
Обидва магазини вважають це вашою проблемою, а не своєю. Google Play каже, що ваші відповіді Data safety мають завжди залишатися точними й повними і що дані, які збирають сторонні бібліотеки і SDK у вашому застосунку, декларуєте ви. Apple каже те саме про відомості App Privacy і додає, що відповіді в App Store Connect можна змінити будь-коли без подання оновлення.
Звідки насправді береться розбіжність
Майже ніколи не з рішення «збирати більше даних». Вона береться зі звичайної інженерної роботи:
- Нова залежність. Звіти про збої, аналітика, SDK пейволу, бібліотека карт.
- Новий дозвіл. Геолокація для однієї функції, камера для сканера, відстеження для реклами.
- Flavor або target. Безкоштовна збірка отримує рекламний SDK, якого немає в платній.
- Видалення. Це теж розбіжність: тепер політика декларує зайве — безпечніша помилка, але все одно помилка.
Кожна з них потрапляє у файл збірки — build.gradle, AndroidManifest.xml, Podfile,
Package.swift, Info.plist, pubspec.yaml, package.json. Саме тому це можна перевірити.
Підхід: запис і перевірка в кожному pull request
- Коли ваші сторінки написано, зафіксуйте, на основі чого їх написано: SDK, типи даних і дозволи в збірці на той момент.
- У кожному pull request знову прочитайте файли збірки і порівняйте.
- Коли щось відрізняється, скажіть, що саме, де (файл і рядок) і на яку сторінку чи форму це може вплинути.
Важливі дві властивості. Перевірка має читати лише файли збірки — ніколи вихідний код, ніколи секрети, — щоб її було безпечно запускати в будь-якому репозиторії. І вона має казати «може бути застарілим», а не «порушення»: бібліотека у файлі збірки не доводить, що застосунок нею користується, і лише ви знаєте, чи змінює вона те, що збирає ваш застосунок.
Налаштування з AppFoyer
Перевірка безкоштовна на будь-якому тарифі. Вона читає лише файли збірки, не потребує ключа чи секрету, нікуди нічого не надсилає і ніколи не змінює сторінку.
З плагіном Claude Code
- Скажіть “make this app store-ready”. Окрім чернеток сторінок, плагін записує
appfoyer.jsonу корінь вашого репозиторію: запис того, на основі чого написано сторінки. - Скажіть “add the AppFoyer drift check”. Він покаже вам GitHub workflow і запише
.github/workflows/appfoyer.yml, коли ви погодитеся. - Закомітьте обидва файли. Плагін ніколи не робить commit чи push за вас.
Без плагіна
Додайте workflow самі:
name: AppFoyer drift check
on: pull_request
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: appfoyer/check-action@v1
Відкрийте pull request. Поки в репозиторії ще немає appfoyer.json, підсумок завдання (job
summary) покаже файл, який було б записано з вашої збірки. Порівняйте його з опублікованими
сторінками і закомітьте.
Або створіть його локально — той самий сканер, опублікований у npm:
npx @appfoyer/check init
В іншій CI-системі
npm-пакет працює всюди, де працює Node 20 або новіша. Наприклад, для GitLab:
appfoyer-drift-check:
image: node:22
script:
- npx -y @appfoyer/check --fail-on-drift
--format markdown дає той самий звіт, що показує job summary у GitHub; --format json — для
скриптів.
Який вигляд має результат
Pull request, який додає RevenueCat у застосунок, сторінки якого написано без нього:
"Trail Notes": 2 changes
+ In-app purchases / subscriptions (data collected) app/build.gradle.kts:28
→ Privacy policy may not declare "In-app purchases / subscriptions"
→ Google Play Data safety and Apple App Privacy answers may be outdated
→ Terms may not cover purchases and subscriptions
+ RevenueCat (SDK) app/build.gradle.kts:28
→ Store forms: RevenueCat is not in the app's SDK list
→ Privacy policy may not name this SDK
За замовчуванням завдання звітує і проходить. Додайте fail-on-drift: "true" під with:, щоб воно
падало, доки запис не оновлено.
Коли перевірка повідомляє про зміну
- Оновіть те, на що впливає зміна. Знову скажіть “make this app store-ready” у тій самій
гілці: плагін ще раз прочитає збірку, оновить факти про застосунок, перепише чернетки сторінок,
яких стосується зміна, і перезапише
appfoyer.json. Або відредагуйте сторінки і вкладку Store forms у дашборді самі. - Оновіть запис. Плагін уже зробив це. Після редагування в дашборді запустіть
npx @appfoyer/check updateабо скопіюйте оновлений файл із job summary, де він розміщений під результатами. - Закомітьте його в тому самому pull request. Наступний запуск не покаже змін, а історія покаже, що залежність і зміна розкриття з’явилися разом.
- Оновіть форми магазинів у консолях. Ні перевірка, ні AppFoyer не мають доступу до Play Console чи App Store Connect. Чернетки відповідей — на вкладці Store forms у дашборді.
- Опублікуйте оновлені чернетки з екрана перегляду.
Кілька застосунків в одному репозиторії
appfoyer.json містить один запис на кожну сторінку застосунку в магазині. Product flavor із
власним application id отримує власний запис, тож рекламний SDK, який використовує лише
безкоштовний flavor, порівнюється зі сторінками безкоштовного flavor, а не платного. Плагін записує
по одному запису на кожен flavor, який він підготував до магазину. Вручну запис приймає список
sourceSets — ["free"] або, для збірки з кількома вимірами, кожен flavor у комбінації плюс саму
комбінацію — і теку root, коли застосунок лежить усередині монорепозиторію.
Чого вона не бачить
- Залежностей залежностей, окрім iOS, де їх перелічує
Podfile.lock. SDK, який підтягує інша бібліотека, не з’являється у вашому файлі збірки, тож не з’являється і тут. - Конфігурації лише в коді.
app.config.js/app.config.tsв Expo — це JavaScript, і їх не читають;app.jsonіpackage.jsonчитають. - Чи користуєтеся ви тим, що оголошуєте. Про залежність, яка є, але не використовується, однаково буде повідомлено.
- Вашого бекенда. Ніщо у файлі збірки не каже, що зберігає ваш сервер і як довго.
Це нагадування в момент, коли розкрити зміну найдешевше, а не вердикт щодо відповідності і не юридична порада.
Авторитетні джерела
- Надання інформації для розділу Data safety у Google Play — довідка Google Play Console: про точність форми і дані сторонніх SDK
- Відомості App Privacy в App Store — Apple: про актуальність відповідей і їх оновлення без оновлення застосунку
appfoyer/check-actionі@appfoyer/check— Action і npm-пакет, з описом того, що вони читають