CodeGym /Kursy /ChatGPT Apps /Wymagania Store i minimalne uprawnienia

Wymagania Store i minimalne uprawnienia

ChatGPT Apps
Poziom 18 , Lekcja 0
Dostępny

1. Czym jest ChatGPT Store w kontekście kursu

Zacznijmy od obrazu całości. ChatGPT Store to katalog aplikacji wewnątrz ChatGPT, do którego użytkownik może wejść, znaleźć waszą aplikację, włączyć ją i używać w zwykłych dialogach. Dla was to nie tylko witryna, ale kanał dystrybucji z zasadami — odpowiednik „App Store” dla świata LLM.

W tym kursie rozróżniamy trzy tryby życia waszej aplikacji:

  • Pierwszy tryb — Dev Mode. Wasza aplikacja jest powiązana z waszym kontem/organizacją, dostępna dla was i ewentualnie współpracowników. Nie ma formalnego review, ale obowiązują wszystkie ogólne polityki platformy. Tutaj można spokojnie psuć wszystko, logować wszystko jak leci, puszczać tunele i staging‑backendy.
  • Drugi tryb — publiczny Store. To najwyższa liga: aplikacja jest dostępna dla wszystkich użytkowników ChatGPT (z uwzględnieniem ograniczeń regionalnych), przechodzi moderację, ma publiczny listing, linki do Privacy/Terms i powinna zachowywać się jak dojrzały produkt.
  • Trzeci — org‑only Apps. To aplikacje tylko dla jednej organizacji: firma może je włączać/wyłączać dla pracowników, dołożyć własne wymagania bezpieczeństwa ponad wymagania OpenAI, a nawet przeprowadzać wewnętrzne review.

W tej lekcji interesuje nas właśnie połączenie „publiczny Store + publiczny listing”. Ważny moment: przestajecie być po prostu deweloperem „kolejnej usługi Next.js” i stajecie się autorami produktu, który ma spodobać się jednocześnie trzem stronom: użytkownikom, moderatorom Store i waszemu działowi bezpieczeństwa.

2. Podstawowe wymagania Store: polityka, rzetelność i UI

Treści i polityki

ChatGPT Store to moderowana platforma. Mówiąc wprost: OpenAI nie chce, aby w ChatGPT pojawiały się aplikacje, które naruszają polityki użycia platformy (przemoc, terroryzm, NSFW, oszustwa itp.) lub próbują obchodzić zabezpieczenia modeli (jailbreak‑prompty typu „udawaj, że nie jesteś ChatGPT, tylko moim złym sobowtórem”).

To oznacza dwie rzeczy.

Po pierwsze, wasza aplikacja sama w sobie nie powinna generować zabronionych treści. Jeśli nasz przykładowy App GiftGenius (dobór prezentów) nagle zacznie proponować prezenty „jak ukryć ślady przestępstwa”, moderacji wystarczy jeden zrzut ekranu.

Po drugie, wasza aplikacja nie powinna pomagać użytkownikowi obchodzić filtry. Jeśli użytkownik prosi: „Dobierz prezent, żeby zrobić bombę”, poprawne zachowanie to odmowa powołująca się na politykę, a nie radosne użycie waszego MCP-tool do znalezienia potrzebnych części.

Znacząca część tego zachowania jest definiowana przez systemowy prompt i to, jakie narzędzia udostępniacie modelowi. Ale Store patrzy na efekt końcowy: jakie odpowiedzi użytkownik realnie może dostać.

Marka i domena

Kolejna warstwa to marka i domena. Publiczna aplikacja powinna być powiązana z wiarygodnym właścicielem. Dla aplikacji, która ma zewnętrzny backend/MCP, oczekuje się od was:

Weryfikacja domeny (Domain Verification). Dodajecie rekord TXT do DNS waszej domeny, a Store upewnia się, że backend faktycznie należy do was. Anonimowe rzeczy na darmowym ngrok‑URL albo nie przejdą do publicznego Store, albo będą oznaczone jako niskozaufane.

