1. Высокоуровневый взгляд на ревью-процесс
Публикация ChatGPT App в Store — это не «загрузил ссылку и забыл», а вполне живой цикл. В упрощённом виде он выглядит так: вы подготавливаете App, отправляете на ревью, ревьюеры гоняют его по своим чек‑листам, вы получаете замечания, дорабатываете и снова отправляете. И так несколько раз, пока всех всё не устроит.
Удобнее всего смотреть на это как на небольшой рабочий процесс (workflow):
flowchart TD A[Dev Mode / Internal beta] --> B[Submit to Store] B --> C[Under review] C -->|Approved| D[Published] C -->|Changes requested| E[Fixes & Iteration] E --> B D --> F[Updates] F --> C D --> G[Paused / Unpublished]
На ранних шагах (Dev Mode, внутренний бета‑тест) вы ловите технические и UX‑проблемы. Когда нажимаете «Submit to Store», начинается более формальное ревью: смотрят на соответствие политике контента, на пермишены, на стабильность и на то, что написано в листинге и юридических документах.
Полезно сразу принять философию: ревью — не экзамен, где вы либо «сдали» и больше никогда туда не вернётесь, либо «завалили». Это постоянный канал обратной связи между вами и платформой. Store хочет, чтобы ваш App был безопасным, понятным и стабильным, а вы хотите, чтобы вас пустили к пользователям и не сняли через неделю. Сюрприз: ваши интересы вообще-то совпадают.
2. Что вы отправляете на ревью
Перед тем как кто-то на стороне платформы откроет ваш App, вы заполняете довольно банальный набор сущностей:
- Метаданные App: название, подзаголовок, категория, иконка.
- Описание листинга: короткое и полное описание, примеры сценариев.
- Ссылки на Privacy Policy, Terms, Support/Contact.
- Настройки пермишенов: какие доступы запрашивает App (например, OAuth, внешние API, платёжные режимы и т.п.).
- Иногда — описание тестовых сценариев и учётных записей для ревьюера.
- Сам App: MCP‑сервер, UI‑бандл, system‑prompt и описания tools, которые платформа уже знает по Dev Mode/production‑URL.
Технически вы к этому моменту уже деплоите продакшен‑версию (обычно на Vercel или аналог), на которую Store и будет стучаться. То есть кнопка «Submit» — это не про деплой кода, а про смену его статуса: «этот код уже живёт на вашем продакшене, теперь, пожалуйста, проверьте его и пустите пользователей».
Чтобы связать все куски, обычно удобно иметь небольшой конфиг в репозитории, где вы явно фиксируете, что включено в версию «кандидата на ревью». Например, простая TypeScript‑структура:
// config/release-candidate.ts
export const releaseCandidate = {
version: "1.0.0",
apiBaseUrl: process.env.API_BASE_URL,
enableCommerce: true,
privacyPolicyUrl: "https://example.com/legal/privacy",
termsUrl: "https://example.com/legal/terms",
supportUrl: "https://example.com/support",
};
Такой файл не заменяет сам Store‑форму, но помогает вашей команде понимать, что именно вы сейчас «продаёте» ревьюерам и пользователям.
3. Как ревьюеры смотрят на ваш App
Итак, вы заполнили формы, подготовили ссылки и нажали Submit. Что происходит по ту сторону Store? Представьте, что вы сами ревьюер. Вы не видели ваш код, не знаете всей истории проекта, но у вас есть чек‑лист и ограниченное время. Обычно на App смотрят с нескольких ракурсов.
Во‑первых, смотрят на соответствие политике контента и бренду. Нельзя выдавать запрещённые категории, нарушать правила по медицине, праву или финансам без нужных дисклеймеров и «human in the loop». Нельзя притворяться OpenAI или использовать их бренд так, будто это их официальный продукт.
Во‑вторых, анализируют пермишены. Если вы просите доступ к чему‑то чувствительному (профили пользователей, платежи, сторонний аккаунт через OAuth), вас спросят: это действительно нужно? И понятно ли это пользователю по описанию и по поведению App? Идеальный случай — когда пермишены минимальны и равно соответствуют описанным сценариям.
В‑третьих, оценивают UX и стабильность. App не должен захватывать весь экран ChatGPT: если он без конца разворачивается в fullscreen по любому поводу, без понятного объяснения, это будет минус. Если backend регулярно кидает ошибки, а инструменты ломаются через раз, доверия тоже не будет.
Наконец, смотрят на честность листинга: совпадает ли описание App с тем, что ревьюер реально видит в чате. Если вы обещаете «молниеносный подбор идеального подарка и мгновенный checkout», а по факту App три раза падает на шаге поиска и не умеет оформлять заказы, ревью закончится быстро и грустно.
Чтобы ревьюерам было проще, имеет смысл заранее подготовить им «маршрут»: список шагов, которые стоит попробовать, и какие ожидаемые результаты. Это же будет полезно и для вашей собственной регрессии.
Простейший пример такого описания в коде — структура с тестовыми сценариями, на которую можно ссылаться во внутренней документации:
// test/review-scenarios.ts
export const reviewScenarios = [
{
id: "gift-basic",
title: "Подбор подарка без покупки",
steps: [
"Попросить: Подбери подарок для друга, любит настольные игры, бюджет 50$",
"Убедиться, что App предлагает варианты и не требует логина",
],
},
{
id: "gift-checkout",
title: "Подбор подарка с тестовым checkout",
steps: [
"Выбрать любой подарок из списка",
"Перейти к оформлению, используя тестовую карту",
],
},
];
Эта структура не уходит в Store напрямую, но она дисциплинирует вашу команду и позже помогает обновлять описание для ревьюеров и техподдержки.
4. Тестовые аккаунты и данные: без них ревью не полетит
Как только в дело вступают деньги, личные данные или внешние аккаунты, ревьюеры ожидают, что вы предоставите безопасный способ пройти весь сценарий без использования их настоящей карты, личной почты или реального Slack/Google/чего‑угодно.
Условно можно выделить два больших типа тестовых сущностей.
Первый тип — тестовые пользователи/организации в вашей системе. Например, для GiftGenius вы можете завести специальную «ревью‑организацию» с заранее подготовленным демо‑каталогом и привязенными тестовыми платёжными методами в sandbox‑режиме платёжного провайдера. Важно, чтобы ревьюер не проходил сложный онбординг: по идее, он должен получить логин/пароль или магическую ссылку и сразу оказаться в готовой песочнице.
Второй тип — тестовые данные внешних провайдеров. Платежи, как правило, имеют sandbox‑режим (test cards, test accounts). Если ваш App делегирует оплату через ACP/Instant Checkout, вы должны быть уверены, что он использует тестовую среду в ревью и никто не платит реальными деньгами. Это уже затрагивает архитектуру commerce‑части, но идея проста: добавить в бэкенд флаг «review/test mode».
В терминах кода это может выглядеть как простой флаг окружения и config:
// config/env.ts
export const env = {
nodeEnv: process.env.NODE_ENV,
reviewMode: process.env.REVIEW_MODE === "true",
paymentProviderEnv: process.env.REVIEW_MODE === "true" ? "sandbox" : "production",
};
А в месте, где вы инициализируете клиента платёжной системы:
// lib/payments/client.ts
import { env } from "@/config/env";
export const paymentClient = createPaymentClient({
environment: env.paymentProviderEnv, // "sandbox" или "production"
apiKey: process.env.PAYMENT_API_KEY!,
});
Такая мелочь сильно облегчает жизнь: вы можете запускать App в режиме, максимально похожем на продакшен, но при этом ревьюеры не трогают настоящие деньги.
Отдельно стоит продумать тестовые сценарии для интеграций вроде Gmail, Slack, Notion и т.п. Там, где используется OAuth, ревью часто ожидает либо общий demo‑аккаунт, либо очень простую инструкцию, как создать тестовый workspace. Старайтесь избегать сценариев «напишите на support, мы вручную вам что‑то включим» — ревью часто автоматизировано и лимитировано по времени, и ждать вашего письма никто не будет.
5. Типичные замечания от ревью и как на них реагировать
Теперь, возможно, неприятная новость: вероятность того, что ваш первый проход через ревью будет идеальным, близка к вероятности того, что программист сразу написал код без багов. То есть где‑то в районе нуля. И это нормально.
Замечания чаще всего попадают в несколько предсказуемых категорий.
Первая категория — пермишены и приватность. Например, вы запрашиваете доступ к email пользователя, но в листинге не объясняете, зачем. Или в Privacy Policy написано, что вы «не храните данные чата», а логи MCP‑сервера спокойно пишут весь запрос вместе с PII. Ревьюер может попросить либо уточнить документы, либо изменить поведение App, либо и то, и другое.
Вторая категория — UX и поведение в чате. App может «захватывать» диалог: агрессивно открывать fullscreen там, где можно обойтись inline, не оставлять текстового резюме после действий, не давать пользователю понятного способа «вернуться к чату». В таких случаях от вас, скорее всего, попросят упростить UX и уважать основной диалоговый интерфейс ChatGPT.
Третья категория — стабильность и ошибки. Если при типовых сценариях App регулярно выдаёт «Error talking to app» или внутренние 500‑ки, ревью может остановиться до тех пор, пока вы не покажете, что это единичный случай, а не норма. Здесь от вас ждут не только фикса багов, но и минимальной наблюдаемости: логов, health‑чеков, разумных таймаутов.
Четвёртая категория — честность листинга и маркетинговых обещаний. Если вы в описании обещаете больше, чем умеете на самом деле, ревьюеры обычно довольно быстро это замечают, особенно если вы обещаете «гарантированные результаты» в чувствительных доменах. Исправление в этом случае состоит из двух шагов: либо уменьшаете обещания, либо увеличиваете реализацию (чаще всё‑таки первое).
Как правильно реагировать на замечания? Главное правило — относиться к ревью как к партнёрству, а не к «злобным модераторам». В ответе полезно:
- Чётко признать проблему: «Да, в текущей версии App делает X, а в описании написано Y».
- Описать, что вы уже изменили: «Мы скорректировали листинг и обновили Privacy Policy, уточнив, что…».
- По возможности приложить короткое описание тестового сценария, где ревьюер увидит исправление.
Если вы явно не понимаете, почему прилетело замечание, лучше задать уточняющий вопрос, а не пытаться угадать. Например: «Правильно ли мы понимаем, что основная проблема в том, что App автоматически разворачивается в fullscreen без запроса пользователя?».
6. Внутренний чек-лист перед отправкой на ревью
Чтобы сократить количество итераций, полезно завести собственный «pre‑flight чек‑лист» по мотивам модулей 7, 15–17. Это не список «для галочки», а вполне практическая штука, которую вы реально проходите перед каждым сабмитом.
Технически вы можете даже зашить этот чек‑лист в репозиторий как небольшой JSON/TS‑модуль и прогонять его в README или в пайплайне.
Простейший вариант на TypeScript может выглядеть так:
// tools/review-checklist.ts
export interface ChecklistItem {
id: string;
description: string;
done: boolean;
}
export const reviewChecklist: ChecklistItem[] = [
{
id: "ux-inline-first",
description: "Основные сценарии App работают в inline-режиме, fullscreen только там, где он реально оправдан.",
done: false,
},
{
id: "privacy-links",
description: "Ссылки на Privacy Policy, Terms, Support валидны и открываются без авторизации.",
done: false,
},
{
id: "permissions-minimal",
description: "Запрошены только минимально необходимые пермишены; каждый описан в листинге.",
done: false,
},
];
А в каких‑то своих внутренних тулзах или просто в консоли вы можете выводить этот список и отмечать прогресс. Это, конечно, не обязательная автоматика, но программисты традиционно лучше дружат с кодом, чем с Google Docs, так что почему бы не использовать привычный инструмент.
7. Итерации и версионирование: жизнь после первой публикации
Сюрприз номер два: даже после того, как ваш App прошёл ревью и стал доступен пользователям, процесс не заканчивается. Любое существенное обновление может снова триггерить проверку, особенно если вы меняете пермишены, добавляете новые чувствительные сценарии или радикально переделываете UX.
Поэтому стоит относиться к ChatGPT App как к живому продукту с нормальным release‑процессом, а не как к «последнему выстрелу».
Обычно разумный минимум такой: у вас есть версия в коде (semver), журнал изменений (changelog) и представление, какие релизы тянут за собой необходимость повторного ревью, а какие — нет. Например, правка опечаток в UI, не затрагивающая поведение App и пермишены, может пройти тихо, а переход от «только рекомендации» к «полноценному checkout с оплатой» точно потребует нового внимания.
В коде это может выглядеть как простая константа и объект с изменениями:
// config/app-version.ts
export const appVersion = "1.1.0";
export const appChangelog = {
"1.1.0": [
"Добавлен sandbox-checkout для тестовых пользователей",
"Уточнено описание пермишенов в листинге",
],
"1.0.0": ["Первая публичная версия GiftGenius без оплаты"],
};
И да, здорово, если вы синхронизируете эти заметки с тем, что пишете в релиз‑нотах Store. Тогда и ревьюерам, и пользователям проще понимать, что произошло.
8. Коммуникация с платформой: как не поссориться с ревьюерами
Возможно, самый недооценённый навык — нормально разговаривать с ревьюерами. Как правило, фидбек приходит в виде набора тезисов: что не так, на какие пункты политики вы налетели, какие участки UX вызывают вопросы. Хороший ответ — это не «Да вы ничего не понимаете», а спокойное и конкретное сообщение.
Стоит держать в голове несколько простых принципов.
Во‑первых, ясность. Не пишите километровых эссе о том, как устроена внутренняя архитектура вашего MCP‑сервера и почему он такой красивый. Ревьюера интересует прежде всего пользовательский опыт и соответствие политике. Достаточно коротко описать, что вы изменили и как теперь можно это проверить.
Во‑вторых, прозрачность. Если проблема сложнее, чем «мы поправили текст», и требует существенных переделок, честнее написать: «Это замечание затрагивает ключевую часть нашего checkout‑флоу, нам потребуется 1–2 недели на корректное исправление. Мы пришлём обновлённую версию как только она будет готова».
В‑третьих, память. Замечания ревью стоит сохранять не только в почте или во внутреннем трекере, но и в виде небольшого «решения» в документации: что именно было нельзя и почему. Это помогает новым разработчикам и продакту не наступать на те же грабли. Здесь может помочь простая внутренняя заметка в документации или даже README‑секция вида «Store Review Decisions».
9. Связь с архитектурой и предыдущими модулями
Полезно посмотреть на ревью‑процесс как на «интегральную проверку» всего, что вы делали в предыдущих модулях.
Без модулей по безопасности и пермишенам (7, 15) у вас, скорее всего, будут вопросы по доступам, работе с PII, OAuth и destructive actions.
Без модулей по стабильности и наблюдаемости (16, 17) вы не сможете внятно ответить, почему App иногда падает, а иногда нет, и как вы за этим следите. Метрики и SLO превращаются из теории в аргументы: «мы видим p95 < 2 секунд для основного инструмента и error rate < 1% за последние N дней».
Без UX‑модулей (8, 11) App может просто «ломать» чат: fullscreen там, где он не нужен, непонятные переходы между режимами, отсутствие текстового резюме. Ревьюеры эти вещи видят быстрее, чем вы, потому что тестируют много разных App и хорошо чувствуют, когда кто‑то «борщит».
И наконец, без сегодняшнего понимания процесса ревью вы рискуете просто застрять на стадии «мы отправили, нам вернули, мы обиделись». Правильнее относиться к этому как к ещё одному циклу итераций, очень похожему на вашу внутреннюю регрессию, только с ещё одним заинтересованным участником — платформой.
В итоге, если у вас есть вменяемый чек‑лист, тестовые аккаунты и sandbox‑режим, базовая наблюдаемость и нормальная коммуникация с ревьюерами, процесс ревью перестаёт быть лотереей. Это просто ещё один итеративный цикл вокруг вашего ChatGPT App — такой же естественный, как регрессия перед релизом или код‑ревью внутри команды.
10. Типичные ошибки при прохождении ревью
Ошибка №1: Отправить App «как есть» без внутреннего чек-листа.
Многие команды нажимают «Submit» сразу после того, как App «заработал» в Dev Mode. В результате на ревью всплывают базовые вещи: битые ссылки на Privacy/Terms, неработающие сценарии, отсутствие тестовых аккаунтов. Лечится простым внутренним чек‑листом, который вы реально проходите перед каждым сабмитом (валидные ссылки, минимальные пермишены, рабочие ключевые сценарии) — пример такого чек‑листа мы как раз разобрали выше в разделе «Внутренний чек‑лист перед отправкой на ревью».
Ошибка №2: Игнорировать тестовые аккаунты и sandbox-режимы.
Отправлять на ревью App, который требует реальной банковской карты ревьюера — плохая идея. Так же плохо, если checkout теоретически есть, но ревьюер не может его протестировать вообще. Нужно заранее продумать тестовые organization/user в вашей системе и sandbox‑режим платёжного провайдера, привязанный к REVIEW_MODE или аналогичному флагу.
Ошибка №3: Пытаться «выторговать» исключения вместо того, чтобы исправить проблему.
Иногда разработчики начинают спорить с ревьюером: «но у конкурентов же так же» или «это ограничение платформы, мы тут ни при чём». Такой стиль редко помогает. Гораздо эффективнее переформулировать сценарий, упрощать UX, уменьшать пермишены и править листинг так, чтобы он честно отражал поведение App.
Ошибка №4: Не документировать замечания и решения.
Если вы получили комментарий от ревью и просто «пофиксили баг в коде», не записав, что именно было нельзя, через полгода кто‑то в команде снова сделает то же самое. Лучше вести небольшой реестр решений ревью: «Нельзя автоматически разворачивать fullscreen без явного действия пользователя», «нельзя хранить полные тексты чатов дольше N дней без явного указания в Policy» и т.п.
Ошибка №5: «Большие релизы» без поэтапной стратегии.
Пытаться за один релиз добавить и оплату, и новые пермишены, и новый UX, и переработанный backend — хороший рецепт для долгих итераций ревью. Намного спокойнее выходить маленькими шагами: сначала рекомендации без оплаты, потом — sandbox‑checkout, потом — полноценный платежный флоу. Так вы и риски снижаете, и аргументов на ревью становится меньше.
Ошибка №6: Опираться на приёмку Store вместо своей QA и наблюдаемости.
Иногда команда подсознательно ждёт, что ревьюеры «протестируют за них». В результате ревью превращается в бесплатный QA, но затягивает запуск на недели. Гораздо здоровее относиться к ревью как к финальной sanity‑проверке уже довольно зрелого продукта, у которого есть свои тесты, логи, метрики и понятные сценарии.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