Guideline 2.3.1: skrivene funkcije i OTA ažuriranja
Autor: Mehdi Azizi
Objavljeno , 9 min
Apple odbija skrivene, uspavane ili nedokumentirane funkcije. Evo što smiješ mijenjati na daljinu, a što traži novi build.
Guideline 2.3.1 zabranjuje skrivene, uspavane ili nedokumentirane funkcije: sve što tvoja aplikacija radi mora biti vidljivo korisniku i revieweru. Svaku novost treba precizno opisati u bilješkama za reviziju. Ažuriranje na daljinu može ispraviti ono što je Apple vidio, ali nikad ne smije dodati ono što Apple nije vidio.
Svoje iOS aplikacije objavljujem s Expoom i svaka od njih ima EAS Update već od prvog builda, da mogu slati ispravke. Moje pravilo: nikakvo ažuriranje na daljinu dok je neka verzija na reviziji. Ovaj vodič oslanja se na Appleov tekst, njegovu licencu, Expoovu dokumentaciju i objavljena odbijanja.
Što kaže guideline 2.3.1?
2.3.1 otvara dio 2.3 „Accurate Metadata” u App Review Guidelines, unutar odjeljka 2 „Performance”. Tekst počinje ovako: „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.” Jednostavno rečeno: ništa skriveno, uspavano ili nedokumentirano.
Nastavak se odnosi na svaku prijavu: „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.” Svaka novost mora biti precizno opisana u bilješkama za reviziju i dostupna revieweru. „Ispravci grešaka i poboljšanja” dakle nije dovoljno.
Isti stavak cilja i na obmanjujući marketing: obećavanje sadržaja ili usluge koje nema, ili prikazivanje lažne cijene, na App Storeu ili bilo gdje drugdje.
Taj dio mi je pomogao kod Nolere. Dok sam prije izlaska čitao njezinu stranicu, našao sam dvije rečenice koje se nisu mogle provjeriti: „sučelje samo na francuskom”, što više nije bilo točno, i „najčešće biran paket”, za aplikaciju koja nikad nije bila objavljena. I bilješke za reviewera opisivale su zastarjelo stanje proizvoda. Upravo na to cilja ovaj dio. 2.3.10 se pak uglavnom odnosi na stranicu aplikacije.
Što znači poruka o odbijanju 2.3.1?
Odbijanje nosi naslov „Guideline 2.3.1 - Performance”, ponekad s dodatkom „Hidden Features”. Dvije poruke koje su objavili React Native developeri:
- Ožujak 2024., u CodePush ticketu na GitHubu: „The app contains hidden features.”, bez ikakvih dodatnih detalja. Developer traži pojašnjenje i dobiva dopunu po 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.” Ticket ne kaže je li aplikacija poslije prošla.
- Veljača 2023., u drugom ticketu, Apple cilja na „CodePush-related remote code downloading/updating support” u binaryju.
Kako ja to čitam: reviewer ne vidi tvoja ažuriranja, vidi kod koji ih može primiti. Oba slučaja odnose se na CodePush. Nisam našao nijedno nedavno javno odbijanje zbog EAS Updatea, ali to ništa ne dokazuje.
Ažuriranja na daljinu: što dopuštaju 2.5.2 i licenca
Pravilo 2.5.2, o kojem pišem i u vodiču o pozadinskim načinima rada, zabranjuje aplikaciji da „download, install, or execute code which introduces or changes features or functionality of the app”.
Članak 3.3.1(B) Apple Developer Program License Agreementa zabranjuje preuzeti izvršni kod, ali precizira: „Interpreted code may be downloaded to an Application”. Uz tri uvjeta: taj kod ne mijenja osnovnu svrhu aplikacije, ne zaobilazi potpisivanje, sandbox ni sigurnosne mehanizme sustava i ne stvara trgovinu drugih aplikacija.
JavaScript u Expo aplikaciji je interpretirani kod: po mom mišljenju, EAS Update spada u taj okvir. Njegova dokumentacija podsjeća da ažuriranja slijede pravila App Storea i da „changes to your app's behavior need to be reviewed”. Za kritičnu grešku Expo predlaže ispravak na daljinu, a zatim novu prijavu koja ga sadrži.
Moja granica: ispravljati i dotjerivati ono što postoji, da. Mijenjati ono što aplikacija jest ili što prodaje, ne.
Što smiješ mijenjati na daljinu, a što traži novi build
Tablica koju koristim, izvučena iz ovdje citiranih Appleovih i Expoovih stranica. Redak „besplatno postaje plaćeno” i zadnja dva retka moje su tumačenje.
| Promjena | Put | Zašto |
|---|---|---|
| JavaScript greška | Ažuriranje na daljinu | Predviđena upotreba u Expou |
| Tekst, prijevod, stil | Ažuriranje na daljinu | Predviđena upotreba u Expou |
| Cijena pretplate | App Store Connect | Kod se ne mijenja |
| Promotivni tekst | App Store Connect | Bez nove prijave |
| Kupnja već odobrenog tipa | Revizija samo te kupnje | Pravilo App Store Connecta |
| Prva kupnja nekog tipa | Nova verzija | Pravilo App Store Connecta |
| Nova funkcija | Nova verzija | 2.3.1 i 2.5.2 |
| Besplatno postaje plaćeno | Nova verzija | Treba revidirati stranicu i bilješke |
| Dopuštenje, Info.plist | Novi build | Datoteka u binaryju |
| Nativni modul, Expo SDK | Novi build | Promijenjen nativni kod |
| Prekidač koji isključuje | Udaljena konfiguracija | Tolerira se ako je privremeno |
| Prekidač koji otkriva | Zabranjeno | Funkcija nikad revidirana |
Promotivni tekst mijenja se „without requiring an updated submission”, prema Appleovoj stranici o informacijama o verziji. Prva kupnja svakog tipa ide s novom verzijom, a sljedeće same, prema pomoći o prijavi kupnji. Expo nativni kod, dopuštenja i verziju SDK-a svrstava u ono što traži novi binary, kao i kod ITMS-90683. Prekidač koji isključuje pokvarenu funkciju ne dodaje ništa novo, dok god ne oduzima ono što su pretplatnici platili.
Prekidači na daljinu bez odbijanja
Prekidač na daljinu, odnosno feature flag, nije zabranjen sam po sebi: sve ovisi o tome što skriva. Moja pravila:
- Sve što prekidač može prikazati prisutno je i uključeno za reviewera, i navedeno u bilješkama za reviziju.
- A/B test uspoređuje dvije varijante koje reviewer može vidjeti, nikad jednu revidiranu i jednu neviđenu.
- Nikakav kod ne prepoznaje reviziju da bi se ponašao drukčije. To je sama definicija skrivene funkcije.
- Paywall upravljan na daljinu prikazuje samo odobrene proizvode, a svaka varijanta poštuje pravilo 3.1.2.
Demo način i testni računi
Guideline 2.1 traži demo račun ako tvoja aplikacija ima prijavu, uz uključen server. Ako ti zakonske ili sigurnosne obveze ne dopuštaju da ga daš, ugrađeni demo način može ga zamijeniti, ali samo „with prior approval by Apple”, i mora pokazati sve funkcije. Appleova stranica o informacijama o verziji dodaje: račun ne smije isteći, a dodatni računi idu u bilješke, ograničene na 4000 bajtova.
Veza s 2.3.1: demo način ili testni račun koji otvara zaslone inače nevidljive mora biti opisan. Tajna gesta, kod ili poseban račun koji nisu navedeni, to je skrivena funkcija. Navedi svaki poseban pristup u bilješkama, uz ono što otvara.
Moje pravilo: nikakvo ažuriranje na daljinu tijekom revizije
Zašto mi je EAS Update posvuda: u Solysu, mojoj budilici, JavaScript greška utišala bi aplikaciju čim bi se neki zvučni efekt jednom ne bi učitao. Ispravak je stao u tri retka, ali za isporuku je trebao cijeli build i revizija. Od tada sve moje aplikacije imaju expo-updates od prvog builda: to je nativni modul, a binary kompajliran bez njega nikad ništa neće primiti. Moja konfiguracija, u app.json:
{
"expo": {
"runtimeVersion": { "policy": "fingerprint" },
"updates": { "fallbackToCacheTimeout": 0, "checkAutomatically": "ON_LOAD" }
}
}
Uz fingerprint, ažuriranje stiže samo do binaryja čiji nativni kod odgovara (runtime verzije). No dok verzija čeka ili prolazi reviziju, ne objavljujem ništa. Dva razloga.
- Reviewer ne bi vidio ispravak. S
fallbackToCacheTimeoutna 0, nova instalacija kreće s ugrađenim kodom i ažuriranje primjenjuje pri sljedećem pokretanju (dokumentacija za expo-updates). Reviewer instalira, pokrene jednom i testira binary. Nolera je odbijena s ispravkom koji je već bio isporučen na daljinu: o tome pišem u vodiču za 2.1. - Ono što reviewer testira mora ostati ono što korisnici dobivaju. Mijenjanje ponašanja tijekom revizije stvara razliku između viđene i isporučene verzije.
Precizne bilješke za reviziju
2.3.1 odbija generičke opise. Predložak koji bih koristio, na engleskom:
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.
Kako odgovoriti na odbijanje 2.3.1?
Odgovori u App Store Connectu, gdje odgovaraš na poruku App Reviewa.
- Poruka ostaje nejasna: pitaj na koju funkciju misle, kao developer iz ticketa iz 2024.
- Prava funkcija je loše opisana: daj točan put i kratak video, pa dopuni bilješke.
- Prekidač otkriva nešto neviđeno: ukloni ga ili ga uključi i opiši, pa napravi novi build.
- Problem je kod za ažuriranje: objasni da služi za ispravke, u okviru članka 3.3.1(B). U ticketu iz 2023. Apple je tražio da se ukloni.
Checklista za 2.3.1 prije prijave
- Svaka novost u verziji opisana je u bilješkama, s putem do nje.
- Svaki prekidač na daljinu uključen je za reviziju i naveden u bilješkama.
- Nikakav kod ne mijenja ponašanje za reviewera.
- Posebni pristupi su opisani: demo način, testni račun, gesta.
- Stranica aplikacije i paywall ne obećavaju ništa što build ne radi.
- Tijekom revizije ne objavljuje se nikakvo ažuriranje na daljinu.
Provjeri svoju prijavu prije slanja
Review Kit okuplja moju checklistu prije slanja, predloške bilješki za testera i Claude Code skillove koji pregledavaju tvoj projekt. Ako želiš ljudsko oko, rezerviraj sat vremena sa mnom: zajedno pregledamo tvoje bilješke za reviziju i konfiguraciju ažuriranja, preko videopoziva. Cijeli postupak je na stranici aplikacija koju je Apple odbio.
Pripremaš svoje prvo izdanje? Napravi besplatnu dijagnostiku: posložit će ti korake po redu i poslati ti moju checklistu protiv Appleovih odbijanja.
Česta pitanja
Što znači „Guideline 2.3.1 - Performance - Hidden Features”?
Apple smatra da tvoja aplikacija sadrži skrivenu, uspavanu funkciju ili funkciju koje nema u bilješkama za reviziju. Poruka može ciljati i na kod koji može mijenjati aplikaciju nakon revizije, ponekad uz odbijanje po 2.5.2.
Dopušta li Apple EAS Update?
Licenca dopušta preuzeti interpretirani kod dok god ne mijenja osnovnu svrhu aplikacije. Ispravljati, da. Dodati nerevidiranu funkciju, ne.
Smiju li se koristiti feature flagovi u iOS aplikaciji?
Da, ako je sve što mogu prikazati prošlo reviziju. Uključi svaki prekidač za reviziju i opiši ga u bilješkama.
Treba li revieweru prijaviti demo način?
Da. Ugrađeni demo način traži prethodno Appleovo odobrenje i mora pokazati sve funkcije.
Smije li se objaviti ažuriranje na daljinu tijekom revizije?
Ništa to izričito ne zabranjuje. Ali reviewer ga ne bi vidio pri prvom pokretanju, a stvara i razliku u odnosu na revidiranu verziju. Ja to uvijek izbjegavam.