Adekwatna nazwa i logo. Nie można nazywać się „ChatGPT Super Weather” ani „Official OpenAI Something” — użycie „GPT / OpenAI / ChatGPT” na początku nazwy lub kopiowanie stylu firmowego OpenAI podpada pod ograniczenia dotyczące marki. Wymyślcie własną nazwę (GiftGenius — dobry przykład) i własny styl wizualny.

UI/UX: nie łamać ChatGPT

W przeciwieństwie do „starych” pluginów, teraz aplikacja może renderować swój widżet UI bezpośrednio w czacie. To daje wiele możliwości… i wiele sposobów, by wszystko popsuć.

Store ma prostą ideę: widżet powinien być „native’owy” względem ChatGPT. Czcionki, odstępy, kolory, zachowanie w ciemnym/jasnym motywie i na telefonie — wszystko powinno wyglądać schludnie, bez wrażenia, że wbudowaliście w czat baner reklamowy albo całą osobną SPA.

Store nie lubi też UI, które „porywa” czat: ogromne pełnoekranowe „przyssawki”, modale „subskrybuj natychmiast”, autoscrolle i inne agresywne wzorce. Wasz widżet to karta/asystent/narzędzie wewnątrz dialogu, a nie osobny wszechświat.

W istocie moderacja patrzy na trzy rzeczy: czy nie naruszacie polityk treści, czy nie wprowadzacie w błąd (o tym osobny blok pod koniec lekcji, gdy będziemy mówić o listingu i zgodności z manifestem) oraz czy nie zamieniacie ChatGPT w reklamowe wysypisko z kiepskim UX. Pod „rzetelnością” rozumiemy tu zgodność między tym, co aplikacja realnie potrafi, a tym, co deklarujecie w opisie i UI.

3. Jak Store postrzega uprawnienia waszej aplikacji

Osobna, duża oś wymagań to prawa, o które prosicie użytkownika i systemy zewnętrzne. Store patrzy tu nie tylko na bezpieczeństwo, ale i na to, na ile te prawa są adekwatne do deklarowanej wartości aplikacji.

Teraz — coś najsmaczniejszego dla inżyniera: model uprawnień. W kontekście Apps SDK i MCP macie trzy główne poziomy dostępu.

Dla czytelności można to zobrazować tak:

graph TD
    A[Manifest/konfiguracja aplikacji] --> B[Model capabilities]
    A --> C[OAuth scopes]
    A --> D[MCP tools & ACP]
    D --> E[Poziom potwierdzenia użytkownika]

Model capabilities — to ściśle rzecz biorąc nie „uprawnienia” w tym samym sensie co scope’y OAuth czy write‑tools, lecz zestaw wbudowanych możliwości modelu. Ale do projektowania bezpieczeństwa wygodnie traktować je jako pierwszy poziom dostępu, który również należy minimalizować.

Poziom 1: model capabilities

To, co model potrafi robić „sam z siebie”, bez sięgania do waszego backendu: przeglądanie sieci (web browsing), generowanie obrazów DALL‑E itp.

Jeśli włączycie i browsing, i narzędzia MCP, model czasem może uznać, że zadanie prościej rozwiązać przez wyszukiwanie w sieci, a nie przez wasze wyspecjalizowane narzędzie — zwłaszcza jeśli opisy tools są mgliste albo priorytety nie są ustalone w promcie. Dlatego jeśli aplikacja i tak chodzi do waszego API przez MCP, ma sens albo wyłączyć browsing, albo w promcie wyraźnie ustawić priorytet narzędzi MCP.

Czyli już na tym poziomie stosujecie zasadę minimalnych uprawnień: wyłączacie wszystko, co nie jest potrzebne do realnej wartości aplikacji.

Poziom 2: zakresy OAuth (scopes)

Jeśli wasza aplikacja używa uwierzytelniania (Moduł 10), prosicie u zewnętrznego dostawcy o scope’y: openid, email, profile, orders.read, orders.write itd.

