# Guideline 2.3.1: ukryte funkcje i aktualizacje OTA

> Guideline 2.3.1: Apple odrzuca każdą ukrytą, uśpioną lub nieopisaną w notatkach funkcję. Co zmienisz zdalnie, a co wymaga nowego buildu.

Oryginalna strona: [Guideline 2.3.1: ukryte funkcje i aktualizacje OTA](https://devoria.fr/pl/blog/guideline-2-3-1-ukryte-funkcje-aktualizacje-ota)
Autor: [Mehdi Azizi](https://devoria.fr/pl/mehdi-azizi)
Publikacja: 2026-11-04
Ostatnia aktualizacja treści: 2026-11-04


Guideline 2.3.1 zakazuje ukrytych, uśpionych lub nieudokumentowanych funkcji: wszystko, co robi twoja aplikacja, musi być widoczne dla użytkownika i dla recenzenta. Każdą nowość opisujesz dokładnie w notatkach dla recenzenta. **Aktualizacja zdalna może poprawić to, co Apple widziało, ale nigdy nie może dodać tego, czego Apple nie widziało.**

Publikuję swoje aplikacje iOS z Expo i każda ma EAS Update od pierwszego buildu, żeby dostarczać poprawki. Moja zasada: żadnej aktualizacji zdalnej, kiedy wersja jest w recenzji. Ten poradnik opiera się na tekście Apple, jego licencji, dokumentacji Expo i opublikowanych odrzuceniach.

## Co mówi guideline 2.3.1?

2.3.1 otwiera część 2.3 „Accurate Metadata” w [App Review Guidelines](https://developer.apple.com/app-store/review/guidelines/#2.3.1), w sekcji 2 „Performance”. Tekst zaczyna się tak: „Don't include any hidden, dormant, or undocumented features in your app; your app's functionality should be clear to end users and App Review.” Po ludzku: nic ukrytego, uśpionego ani nieudokumentowanego.

Dalsza część dotyczy każdego zgłoszenia: „All new features, functionality, and product changes must be described with specificity in the Notes for Review section of App Store Connect (generic descriptions will be rejected) and accessible for review.” **Każda nowość musi być dokładnie opisana w notatkach dla recenzenta i dostępna dla niego.** „Poprawki błędów i ulepszenia” więc nie wystarczą.

Ten sam akapit dotyczy wprowadzającego w błąd marketingu: obiecywania treści lub usługi, której nie ma, albo pokazywania fałszywej ceny, w App Store lub gdzie indziej.

Ta część przydała mi się przy Nolerze. Czytając jej stronę przed premierą, znalazłem dwa zdania, których nie dało się zweryfikować: „interfejs tylko po francusku”, co przestało być prawdą, i „najczęściej wybierany pakiet”, w aplikacji, która nigdy nie była opublikowana. Notatki dla recenzenta też opisywały nieaktualny stan produktu. Dokładnie w to celuje ta część. [2.3.10](https://devoria.fr/pl/blog/guideline-2-3-10-odrzucenie-aplikacji-metadane) dotyczy natomiast głównie strony aplikacji.

## Co znaczy komunikat odrzucenia 2.3.1?

Odrzucenie nosi tytuł „Guideline 2.3.1 - Performance”, czasem z dopiskiem „Hidden Features”. Dwa komunikaty opublikowane przez programistów React Native:

- **Marzec 2024**, w [zgłoszeniu na GitHubie CodePush](https://github.com/microsoft/react-native-code-push/issues/2680): „The app contains hidden features.”, bez dalszych szczegółów. Programista prosi o wyjaśnienie i dostaje uzupełnienie w ramach 2.5.2: „Your app, extension, or linked framework appears to contain code designed explicitly with the capability to change the app's behavior or functionality after App Review approval.” Zgłoszenie nie mówi, czy aplikacja potem przeszła.
- **Luty 2023**, w [innym zgłoszeniu](https://github.com/microsoft/react-native-code-push/issues/2434), Apple wskazuje „CodePush-related remote code downloading/updating support” w binarce.

Moja interpretacja: **recenzent nie widzi twoich aktualizacji, widzi kod, który może je odbierać.** Oba przypadki dotyczą CodePush. Nie znalazłem świeżego publicznego odrzucenia dotyczącego EAS Update, co niczego nie dowodzi.

## Aktualizacje zdalne: na co pozwalają 2.5.2 i licencja

[Reguła 2.5.2](https://developer.apple.com/app-store/review/guidelines/#2.5.2), o której piszę też w poradniku o [trybach działania w tle](https://devoria.fr/pl/blog/guideline-2-5-4-tryb-dzialania-w-tle-odrzucenie), zabrania aplikacji „download, install, or execute code which introduces or changes features or functionality of the app”.

Punkt 3.3.1(B) [Apple Developer Program License Agreement](https://developer.apple.com/support/terms/apple-developer-program-license-agreement/#b331) zabrania pobierania kodu wykonywalnego, ale precyzuje: „Interpreted code may be downloaded to an Application”. Pod trzema warunkami: ten kod nie zmienia głównego celu aplikacji, nie omija podpisu, piaskownicy ani zabezpieczeń systemu i nie tworzy sklepu z innymi aplikacjami.

JavaScript w aplikacji Expo to kod interpretowany: moim zdaniem EAS Update mieści się w tych ramach. Jego [dokumentacja](https://docs.expo.dev/eas-update/introduction/) przypomina, że aktualizacje podlegają zasadom App Store i że „changes to your app's behavior need to be reviewed”. Przy krytycznym błędzie Expo proponuje poprawkę zdalną, a potem nowe zgłoszenie, które ją zawiera.

**Moja granica: poprawiać i dostrajać to, co istnieje, tak. Zmieniać to, czym aplikacja jest albo co sprzedaje, nie.**

## Co możesz zmienić zdalnie, a co wymaga nowego buildu

Tabela, którą stosuję, oparta na cytowanych tu stronach Apple i Expo. Wiersz „darmowe staje się płatne” i dwa ostatnie to moja interpretacja.

| Zmiana                        | Droga                  | Dlaczego                             |
| ----------------------------- | ---------------------- | ------------------------------------ |
| Błąd w JavaScripcie           | Aktualizacja zdalna    | Zastosowanie przewidziane przez Expo |
| Tekst, tłumaczenie, styl      | Aktualizacja zdalna    | Zastosowanie przewidziane przez Expo |
| Cena subskrypcji              | App Store Connect      | Żaden kod się nie zmienia            |
| Tekst promocyjny              | App Store Connect      | Bez nowego zgłoszenia                |
| Zakup już zatwierdzonego typu | Recenzja samego zakupu | Zasada App Store Connect             |
| Pierwszy zakup danego typu    | Nowa wersja            | Zasada App Store Connect             |
| Nowa funkcja                  | Nowa wersja            | 2.3.1 i 2.5.2                        |
| Darmowe staje się płatne      | Nowa wersja            | Strona i notatki do poprawy          |
| Uprawnienie, Info.plist       | Nowy build             | Plik w binarce                       |
| Moduł natywny, SDK Expo       | Nowy build             | Zmieniony kod natywny                |
| Przełącznik, który wyłącza    | Konfiguracja zdalna    | Tolerowany, jeśli tymczasowy         |
| Przełącznik, który odsłania   | Zakazane               | Funkcja nigdy nierecenzowana         |

Tekst promocyjny zmienia się „without requiring an updated submission”, według strony Apple o [informacjach o wersji](https://developer.apple.com/help/app-store-connect/reference/app-information/platform-version-information). Pierwszy zakup każdego typu idzie razem z nową wersją, kolejne osobno, według pomocy o [zgłaszaniu zakupów](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/submit-an-in-app-purchase). Expo zalicza kod natywny, uprawnienia i wersję SDK do rzeczy wymagających nowej binarki, tak jak przy [ITMS-90683](https://devoria.fr/pl/blog/itms-90683-missing-purpose-string-expo). Przełącznik, który wyłącza zepsutą funkcję, nie dodaje niczego nowego, dopóki nie zabiera tego, za co subskrybenci zapłacili.

## Zdalne przełączniki bez odrzucenia

Zdalny przełącznik, czyli feature flag, sam w sobie nie jest zakazany: wszystko zależy od tego, co ukrywa. Moje zasady:

- **Wszystko, co przełącznik może pokazać, jest obecne i włączone dla recenzenta**, i nazwane w notatkach dla recenzenta.
- Test A/B porównuje dwa warianty, które recenzent może zobaczyć, nigdy wariant zrecenzowany z nowym.
- **Żaden kod nie wykrywa recenzji, żeby zachować się inaczej.** To jest sama definicja ukrytej funkcji.
- Paywall sterowany zdalnie pokazuje tylko zatwierdzone produkty, a każdy wariant przestrzega [reguły 3.1.2](https://devoria.fr/pl/blog/guideline-3-1-2-odrzucenie-subskrypcja-paywall).

## Tryb demo i konta testowe

[Guideline 2.1](https://devoria.fr/pl/blog/guideline-2-1-odrzucenie-app-store) wymaga konta demo, jeśli twoja aplikacja ma logowanie, z działającym serwerem. Jeśli obowiązki prawne lub bezpieczeństwa nie pozwalają ci go dać, może je zastąpić wbudowany tryb demo, ale tylko „with prior approval by Apple”, i musi on pokazywać wszystkie funkcje. Strona Apple o informacjach o wersji dodaje: konto nie wygasa, a dodatkowe konta trafiają do notatek, ograniczonych do 4000 bajtów.

Związek z 2.3.1: **tryb demo albo konto testowe, które otwiera ekrany niewidoczne w inny sposób, musi być opisane.** Sekretny gest, kod albo specjalne konto, o którym nie wspomniałeś, to ukryta funkcja. Nazwij każdy specjalny dostęp w notatkach, razem z tym, co otwiera.

## Moja zasada: żadnej aktualizacji zdalnej w trakcie recenzji

Dlaczego mam EAS Update wszędzie: w Solys, moim budziku, błąd w JavaScripcie wyciszał aplikację, gdy tylko jeden dźwięk raz się nie odtworzył. Poprawka miała trzy linijki, ale żeby ją dostarczyć, trzeba było pełnego buildu i recenzji. Od tego czasu wszystkie moje aplikacje mają expo-updates od pierwszego buildu: to moduł natywny, więc binarka skompilowana bez niego nigdy niczego nie odbierze. Moja konfiguracja w `app.json`:

```json
{
  "expo": {
    "runtimeVersion": { "policy": "fingerprint" },
    "updates": { "fallbackToCacheTimeout": 0, "checkAutomatically": "ON_LOAD" }
  }
}
```

Z `fingerprint` aktualizacja trafia tylko do binarek, których kod natywny się zgadza ([wersje środowiska uruchomieniowego](https://docs.expo.dev/eas-update/runtime-versions/)). Ale kiedy wersja czeka na recenzję albo w niej jest, niczego nie publikuję. Z dwóch powodów.

1. **Recenzent nie zobaczyłby poprawki.** Z `fallbackToCacheTimeout` ustawionym na 0 świeża instalacja startuje na wbudowanym kodzie i stosuje aktualizację przy następnym uruchomieniu ([dokumentacja expo-updates](https://docs.expo.dev/versions/latest/sdk/updates/)). Recenzent instaluje, uruchamia raz i testuje binarkę. Nolera została odrzucona z poprawką już dostarczoną zdalnie: opisuję to w poradniku o 2.1.
2. **To, co testuje recenzent, musi zostać tym, co dostają użytkownicy.** Zmiana zachowania w trakcie recenzji tworzy rozbieżność między wersją obejrzaną a dostarczoną.

## Precyzyjne notatki dla recenzenta

2.3.1 odrzuca ogólnikowe opisy. Szablon, którego bym użył, po angielsku:

```text
What's new in this version:
- [Feature]: [where to find it, how to test it].

Remote configuration:
- "[flag]" controls [feature]. It is ON for review.

Over-the-air updates:
- The app uses expo-updates for bug fixes only.
  No update will be published during this review.

Demo account: see Sign-in information. It never expires.
```

## Jak odpowiedzieć na odrzucenie 2.3.1?

Odpowiedz w App Store Connect, gdzie [odpowiadasz na wiadomość od App Review](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/reply-to-app-review-messages/).

- **Komunikat jest niejasny**: zapytaj, o którą funkcję chodzi, jak programista ze zgłoszenia z 2024.
- **Prawdziwa funkcja jest źle opisana**: podaj dokładną ścieżkę i krótkie wideo, potem uzupełnij notatki.
- **Przełącznik odsłania coś nowego**: usuń go albo włącz i opisz, potem zrób nowy build.
- **Problemem jest kod aktualizacji**: wyjaśnij, że służy do poprawek, w ramach punktu 3.3.1(B). W zgłoszeniu z 2023 Apple prosiło o jego usunięcie.

## Checklista 2.3.1 przed zgłoszeniem

- Każda nowość w wersji jest opisana w notatkach, razem ze ścieżką.
- Każdy zdalny przełącznik jest włączony na czas recenzji i nazwany w notatkach.
- Żaden kod nie zmienia zachowania dla recenzenta.
- Specjalne dostępy są opisane: tryb demo, konto testowe, gest.
- Strona aplikacji i paywall nie obiecują niczego, czego build nie robi.
- W trakcie recenzji nie jest publikowana żadna aktualizacja zdalna.

## Sprawdź swoje zgłoszenie przed wysłaniem

[Review Kit](https://devoria.fr/pl/kits/app-review) zawiera moją checklistę przed wysłaniem, szablony notatek dla testera i skille Claude Code, które przeglądają twój projekt. Jeśli chcesz, żeby spojrzał na to człowiek, [zarezerwuj ze mną godzinę](https://devoria.fr/pl/coaching): razem przejrzymy twoje notatki dla recenzenta i konfigurację aktualizacji, na wideorozmowie. Cały proces znajdziesz na stronie [aplikacja odrzucona przez Apple](https://devoria.fr/pl/expertise/aplikacja-odrzucona-przez-apple).

Przygotowujesz swoją pierwszą premierę? [Zrób darmową diagnozę](https://devoria.fr/pl/diagnostic): ułoży kroki w odpowiedniej kolejności i wyśle ci moją checklistę przeciw odrzuceniom Apple.

## Najczęściej zadawane pytania

### Co znaczy „Guideline 2.3.1 - Performance - Hidden Features”?

Apple uważa, że twoja aplikacja zawiera ukrytą, uśpioną lub nieopisaną w notatkach dla recenzenta funkcję. Komunikat może też dotyczyć kodu zdolnego zmienić aplikację po recenzji, czasem razem z odrzuceniem 2.5.2.

### Czy Apple pozwala na EAS Update?

Licencja pozwala na pobierany kod interpretowany, dopóki nie zmienia głównego celu aplikacji. Poprawiać tak. Dodawać niezrecenzowaną funkcję nie.

### Czy można używać feature flagów w aplikacji iOS?

Tak, jeśli wszystko, co mogą pokazać, zostało zrecenzowane. Włącz każdy przełącznik na czas recenzji i opisz go w notatkach.

### Czy trzeba zgłosić recenzentowi tryb demo?

Tak. Wbudowany tryb demo wymaga wcześniejszej zgody Apple i musi pokazywać wszystkie funkcje.

### Czy można opublikować aktualizację zdalną w trakcie recenzji?

Nic tego wprost nie zabrania. Ale recenzent nie zobaczyłby jej przy pierwszym uruchomieniu, a ona tworzy rozbieżność z wersją zrecenzowaną. Zawsze się od tego powstrzymuję.


## Twój projekt

[Review Kit](https://devoria.fr/pl/kits/app-review): Moja checklista do App Store Review, poprawione odrzucenia od Apple, checklista do Google Play i trzy skille Claude Code. 219 zł.

[iOS & Android Kit](https://devoria.fr/pl/kits/ios): Stwórz swoją aplikację na iPhone'a i Androida z Claude Code: kod startowy moich aplikacji, droga aż do sklepów i wszystkie kity. 439 zł.

[Diagnoza: co dzieli cię od twojej aplikacji na iPhone'a](https://devoria.fr/pl/diagnostic): 7 pytań, 60 sekund: wiesz, co naprawdę blokuje publikację twojej aplikacji na iPhone'a, masz plan w 4 krokach i kit dopasowany do ciebie.
