1. Что такое ChatGPT Store в контексте курса
Начнём с картины мира. ChatGPT Store — это каталог приложений внутри ChatGPT, куда пользователь может зайти, найти ваш App, включить его и использовать в обычных диалогах. Для вас это не просто витрина, а канал дистрибуции с правилами, аналог «App Store» для мира LLM.
В этом курсе мы различаем три режима жизни вашего App:
- Первый режим — Dev Mode. Ваш App привязан к вашему аккаунту/организации, доступен вам и, возможно, коллегам. Формального ревью нет, но действуют все общие политики платформы. Здесь вы спокойно ломаете всё, логируете всё подряд, гоняете туннели и staging‑бэкенды.
- Второй режим — публичный Store. Это высшая лига: App доступен всем пользователям ChatGPT (с учётом региональных ограничений), проходит модерацию, имеет публичный листинг, ссылки на Privacy/Terms и уже должен вести себя как взрослый продукт.
- Третий — org‑only Apps. Это приложения только для одной организации: компания может включать/выключать их для сотрудников, накручивать свои требования безопасности поверх требований OpenAI и даже проводить внутреннее ревью.
В этой лекции нас интересует именно связка «публичный Store + публичный листинг». Важный момент: вы перестаёте быть просто разработчиком «ещё одного Next.js‑сервиса» и превращаетесь в автора продукта, который должен понравиться сразу трём сторонам: пользователям, модераторам Store и вашей службе безопасности.
2. Базовые требования Store: политика, честность и UI
Контент и политики
ChatGPT Store — модераируемая платформа. Если грубо: OpenAI не хочет, чтобы внутри ChatGPT появлялись приложения, которые нарушают политики использования платформы (насилие, терроризм, NSFW, мошенничество и т.п.) или пытаются обойти защиту моделей (jailbreak‑промпты «сделай вид, что ты не ChatGPT, а мой злой двойник»).
Это означает две вещи.
Во‑первых, ваш App сам по себе не должен генерировать запрещённый контент. Если наш примерный App GiftGenius (подбор подарков) вдруг начинает предлагать подарки «как скрыть следы преступления», модерации хватит одного скриншота.
Во‑вторых, ваш App не должен помогать пользователю обходить фильтры. Если пользователь просит: «Подбери подарок, чтобы сделать бомбу», корректное поведение — отказ с опорой на политику, а не радостное использование вашего MCP-tool для поиска нужных деталей.
Значительная часть этого поведения задаётся system‑prompt’ом и тем, какие инструменты вы предоставляете модели. Но Store смотрит на итог: какие ответы реально может получить пользователь.
Бренд и домен
Следующий пласт — бренд и домен. Публичный App должен быть привязан к вменяемому владельцу. Для App, у которого есть внешний backend/MCP, от вас ожидается:
Проверка домена (Domain Verification). Вы добавляете TXT‑запись в DNS вашего домена, и Store убеждается, что backend действительно принадлежит вам. Анонимные штуки на бесплатном ngrok‑URL либо не пройдут в публичный Store, либо будут помечены как низко доверенные.
Адекватное имя и лого. Нельзя называться «ChatGPT Super Weather» или «Official OpenAI Something» — использование «GPT / OpenAI / ChatGPT» в начале названия или копирование фирменного стиля OpenAI попадает под бренд‑ограничения. Придумывайте своё имя (GiftGenius — хороший пример) и свой визуальный стиль.
UI/UX: не ломать ChatGPT
В отличие от «старых» плагинов, теперь App может отрисовывать свой UI‑виджет прямо в чате. Это даёт много возможностей… и много способов всё испортить.
У Store есть простая идея: виджет должен чувствоваться «нативным» по отношению к ChatGPT. Шрифты, отступы, цвета, поведение в тёмной/светлой теме и на мобилке — всё должно выглядеть аккуратно, без ощущений, что вы встроили в чат рекламный баннер или целую отдельную SPA.
Также Store не любит UI, который захватывает чат: огромные полноэкранные «присоски», модальные окна «подпишись немедленно», автоскроллы и прочие агрессивные паттерны. Ваш виджет — это карточка/мастер/инструмент внутри диалога, а не собственная вселенная.
По сути, модерация смотрит на три вещи: не нарушаете ли вы контент‑политику, не вводите ли в заблуждение (про это — отдельный блок ближе к концу лекции, когда будем говорить про листинг и соответствие манифесту) и не превращаете ли ChatGPT в рекламную помойку с плохим UX. Под «честностью» здесь будет иметься в виду соответствие между тем, что App реально умеет, и тем, что вы про него заявляете в описании и UI.
3. Как Store видит пермишены вашего App
Отдельная большая ось требований — то, какие права вы запрашиваете у пользователя и внешних систем. Здесь Store смотрит не только на безопасность, но и на то, насколько эти права соответствуют заявленной ценности приложения.
Теперь — самое вкусное для инженера: модель пермишенов. В контексте Apps SDK и MCP у вас три основных уровня доступа.
Для наглядности удобно изобразить это так:
graph TD
A[Манифест/конфиг App] --> B[Model capabilities]
A --> C[OAuth scopes]
A --> D[MCP tools & ACP]
D --> E[Уровень подтверждения пользователя]
Model capabilities — это строго говоря не «пермишены» в том же смысле, что OAuth-scopes или write-tools, а набор встроенных возможностей модели. Но для проектирования безопасности их удобно считать первым уровнем доступа, который тоже нужно минимизировать.
Уровень 1: model capabilities
Это то, что модель может делать «сама по себе», без обращения к вашему backend’у: веб‑браузинг, генерация картинок DALL‑E и т.п.
Если включить и браузинг, и MCP-tools, модель иногда может решить, что задачу проще решить через веб-поиск, а не через ваш специализированный инструмент — особенно если описания tools расплывчатые или приоритеты не заданы в промпте. Поэтому, если App и так ходит в ваш API через MCP, имеет смысл либо попробовать выключить browsing, либо в промпте чётко зафиксировать приоритет MCP-tools.
То есть на этом уровне вы уже применяете принцип минимальных пермишенов: выключаете всё, что не нужно для реальной ценности App.
Уровень 2: OAuth scopes
Если ваш App использует аутентификацию (Модуль 10), вы запрашиваете скоупы у внешнего провайдера: openid, email, profile, orders.read, orders.write и т.д.
Здесь принцип минимализма особенно важен:
- Если вам нужно просто различать пользователей, чаще всего хватает openid (анонимный идентификатор), и email вообще не нужен.
- Если email всё‑таки нужен, то это должно быть прозрачно в UX и в описаниях пермишенов: «нужен, чтобы отправить вам чеки и напоминания по заказам», а не «просто на всякий случай».
Плюс мы стараемся делать авторизацию «по требованию»: сначала даём пользователю попробовать базовые функции без логина, а просим доступ только когда он реально хочет, например, «сохранить подборку подарков в избранное» или «посмотреть историю заказов». Это снижает трение и повышает конверсию.
Пример конфигурации скоупов для MCP‑tools (упрощённо):
// server/mcp/config/auth.ts
export const OAUTH_SCOPES = {
basic: ["openid"],
orders: ["openid", "orders.read"],
checkout: ["openid", "orders.read", "orders.write"]
};
Уровень 3: MCP‑tools и «consequential» действия
Третий уровень — это ваши MCP-инструменты и ACP/Instant Checkout. Каждый tool в MCP-сервере может быть:
- только читающим (read‑only): получить курс валют, подобрать подарки, посмотреть каталог;
- меняющим состояние (consequential): создать заказ, отправить письмо, списать деньги.
От инструментов второго типа Store ожидает более строгую модель подтверждения. Идея такова: не всё можно вызывать «просто так». В терминах платформы это обычно выражается через флаг consequential: true и политику подтверждения (always_allow против ask_user).
Пример регистрации MCP‑инструмента с указанием security‑schemes и того, что это изменяющее действие:
// server/mcp/tools/createOrder.ts
server.registerTool(
"create_order",
{
title: "Create order",
description: "Создаёт новый заказ в GiftGenius.",
inputSchema: {
type: "object",
properties: {
productId: { type: "string" },
quantity: { type: "integer", minimum: 1 }
},
required: ["productId", "quantity"]
},
_meta: {
securitySchemes: [{ type: "oauth2", scopes: ["orders.write"] }]
},
// псевдо-поле, идея: это действие меняет состояние
consequential: true
},
async ({ input, security }) => {
// ... логика создания заказа
}
);
Пример скоупов и security‑schemes взят из официальной документации по MCP-tools, где инструменты могут быть либо без авторизации, либо защищёнными OAuth2.
С точки зрения Store это превращается в понятный текст «Это приложение может создавать и управлять заказами в магазине GiftGenius» и, возможно, отдельный шаг подтверждения.
4. Пермишены глазами пользователя и модератора
Для нас, инженеров, App — это манифест, MCP-сервер и куча TypeScript. Для Store это набор фактов: что App может сделать с данными пользователя и с внешним миром.
Можно представить такую таблицу:
| Уровень доступа | Пример для GiftGenius | Как это увидит Store/пользователь |
|---|---|---|
| Model capabilities | Browsing: off, DALL‑E: off | «App не ходит сам в интернет, не генерит медиа» |
| OAuth scopes | openid, orders.read | «Считывает ваши заказы в GiftGenius‑аккаунте» |
| Read‑only MCP tools | search_products, get_price_history | «Просмотр каталога и цен» |
| Consequential MCP tools | create_order, cancel_order | «Создание и отмена заказов» |
Ключевая идея: каждый технический элемент должен маппиться на понятное человеку действие. В планах модуля это прямо сформулировано: технический MCP-tool get_user_orders превращается в листинге в текст «Просмотр списка ваших заказов в нашем магазине».
Если вы не можете объяснить пермишен одним‑двумя предложениями — это тревожный сигнал. Возможно, вы либо просите лишнее, либо смешали несколько разных задач в одном App.
5. Принцип минимально необходимых пермишенов
В обычном бэкенд‑мире принцип PoLP (Principle of Least Privilege) часто воспринимают как «ну да, надо как‑нибудь ограничить роли в БД, сделаем потом». В ChatGPT Apps это не «потом», это критерий попадания в Store и фактор конверсии пользователей.
Важные моменты:
- Чем меньше прав просит App, тем выше базовое доверие пользователя. Диалог внутрь ChatGPT — это пространство, где пользователь ожидает определённого уровня приватности. App, который внезапно просит доступ ко всему аккаунту, платежам и контактам, выглядит подозрительно.
- Чем понятнее и уже пермишены, тем проще ревьюеру. Модератору нужно быстро понять, что App делает и насколько это соотносится с политиками и лучшими практиками безопасности. Over‑permissioned Apps — типичный кандидат на «отложить и запросить уточнения», а иногда и на отказ.
- Чем более минимальный и «just‑in‑time» доступ вы реализуете, тем мягче UX. Auth‑экран — это сильный момент трения. Если App даёт полезный опыт ещё до авторизации (например, показывает топ‑подарки без привязки к пользователю), пользователь охотнее согласится на расширенные возможности позже.
Поэтому «минимальные пермишены» в Store — это не только про безопасность, но и про маркетинг и рост. В модуле 18 отдельно подчёркивается, что минимальные пермишены — это конкурентное преимущество, а не бюрократическая формальность.
6. Примеры: пермишены GiftGenius до и после «диеты»
Чтобы это не оставалось абстрактной теорией, давайте возьмём нашего условного героя — GiftGenius. Представим, что вы проектировали его «по максимуму» и получили такой список нужных возможностей:
- Читать каталог товаров и фильтровать подарки.
- Видеть историю заказов пользователя.
- Создавать новые заказы и отменять существующие.
- Сохранять «избранные подборки» в аккаунте пользователя.
- Отправлять email‑уведомления о скидках.
На уровне конфигурации это может выразиться так:
// server/mcp/config/permissions-naive.ts
export const PERMISSIONS_NAIVE = {
capabilities: { webBrowsing: true, dalle: false },
oauthScopes: ["openid", "email", "orders.read", "orders.write"],
tools: {
searchProducts: { consequential: false },
getUserOrders: { consequential: false },
createOrder: { consequential: true },
cancelOrder: { consequential: true },
saveFavoriteList: { consequential: true },
sendDiscountEmail: { consequential: true }
}
};
На бумаге такой набор кажется логичным («рано или поздно всё это пригодится»), но для первого релиза в Store это перебор:
- Вам не обязательно сразу читать историю заказов. Можно ограничиться одноразовой подборкой и безопасным checkout через ACP/Instant Checkout, где платёжка и так под контролем платформы.
- Email‑уведомления — вообще отдельная песня: для них нужно и хранение email, и объяснение в Privacy Policy, и обработка отписок. Для MVP GiftGenius это почти всегда избыточно.
С учётом принципа минимизации вы можете собрать минимальный стартовый набор пермишенов:
// server/mcp/config/permissions-v1.ts
export const PERMISSIONS_V1 = {
capabilities: { webBrowsing: false, dalle: false },
oauthScopes: [], // без логина, работаем анонимно
tools: {
searchProducts: { consequential: false },
createOrder: { consequential: true }
}
};
В такой версии:
- App не «лезет» в аккаунт пользователя, не читает его историю, не шлёт email.
- Все чувствительные операции (создание заказа) идут через ACP/Instant Checkout, где пользователь и так видит стандартный платёжный флоу.
В листинге можно честно написать: «Подбирает подарки и создаёт заказы в магазине GiftGenius. Приложение не хранит историю ваших чатов и не рассылает email‑уведомления». Это приятно и пользователю, и ревьюеру.
Позже, когда у вас появится стабильный трафик и доверие, можно выпустить обновление с дополнительными пермишенами (история заказов, избранное) и соответствующим обновлением листинга и Privacy Policy.
7. Как описывать пермишены в листинге
Манифест и конфигурация — это язык машины. Модератор и пользователь читают совсем другой текст: название, описание, блок «Что может делать это приложение» и ссылки на Privacy/Terms.
В модуле 17 подчёркивается мэппинг: технические scopes и инструменты → человеко‑понятные действия.
Для GiftGenius v1 мы могли бы оформить это так.
Технически:
- Browsing: off
- DALL‑E: off
- MCP tools: search_products (read‑only), create_order (consequential)
В листинге:
- «Подбирает подарки по вашему описанию или параметрам (пол, возраст, бюджет, интересы).»
- «Может создавать заказы в магазине GiftGenius через защищённый checkout внутри ChatGPT.»
- «Не запрашивает доступ к вашему email или истории заказов, не отправляет уведомления.»
Если позже добавим OAuth‑логин и orders.read, описание честно обновится:
- «При подключении аккаунта GiftGenius может просматривать ваши прошлые заказы, чтобы давать более персональные рекомендации.»
Очень важно не обещать того, чего App не делает, и не умалчивать критичные действия. Вся документация собранная для модуля 18 прямо подчёркивает: информация в листинге должна точно соответствовать реальному поведению, особенно для чувствительных вещей вроде платежей и PII.
8. Связь требований Store с вашей архитектурой
Важно видеть, что требования Store не существуют в вакууме. Все эти требования — не «ещё одна форма от маркетинга». Store по сути проверяет то, что вы уже делали в модулях по безопасности и продакшену:
- Если вы настраивали OAuth и делали аккуратные .well-known‑эндпоинты и проверку токенов, будет странно, если App вдруг запросит у пользователя пол‑интернета через широкие скоупы. Такой App легко завалится на ревью как over‑permissioned.
- Если вы честно реализовали политику retention и PII‑scrub, вам будет проще написать правдивую Privacy Policy и выдержать проверку. Store и пользователи могут перейти по ссылке и сопоставить ваши обещания с реальными процессами.
- Если вы хорошо отладили стабильность MCP-сервера, логи и метрики (модули про observability и SLO), у ревьюеров будет меньше вопросов по производительности и ошибкам инструментов.
Минимальные пермишены красиво дополняют эту картину: вы не только безопасны и стабильны, но и «скромны» в запросах к данным пользователя.
9. Мини‑практика по ходу лекции
Чтобы не только теоретизировать, разберите прямо сейчас ваш текущий App (или GiftGenius) по шагам.
Сначала выпишите все реальные действия, которые App умеет делать. Например: «подобрать подарки», «создать заказ», «показать историю», «сохранить в избранное», «отправить письмо коллегам». Это лучше сделать обычным текстом, не думая ещё о технических деталях.
Дальше для каждого действия ответьте себе: «Какие данные пользователя это затрагивает?» и «Изменяет ли это состояние во внешней системе?». Так вы автоматически разделите действия на read‑only и consequential.
После этого сопоставьте действия с уровнями пермишенов: где нужны только model capabilities, где — OAuth‑скоупы, а где — MCP-tools с флагом consequential: true и, возможно, с подтверждением пользователя.
И теперь сыграйте в «ножницы»: что можно выбросить из первого релиза, не убив основную ценность? Часто оказывается, что без истории, избранных и email‑уведомлений App всё равно делает своё главное дело. А значит, эти пермишены можно оставить на версию 1.1 или 2.0.
10. Типичные ошибки с требованиями Store и пермишенами
Ошибка №1: «Сделаем супер‑App, который делает всё, а Store разберётся».
Разработчик описывает App как универсального ассистента («помогу с финансами, медициной, юриспруденцией и покупками»), подключает десяток MCP-tools и просит максимальные права. Такой App одновременно лезет в чувствительные домены (медицина/финансы/право), запрашивает много данных и нарушает принцип «one job per app». Результат предсказуем: модерация задаст много вопросов или просто завернёт. Лучше сделать несколько узких App с чёткими пермишенами.
Ошибка №2: Over‑permissioned auth «на всякий случай».
Классика: App просит email, profile, orders.read, orders.write, billing.read, хотя по факту нужно только «подобрать подарок по описанию». С точки зрения пользователя это выглядит как жадный сборщик данных, с точки зрения Store — как рискованное приложение. В документации по безопасности Apps это прямо приводится как пример плохой практики.
Ошибка №3: Несоответствие манифеста и листинга.
В манифесте у вас есть create_order, cancel_order и доступ к платёжным операциям, а в описании вы пишете только «рекомендует подарки». Рано или поздно кто‑то из ревьюеров или пользователей заметит, что App умеет больше, чем заявлено. Это подрывает доверие и может привести к снятию App из Store.
Ошибка №4: Попытка скрыть чувствительные действия за «безобидным» UI.
Например, вы рисуете в виджете кнопку «Сохранить подборку», которая на самом деле шлёт письмо всем в отдел или создаёт задачи в чужой системе, не объясняя этого в пермишенах. Store не любит сюрпризы. В руководствах для разработчиков прямо сказано: приложение должно делать ровно то, что обещано, без скрытого поведения.
Ошибка №5: Просьба о логине «на входе», когда можно обойтись без него.
App запускается — и сразу просит подключить аккаунт, выдать доступ ко всему, а то «иначе не работает», хотя половину сценариев вполне можно реализовать анонимно. Это бьёт по конверсии и создаёт впечатление, что вы торопитесь собрать данные, а не дать ценность. Гораздо лучше сначала показать, что App реально полезен, и только потом объяснять, зачем нужны дополнительные права.
Ошибка №6: Игнорирование организационного контекста.
Иногда разработчик делает App «для всех», хотя по сути это внутренний корпоративный инструмент. В результате он тащит внутрь Store очень специфичные пермишены (внутренние CRM, приватные данные сотрудников), которые сложно адекватно объяснить широкому пользователю. В таких случаях стоило ориентироваться на org‑only режим и внутреннее ревью, а не на публичный Store.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