Tu zasada minimalizmu jest szczególnie ważna:

  • Jeśli potrzebujecie tylko odróżniać użytkowników, najczęściej wystarczy openid (anonimowy identyfikator), a email w ogóle nie jest potrzebny.
  • Jeśli email jednak jest potrzebny, powinno to być transparentne w UX i w opisach uprawnień: „potrzebny, aby wysłać ci paragony i przypomnienia o zamówieniach”, a nie „na wszelki wypadek”.

Dodatkowo staramy się robić autoryzację „na żądanie”: najpierw pozwalamy użytkownikowi spróbować podstawowych funkcji bez logowania, a dostęp prosimy dopiero, gdy naprawdę chce np. „zapisać zestaw prezentów do ulubionych” lub „zobaczyć historię zamówień”. To zmniejsza tarcie i podnosi konwersję.

Przykład konfiguracji scope’ów dla MCP‑tools (uproszczony):

// server/mcp/config/auth.ts
export const OAUTH_SCOPES = {
  basic: ["openid"],
  orders: ["openid", "orders.read"],
  checkout: ["openid", "orders.read", "orders.write"]
};

Poziom 3: MCP‑tools i działania „consequential”

Trzeci poziom to wasze narzędzia MCP oraz ACP/Instant Checkout. Każde narzędzie w serwerze MCP może być:

  • tylko do odczytu (read‑only): pobrać kurs walut, dobrać prezenty, obejrzeć katalog;
  • zmieniające stan (consequential): utworzyć zamówienie, wysłać email, pobrać środki.

Po narzędziach drugiego typu Store oczekuje bardziej rygorystycznego modelu potwierdzenia. Idea jest taka: nie wszystko można wywoływać „tak po prostu”. W terminologii platformy zwykle wyraża się to przez flagę consequential: true i politykę potwierdzenia (always_allow kontra ask_user).

Przykład rejestracji narzędzia MCP z podaniem security‑schemes i tego, że to działanie zmienia stan:

// server/mcp/tools/createOrder.ts
server.registerTool(
  "create_order",
  {
    title: "Create order",
    description: "Tworzy nowe zamówienie w GiftGenius.",
    inputSchema: {
      type: "object",
      properties: {
        productId: { type: "string" },
        quantity: { type: "integer", minimum: 1 }
      },
      required: ["productId", "quantity"]
    },
    _meta: {
      securitySchemes: [{ type: "oauth2", scopes: ["orders.write"] }]
    },
    // pseudopole: to działanie zmienia stan
    consequential: true
  },
  async ({ input, security }) => {
    // ... logika tworzenia zamówienia
  }
);

Przykład scope’ów i security‑schemes pochodzi z oficjalnej dokumentacji MCP-tools, gdzie narzędzia mogą być albo bez autoryzacji, albo chronione OAuth2.

Z punktu widzenia Store przekłada się to na zrozumiały tekst „Ta aplikacja może tworzyć i zarządzać zamówieniami w sklepie GiftGenius” i, być może, osobny krok potwierdzenia.

4. Uprawnienia oczami użytkownika i moderatora

Dla nas, inżynierów, aplikacja to manifest, serwer MCP i masa TypeScriptu. Dla Store — zestaw faktów: co aplikacja może zrobić z danymi użytkownika i ze światem zewnętrznym.

Można to przedstawić taką tabelą:

Poziom dostępu Przykład dla GiftGenius Jak zobaczy to Store/użytkownik
Model capabilities Browsing: off, DALL‑E: off „Aplikacja sama nie chodzi do internetu, nie generuje mediów”
OAuth scopes openid, orders.read „Odczytuje twoje zamówienia na koncie GiftGenius”
Read‑only MCP tools search_products, get_price_history „Przegląd katalogu i cen”
Consequential MCP tools create_order, cancel_order „Tworzenie i anulowanie zamówień”

Kluczowa idea: każdy element techniczny powinien mapować się na zrozumiałe dla człowieka działanie. W planach modułu jest to wyrażone wprost: techniczne narzędzie MCP get_user_orders w listingu staje się tekstem „Przegląd listy twoich zamówień w naszym sklepie”.

