Не отправляйте тот же файл повторно: сначала сохраните статус и журнал notarytool, определите, произошёл ли сбой на этапе авторизации, подписи, упаковки или ticket, затем исправьте именно финальный дистрибутив. Статус Accepted тоже не означает завершённую публикацию — после него нужны staple, проверка Gatekeeper и установка в независимой среде.
Эта инструкция предназначена для вас, если вы распространяете приложение вне Mac App Store через DMG, PKG или ZIP с подписью Developer ID. Она также пригодится владельцам автоматизации на удалённом Mac и небольшим командам, которые выпускают приложения с плагинами, вспомогательными инструментами или другими вложенными исполняемыми файлами.
Временная шкала сбоя: что сохранить до любой новой попытки
Представьте типичную обезличенную ситуацию: notarytool вернул Invalid, а команда сразу изменила сертификат и загрузила новый архив. В результате исчезла связь между исходным файлом, журналом и причиной отказа. В другом варианте сервис показал Accepted, но скачанный DMG не устанавливается у пользователя. Это уже не одна и та же проблема: в первом случае нужно изучить решение сервиса, во втором — проверить ticket, упаковку и локальную политику Gatekeeper.
До повторной подписи сохраните:
- идентификатор отправки, замаскировав его в публичных логах;
- полный вывод команды без Apple ID, Team ID, адресов хостов и секретов;
- криптографический хэш финального ZIP, DMG или PKG;
- путь к выбранному Xcode и активной платформе разработчика;
- точное имя файла, его размер и время создания;
- копию исходного артефакта до любых изменений.
Apple описывает notarytool как актуальный командный инструмент для отправки программ на нотариальную проверку. В отдельной технической заметке Apple указывает, что altool перестал приниматься сервисом нотариальной проверки с 1 ноября 2023 года — поэтому старые инструкции с ним нельзя использовать как основу нового процесса. См. официальную заметку Apple о переходе на notarytool.
Важно: не удаляйте сертификат, не запускайте массовый сброс связки ключей и не заменяйте учётные данные до сохранения лога и резервного артефакта. Иначе вы можете устранить доступ к ключу, но потерять доказательство первоначальной причины.
Сразу разделите состояния: авторизация не прошла; загрузка не завершилась; заявка ещё обрабатывается; сервис вернул Invalid; сервис показал Accepted; ticket не прикрепился; конечный Mac блокирует файл. Для каждого состояния нужен свой следующий шаг, а не универсальный повторный запуск.
Первый рубеж: финальный файл против исходного проекта
Проверять нужно не только App в Xcode и не только результат Archive. Нотариальная проверка получает тот объект, который вы реально отправили: ZIP, DMG или PKG. Между экспортом архива, подписанием, упаковкой и загрузкой могли появиться новые изменения.
Разделяйте этапы:
- Build — компиляция компонентов;
- Archive — создание архива проекта;
- Export — получение приложения для распространения;
- Sign — подпись приложения и вложенного кода;
- Package — создание ZIP, DMG или PKG;
- Submit — передача финального объекта в
notarytool; - Accepted — решение сервиса;
- Staple — прикрепление ticket к поддерживаемому объекту;
- Gatekeeper — проверка поведения на машине пользователя.
Проверьте подпись приложения командой codesign, затем отдельно пройдите по вложенным объектам. В перечень обычно входят Framework, плагины, helper-программы, Login Item, XPC-службы и другие исполняемые компоненты. Для каждого важны корректная подпись Developer ID, Hardened Runtime, безопасная метка времени и допустимые entitlements. В справочнике Apple по устранению распространённых проблем нотариальной проверки эти классы ошибок рассматриваются отдельно.
Практический порядок проверки:
- Найдите именно тот App, который вошёл в финальный контейнер.
- Посмотрите, нет ли внутри старого или неподписанного исполняемого файла.
- Проверьте, что entitlements относятся к этому компоненту, а не были бездумно скопированы от другого target.
- Убедитесь, что включён Hardened Runtime там, где он требуется.
- Снимите подпись и хэш до упаковки.
- После создания ZIP, DMG или PKG снова зафиксируйте хэш и имя артефакта.
Подписанный Bundle нельзя безнаказанно изменять. Любое редактирование содержимого после проверки — даже замена ресурса, добавление конфигурации или вспомогательного файла — требует повторной проверки подписи и обычно новой отправки. Поэтому исправляйте источник, а не «лечите» уже принятый контейнер.
Почему подписанный App всё ещё получает Invalid?
Подпись подтверждает целостность и происхождение кода, но не доказывает, что весь дистрибутив соответствует требованиям нотариальной проверки. На практике отказ часто связан с вложенным компонентом, неподходящими правами или отсутствием безопасной метки времени.
Ошибка в подписи или сертификате
Проверьте, что используется именно сертификат Developer ID для распространения вне Mac App Store. Сертификаты Apple Distribution предназначены для другого канала публикации и не заменяют Developer ID в прямой раздаче.
Если журнал указывает путь к конкретному Framework или helper, начинайте с него. Не используйте рекурсивную подпись как способ скрыть структуру Bundle: она может переподписать не тот объект и затруднить откат. Сначала исправьте самый внутренний исполняемый файл, затем подпишите контейнер, а после этого — внешний App.
Ошибка get-task-allow
Entitlement get-task-allow предназначен для отладки и может сделать экспортированный дистрибутив непригодным для прямого распространения. Проверьте файл прав именно у экспортированного приложения, а не только настройки Debug target. Если вы удаляете entitlement, зафиксируйте предыдущую конфигурацию и оставьте возможность повторить экспорт без изменения исходного проекта.
Некорректный формат entitlements
Журнал может указывать на значение, которое не соответствует типу или разрешённому набору. Исправлять такую ошибку нужно в профиле подписи и настройках target, а не вручную редактировать уже подписанный Bundle. После изменения повторите экспорт и проверьте вложенные компоненты.
Отсутствует безопасная метка времени
Для распространения важна подпись с timestamp. Если журнал прямо указывает на её отсутствие, проверьте доступ к службе времени и параметры codesign, затем переподпишите все затронутые объекты. Не объявляйте причину по одному общему сообщению терминала: ориентируйтесь на первую конкретную ошибку из отчёта.
Как получить журнал notarytool после Invalid
После получения идентификатора отправки запросите сведения и журнал по нему. Команды должны выполняться с теми же обезличенными параметрами, которые использовались при отправке. Не вставляйте в статью, CI или общий чат реальные профили паролей, токены и идентификаторы команды.
Примерная последовательность выглядит так:
xcrun notarytool info SUBMISSION_ID \
--keychain-profile "NOTARY_PROFILE"
xcrun notarytool log SUBMISSION_ID \
--keychain-profile "NOTARY_PROFILE" \
notarization-log.json
Названия профиля и идентификатор здесь условные. В вашем журнале используйте собственные значения, но не публикуйте их вместе с секретами. Apple показывает рабочую схему получения статуса и журнала в документации по настройке процесса нотариальной проверки.
Ищите первый полезный объект: путь к файлу, тип нарушения, идентификатор компонента и конкретное описание. Последующие сообщения иногда являются следствием первой ошибки. Если лог указывает на Contents/PlugIns/..., не начинайте с DMG. Если он указывает на внешний пакет, сначала проверьте, как этот пакет создаётся и что именно он устанавливает.
Если статус долго остаётся в обработке
Не превращайте отдельный случай с длительной очередью в универсальное правило. Сначала проверьте корректность идентификатора и состояние сервиса Apple; для этого используйте официальную страницу состояния систем Apple. При подтверждённом сбое сервиса сохраните время, статус и исходный артефакт, а не запускайте бесконечные повторы.
Вторая сборка: подписывайте изнутри наружу
Ремонт цепочки должен идти от самого глубокого исполняемого объекта к внешнему контейнеру:
- Исправьте исходный компонент и его entitlements.
- Подпишите внутренние Framework, плагины, helper и XPC-службы.
- Подпишите основной App после вложенных компонентов.
- Проверьте подпись и timestamp.
- Создайте новый ZIP, DMG или PKG.
- Зафиксируйте хэш нового финального файла.
- Отправьте именно этот файл через
notarytool.
Такой порядок не следует подменять одной командой рекурсивной подписи. Рекурсивный режим полезен только тогда, когда вы понимаете структуру проекта и заранее контролируете исключения.
ZIP, DMG и PKG — не взаимозаменяемые оболочки. ZIP обычно отправляется как архив приложения. DMG является образом распространения, поэтому нужно проверить его содержимое и процесс прикрепления ticket. PKG может устанавливать дополнительные исполняемые файлы, Launch Agent или системные компоненты; их наличие влияет на требования к подписи и проверке. Рекомендации Apple по упаковке программ для распространения на Mac нужно сопоставлять с фактическим содержимым вашего установщика.
Если установщик размещает отдельные исполняемые объекты, не предполагайте, что одна операция над внешним контейнером автоматически закрывает все внутренние риски. Сначала определите, какие файлы устанавливаются, затем проверьте их подписи и только после этого формируйте финальный пакет.
Accepted — это контрольная точка, а не конец публикации
После Accepted получите финальный файл и выполните stapler там, где это поддерживается. Затем проверьте результат командой валидации. Для DMG и других контейнеров порядок зависит от формата и способа распространения, поэтому ориентируйтесь на официальную документацию, а не на старый скрипт из другого проекта.
Затем выполните пользовательскую проверку:
- скачайте настоящий файл, который будет размещён на сайте;
- установите его на Mac без вашего рабочего кэша;
- по возможности повторите проверку при ограниченном или отключённом доступе к сети;
- запустите оценку Gatekeeper;
- убедитесь, что приложение запускается после перемещения в обычную папку;
- проверьте отдельно установленные helper и Login Item.
Это отвечает на частый вопрос о staple: да, после Accepted его следует рассматривать как обязательную часть выпуска, если формат и сценарий распространения поддерживают прикрепление ticket. Даже при успешном Accepted пользователь может получить другой файл, повреждённый DMG или объект без ticket.
Опыт эксплуатации: проверяйте не архив из каталога сборки, а файл после загрузки с вашего CDN или сайта. Иначе вы легко подтвердите правильный локальный артефакт, пока пользователи скачивают старую упаковку.
Если локальная проверка успешна, а удалённый Mac ломает автоматизацию
Локальный и удалённый Mac могут использовать разные Xcode, разные активные Developer Tools, разные связки ключей и разные пользовательские сессии. Поэтому «на моём компьютере прошло» не доказывает воспроизводимость процесса.
Зафиксируйте в автоматизации:
xcode-selectили переменнуюDEVELOPER_DIR;- версию Xcode и путь к
xcrun; - источник профиля учётных данных;
- связь между номером заявки, хэшем и журналом;
- каталог временных файлов;
- таймаут ожидания и допустимое число повторов;
- условие остановки для ручного анализа.
SSH-сеанс и графическая сессия могут иметь разные переменные окружения, доступ к Keychain и состояние доверия. Если подпись выполняется в SSH, не переносите автоматически предположение, что GUI-сессия видит тот же профиль. Если процесс зависит от пользовательского Keychain, задайте явную процедуру разблокировки и безопасного отката, не сохраняя пароль в скрипте.
В течение первой недели после исправления проведите контрольный выпуск на непубличной версии. Оборвите SSH-сеанс, перезапустите задачу и проверьте восстановление по сохранённому идентификатору. Затем выполните полный цикл на следующем реальном релизе. Для постоянной среды полезны материалы о работе на удалённом Mac и отдельное планирование доступа к машине, а не только разовая ручная сессия.
Условия выбора: когда исправлять локально, а когда переносить выпуск
Используйте эту развилку перед изменением инфраструктуры:
- Если ошибка указывает на конкретный вложенный файл, оставьте среду прежней и исправьте Bundle изнутри наружу.
- Если локальная отправка проходит, но удалённый Mac выбирает другой Xcode, сначала зафиксируйте
DEVELOPER_DIR; переносить сертификаты преждевременно не нужно. - Если Developer ID и приватный ключ нельзя безопасно хранить на текущем компьютере, перенесите публикацию на изолированный постоянный Mac после резервного копирования и проверки отката.
- Если требуется только редкий релиз, не стройте сложную круглосуточную инфраструктуру: используйте контролируемую временную сессию.
- Если DMG или PKG проходит
Accepted, но блокируется у пользователя, не отправляйте его снова без изменений: переходите кstaple, Gatekeeper и проверке скачанного файла. - Если команда не может связать заявку, журнал и хэш, сначала восстановите трассировку, иначе каждая новая попытка будет усложнять диагностику.
| Этап | Что проверяете | Что считать результатом |
|---|---|---|
| Build | Собираются ли target и вложенные компоненты | Получен исходный артефакт |
| Archive / Export | Выбран ли правильный канал распространения | Создан App для Developer ID |
| Sign | Подпись, timestamp, Hardened Runtime, entitlements | Вложенный код проверяется отдельно |
| Package | Содержимое ZIP, DMG или PKG | Финальный файл не изменяется после проверки |
| Submit | Авторизация, загрузка, идентификатор заявки | Сохранены статус и журнал |
| Accepted / Staple | Решение сервиса и прикрепление ticket | Артефакт готов к локальной проверке |
| Gatekeeper | Реальный скачанный файл | Пользовательский сценарий подтверждён |
| Симптом | Вероятный слой | Первое действие |
|---|---|---|
| Не удаётся создать заявку | Авторизация или загрузка | Проверить профиль, путь и вывод notarytool |
Invalid с конкретным путём |
Подпись или вложенный код | Исправить первый объект из журнала |
Указан get-task-allow |
Entitlements | Повторить экспорт для распространения |
Accepted, но файл блокируется |
Ticket, контейнер или Gatekeeper | Проверить stapler и скачанный объект |
| Локально проходит, удалённо нет | Окружение | Сверить Xcode, Keychain и переменные |
| После изменения Bundle всё сломалось | Нарушена целостность подписи | Вернуться к исходнику и пересобрать |
| Вариант среды | Когда подходит | Основной риск |
|---|---|---|
| Локальный Mac | Редкие выпуски и ручная проверка | Нет постоянного журнала и стабильного окружения |
| CI или удалённый Mac | Повторяемые релизы и постоянный доступ к инструментам | Дрейф Xcode, сессий и Keychain |
| Изолированный удалённый Mac | Нужны Developer ID, приватный ключ и длительная автоматизация | Требуется резервирование и контроль доступа |
| Перенос на новую среду | Текущий компьютер нестабилен или недоступен | Без тестового релиза легко перенести старую ошибку |
Если ваш текущий компьютер не позволяет стабильно хранить приватный ключ Developer ID, выбранный Xcode и историю журналов, разумно сначала локализовать конкретную ошибку, а затем перенести подпись, нотариальную проверку и Gatekeeper-приёмку на изолированный постоянный Mac. По сравнению с локальной машиной, которую приходится делить с разработкой, такой подход убирает дрейф окружения и риск прерванной сессии; по сравнению с полностью эфемерной CI-средой, он оставляет доступ к реальной macOS-сессии и ручной проверке. Для временного или пилотного выпуска можно рассмотреть тарифы VMSPIN, а если нужен отдельный постоянный сценарий — изучить варианты заказа Mac. Перед переносом проверьте весь путь на непубличной версии: от Sign и Submit до staple, Gatekeeper и установки скачанного DMG или PKG.