# #522 — разрешения и продуктовые согласия Ничего не запрашивается пакетом при первом запуске. OS permission, серверный статус и продуктовый выбор — разные состояния. Прототип выводит системные сценарии **за рамку телефона**, с названием ОС и пометкой «симуляция». Ни одна кнопка не вызывает API браузера или ОС. ## iOS | Возможность / зачем | Когда | Системный механизм | Отказ / ограничение | Полезная альтернатива | Повторное включение | |---|---|---|---|---|---| | Город рядом / площадки поблизости | После «Рядом со мной», с кратким объяснением цели | Core Location / When In Use; purpose string. `notDetermined`, authorized, denied, restricted отдельно | Denied: не показывать prompt снова; restricted: не обещать возможность разрешить. Reduced accuracy — подтверждение города, без точных расстояний. Services disabled — отдельное состояние | Полный ручной выбор города/каталога | Явное «Открыть настройки устройства», по возвращении reread status; для restricted объяснить ограничение. Не автоматически считать grant | | Radar / видимость другим | Только в настройках Radar по инициативе человека | **Не OS permission**. Отдельный versioned product consent; координаты при необходимости — отдельный When In Use | Отказ сохраняет Radar OFF; granted location не включает видимость | Каталог игр/площадок и отдельно настроенный каталог игроков | Явное повторное включение/выключение в продукте; действующие сроки/eligibility сервера сохраняются | | Push / выбранные изменения | После заявки либо в настройках уведомлений | UNUserNotificationCenter authorization; alert/sound/badge по выбранной реализации. Не использовать provisional как незаметную замену согласия | Denied: core работает; authorized без server binding не означает доставку. Permission status не равен per-event consent | Мои игры / внутренний inbox, ручное открытие статуса | Явная ссылка на Settings; затем перечитать OS status, binding и preferences | | Фото профиля / выбранный файл | Нажал «Выбрать из фото» | Photos picker / PHPicker-compatible путь, конкретные items; полный Photo Library access не нужен для выбранного пути | Отмена ничего не меняет. Limited library учитывать, если fallback API вообще запрашивает Photos authorization; не требовать расширения | Профиль без фото; выбрать другой доступный объект | Снова открыть picker / manage selection. Settings только если используемый fallback действительно требует permission | | Камера / снимок аватара | Нажал «Сделать снимок» | Camera usage description и runtime access | Denied/restricted → без циклического prompt; не запрашивать microphone | Выбрать готовое фото либо оставить без фото | Явный путь к Settings, reread по возвращении | ## Android | Возможность / зачем | Когда | Системный механизм | Отказ / ограничение | Полезная альтернатива | Повторное включение | |---|---|---|---|---|---| | Город рядом / площадки поблизости | Только пользовательское «Рядом со мной» | Foreground location. Для города достаточно COARSE; FINE добавлять только при доказанной потребности точного nearby. Android 12+ approximate допустим | Denied vs permanently denied; rationale по API, не по счётчику нашего UI. Location services OFF отдельно. Одноразовый grant/auto reset требуют reread | Выбор города вручную, сохранённые фильтры | Если request ещё допустим — обоснованный запрос по действию; иначе app Settings. Проверить фактическое состояние после возврата | | Radar / показывать профиль | Явный отдельный product consent | Не Android permission; серверные настройки/eligibility | Геопозиция не даёт согласия на показ; отказ не мешает каталогам | Public discovery при фактических privacy settings | Отдельная настройка Radar, не bundled с OS dialog | | Push / нужные события | После полезного действия или из настроек | Android 13+: POST_NOTIFICATIONS. Более ранние версии: проверка OS notifications/channel status, не выдуманный prompt | Dismiss оставляет статус прежним; denial не блокирует вход/игру. Канал может быть выключен при общем grant | Мои игры / inbox | App/channel Settings, reread. Не повторять запрос после каждого входа | | Фото / выбранное изображение | «Выбрать из фото» | System Photo Picker; fallback документный picker при отсутствии поддержки, URI access на выбранное | Не требовать READ_MEDIA_IMAGES/широкий storage access для system picker. Selected photos/URI expiry обрабатывать как ограничение конкретного файла | Профиль без фото; повторный выбор | Снова picker. Persistable URI grants только при необходимости; копирование/загрузка в ограниченный app storage с очисткой | | Камера / снимок | «Сделать снимок» | CAMERA если используемый capture модуль требует; подход exact проверяется development build | Denied/permanently denied → picker/manual alternative. Только фото, без audio | Выбрать из фото / пропустить | Rationale либо Settings в зависимости от реального статуса | ## Отдельные состояния push 1. **Предпочтения пользователя:** события «Мои игры» и «Сообщения» независимы; существующие детальные event preferences/роли сервера не заменяются двумя общими флагами. В прототипе эти две группы — понятный обзор, новое массовое включение event types не предполагается. 2. **ОС:** разрешён ли показ на этом устройстве; на Android дополнительно channel settings. 3. **Токен/привязка:** зарегистрирован ли актуальный transport token за текущим account, environment и installation; не смешивать аккаунты и DEV/PROD. 4. **Доставка:** grant + binding не гарантируют receipt доставки/прочтения. Актуальный статус события читается из API. UI «Не удалось подключить устройство. Уведомления пока не приходят» обязателен при registration error даже после OS grant. «Повторить подключение» идемпотентно, без нового системного permission prompt. Отказ не включает таймер настойчивого re-prompt; предложение снова только из настроек пользователя или нового явно понятного контекста, с учётом OS статуса. Logout/revoke/account switch отзывают server binding и чистят private state, OS grant может остаться. При offline logout локальный доступ прекращается немедленно; серверный detach/revoke надо согласованно завершить, не обещать мгновенный сетевой эффект без ответа. Старый notification tap перечитывает права. Lockscreen payload нейтральный, без имён/сообщений/контактов; открытие требует нужной identity. ## Privacy invariants Новый активный профиль получает безопасное публичное имя «Игрок», каталог включён и contact requests. Старые opt-out не переписываются. Имя provider/account и email не копируются в public name. Radar OFF, отдельный product consent. Фото и уровень необязательны; уровень — самооценка. Это действующие defaults, не предлагаемый новый consent policy. Geo data из contextual запроса не превращается в публичную геолокацию. Background location / Always permission отсутствует. Точная политика retention и Radar transport берётся из текущих контрактов при соответствующем срезе; дизайн её не расширяет. ## Вне scope Контакты, микрофон, календарь, Bluetooth, Health/Fitness, рекламный tracking/ATT не нужны текущему onboarding. Не добавлять usage descriptions или requests «на будущее». Camera permission не включает microphone. Push permission не включает marketing consent. Права на выбранное изображение не заменяют проверку медиа, удаление EXIF и модерацию существующего backend. ## Платформенный UX iOS normal product screen может показать ручной выбор и «Определить город». Если engineering выделит dedicated pre-alert перед системным запросом, применить HIG: одна нейтральная кнопка продолжения, без имитации «Разрешить» и без вынужденного согласия. Android rationale привязывается к фактическому `shouldShowRequestPermissionRationale`, а не копируется буквально из iOS. Тексты system prompts в prototype-panel — ориентир purpose, не пиксельная копия реальной ОС. Actual localized OS wording и новые/старые версии проверяются на физических устройствах в M5. См. [источники](research.md) и [план](native-plan.md).