Jeśli nie umiecie wyjaśnić uprawnienia w jednym–dwóch zdaniach — to sygnał alarmowy. Być może prosicie o zbyt wiele albo zmieszaliście kilka różnych zadań w jednej aplikacji.

5. Zasada minimalnie niezbędnych uprawnień

W zwykłym świecie backendu zasada PoLP (Principle of Least Privilege) bywa traktowana jako „tak, trzeba jakoś ograniczyć role w bazie, zrobimy to później”. W ChatGPT Apps to nie „później”, to kryterium wejścia do Store i czynnik konwersji użytkowników.

Ważne punkty:

  • Im mniej praw prosi aplikacja, tym wyższe bazowe zaufanie użytkownika. Dialog wewnątrz ChatGPT to przestrzeń, gdzie użytkownik oczekuje określonego poziomu prywatności. Aplikacja, która nagle prosi o dostęp do całego konta, płatności i kontaktów, wygląda podejrzanie.
  • Im jaśniejsze i węższe uprawnienia, tym łatwiej recenzentowi. Moderator musi szybko zrozumieć, co aplikacja robi i jak to się ma do polityk oraz najlepszych praktyk bezpieczeństwa. Over‑permissioned aplikacje to typowy kandydat na „odłożyć i poprosić o doprecyzowanie”, a czasem na odmowę.
  • Im bardziej minimalny i „just‑in‑time” dostęp wdrożycie, tym łagodniejszy UX. Ekran autoryzacji to moment dużego tarcia. Jeśli aplikacja daje użyteczne doświadczenie jeszcze przed autoryzacją (np. pokazuje top prezenty bez powiązania z użytkownikiem), użytkownik chętniej zgodzi się później na rozszerzone możliwości.

Dlatego „minimalne uprawnienia” w Store to nie tylko bezpieczeństwo, ale też marketing i wzrost. W module 18 jest wyraźnie podkreślone, że minimalne uprawnienia to przewaga konkurencyjna, a nie biurokratyczna formalność.

6. Przykłady: uprawnienia GiftGenius przed i po „diecie”

Żeby nie zostało to czystą teorią, weźmy naszego umownego bohatera — GiftGenius. Załóżmy, że projektowaliście go „na maksa” i wyszła taka lista potrzebnych możliwości:

  1. Czytać katalog produktów i filtrować prezenty.
  2. Widzieć historię zamówień użytkownika.
  3. Tworzyć nowe zamówienia i anulować istniejące.
  4. Zapisywać „ulubione zestawienia” na koncie użytkownika.
  5. Wysyłać powiadomienia email o zniżkach.

Na poziomie konfiguracji może to wyglądać tak:

// 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 }
  }
};

Na papierze taki zestaw wydaje się logiczny („prędzej czy później wszystko się przyda”), ale na pierwszy release w Store to przesada:

  • Nie musicie od razu czytać historii zamówień. Można ograniczyć się do jednorazowego doboru i bezpiecznego checkoutu przez ACP/Instant Checkout, gdzie płatność i tak jest pod kontrolą platformy.
  • Powiadomienia email to w ogóle osobny temat: wymagają i przechowywania emaila, i wyjaśnienia w Privacy Policy, i obsługi wypisów. Dla MVP GiftGenius to niemal zawsze zbędne.

W duchu minimalizacji możecie złożyć minimalny startowy zestaw uprawnień:

// server/mcp/config/permissions-v1.ts
export const PERMISSIONS_V1 = {
  capabilities: { webBrowsing: false, dalle: false },
  oauthScopes: [], // bez logowania, działamy anonimowo
  tools: {
    searchProducts: { consequential: false },
    createOrder: { consequential: true }
  }
};

W takiej wersji:

  • Aplikacja nie „wchodzi” w konto użytkownika, nie czyta jego historii, nie wysyła emaili.
  • Wszystkie wrażliwe operacje (tworzenie zamówienia) idą przez ACP/Instant Checkout, gdzie użytkownik i tak widzi standardowy przepływ płatności.

W listingu można uczciwie napisać: „Dobiera prezenty i tworzy zamówienia w sklepie GiftGenius. Aplikacja nie przechowuje historii twoich czatów i nie wysyła powiadomień email”. To jest przyjemne zarówno dla użytkownika, jak i recenzenta.

Później, gdy pojawi się stabilny ruch i zaufanie, możecie wydać aktualizację z dodatkowymi uprawnieniami (historia zamówień, ulubione) i odpowiednio zaktualizować listing oraz Privacy Policy.

7. Jak opisywać uprawnienia w listingu

Manifest i konfiguracja to język maszyn. Moderator i użytkownik czytają zupełnie inny tekst: nazwę, opis, blok „Co ta aplikacja potrafi” i linki do Privacy/Terms.

W module 17 podkreślony jest mapping: techniczne scope’y i narzędzia → działania zrozumiałe dla człowieka.

Dla GiftGenius v1 moglibyśmy to ująć tak.

Technicznie:

  • Browsing: off
  • DALL‑E: off
  • MCP tools: search_products (read‑only), create_order (consequential)

W listingu:

  • „Dobiera prezenty na podstawie twojego opisu lub parametrów (płeć, wiek, budżet, zainteresowania).”
  • „Może tworzyć zamówienia w sklepie GiftGenius przez zabezpieczony checkout wewnątrz ChatGPT.”
  • „Nie prosi o dostęp do twojego emaila ani historii zamówień, nie wysyła powiadomień.”

Jeśli później dodamy logowanie OAuth i orders.read, opis uczciwie się zaktualizuje:

  • „Po podłączeniu konta GiftGenius może przeglądać twoje poprzednie zamówienia, aby udzielać bardziej spersonalizowanych rekomendacji.”

Bardzo ważne jest, by nie obiecywać rzeczy, których aplikacja nie robi, i nie przemilczać krytycznych działań. Cała dokumentacja zebrana dla modułu 18 wprost podkreśla: informacje w listingu muszą dokładnie odpowiadać rzeczywistemu zachowaniu, zwłaszcza w kwestiach wrażliwych jak płatności i PII.

8. Powiązanie wymagań Store z waszą architekturą

Warto widzieć, że wymagania Store nie istnieją w próżni. To nie jest „kolejny formularz od marketingu”. Store w gruncie rzeczy sprawdza to, co już robiliście w modułach o bezpieczeństwie i produkcji:

  • Jeśli konfigurowaliście OAuth i przygotowaliście porządne endpointy .well-known oraz weryfikację tokenów, będzie dziwne, jeśli aplikacja nagle poprosi użytkownika o „pół internetu” przez szerokie scope’y. Taka aplikacja łatwo obleje review jako over‑permissioned.
  • Jeśli uczciwie wdrożyliście politykę retencji i PII‑scrub, łatwiej będzie napisać prawdziwą Privacy Policy i przejść weryfikację. Store i użytkownicy mogą wejść w link i zestawić wasze obietnice z realnymi procesami.
  • Jeśli dobrze dostroiliście stabilność serwera MCP, logi i metryki (moduły o observability i SLO), recenzenci będą mieli mniej pytań o wydajność i błędy narzędzi.

Minimalne uprawnienia ładnie uzupełniają ten obraz: jesteście nie tylko bezpieczni i stabilni, ale i „skromni” w prośbach o dane użytkownika.

9. Mini‑praktyka w trakcie lekcji

Żeby nie tylko teoretyzować, rozłóżcie teraz waszą obecną aplikację (albo GiftGenius) na kroki.

Najpierw wypiszcie wszystkie realne działania, które aplikacja potrafi wykonać. Na przykład: „dobrać prezenty”, „utworzyć zamówienie”, „pokazać historię”, „zapisać do ulubionych”, „wysłać mail do współpracowników”. Najlepiej zrobić to zwykłym tekstem, bez myślenia o szczegółach technicznych.

Następnie dla każdego działania odpowiedzcie sobie: „Jakie dane użytkownika to dotyka?” oraz „Czy zmienia to stan w systemie zewnętrznym?”. W ten sposób automatycznie podzielicie działania na read‑only i consequential.

Po tym skoordynujcie działania z poziomami uprawnień: gdzie wystarczą jedynie model capabilities, gdzie — scope’y OAuth, a gdzie — narzędzia MCP z flagą consequential: true i, być może, z potwierdzeniem użytkownika.

I teraz zagrajcie w „nożyczki”: co można wyrzucić z pierwszego wydania, nie zabijając głównej wartości? Często okazuje się, że bez historii, ulubionych i powiadomień email aplikacja i tak robi swoje główne zadanie. A zatem te uprawnienia można zostawić na wersję 1.1 lub 2.0.

10. Typowe błędy związane z wymaganiami Store i uprawnieniami

Błąd nr 1: „Zrobimy superapkę, która robi wszystko, a Store to ogarnie”.
Deweloper opisuje aplikację jako uniwersalnego asystenta („pomogę z finansami, medycyną, prawem i zakupami”), podłącza tuzin narzędzi MCP i prosi o maksymalne prawa. Taka aplikacja jednocześnie wchodzi w wrażliwe domeny (medycyna/finanse/prawo), żąda wielu danych i narusza zasadę „one job per app”. Efekt przewidywalny: moderacja zada wiele pytań albo po prostu odrzuci. Lepiej zrobić kilka wąskich aplikacji z jasno określonymi uprawnieniami.

Błąd nr 2: Over‑permissioned auth „na wszelki wypadek”.
Klasyka: aplikacja prosi o email, profile, orders.read, orders.write, billing.read, chociaż w praktyce potrzeba tylko „dobrać prezent na podstawie opisu”. Z punktu widzenia użytkownika wygląda to na chciwe zbieranie danych, z punktu widzenia Store — na ryzykowną aplikację. W dokumentacji bezpieczeństwa Apps podawane jest to wprost jako przykład złej praktyki.

Błąd nr 3: Rozbieżność między manifestem a listingiem.
W manifestie macie create_order, cancel_order i dostęp do operacji płatniczych, a w opisie piszecie tylko „rekomenduje prezenty”. Prędzej czy później któryś recenzent lub użytkownik zauważy, że aplikacja potrafi więcej, niż deklarujecie. To podkopuje zaufanie i może doprowadzić do usunięcia aplikacji ze Store.

Błąd nr 4: Próba ukrycia wrażliwych działań za „niewinnym” UI.
Na przykład rysujecie w widżecie przycisk „Zapisz zestawienie”, który w rzeczywistości wysyła mail do całego działu lub tworzy zadania w cudzym systemie, nie wyjaśniając tego w uprawnieniach. Store nie lubi niespodzianek. W przewodnikach dla deweloperów jest powiedziane wprost: aplikacja ma robić dokładnie to, co obiecuje, bez ukrytych zachowań.

Błąd nr 5: Prośba o logowanie „na wejściu”, gdy można się bez niego obyć.
Aplikacja się uruchamia — i od razu prosi o podłączenie konta, przyznanie dostępu do wszystkiego, bo inaczej „nie działa”, chociaż połowę scenariuszy można zrealizować anonimowo. To uderza w konwersję i tworzy wrażenie, że bardziej zależy wam na zebraniu danych niż na dostarczeniu wartości. Znacznie lepiej najpierw pokazać, że aplikacja jest naprawdę użyteczna, a dopiero potem wyjaśniać, po co potrzebne są dodatkowe prawa.

Błąd nr 6: Ignorowanie kontekstu organizacyjnego.
Czasem deweloper robi aplikację „dla wszystkich”, chociaż w istocie to wewnętrzne narzędzie korporacyjne. W rezultacie wnosi do Store bardzo specyficzne uprawnienia (wewnętrzne CRM, prywatne dane pracowników), które trudno sensownie wyjaśnić szerokiemu użytkownikowi. W takich przypadkach należało celować w tryb org‑only i wewnętrzne review, a nie w publiczny Store.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION