# Guideline 2.3.1: funcții ascunse și actualizări OTA

> Guideline 2.3.1: Apple respinge orice funcție ascunsă, inactivă sau nedescrisă în notele de review. Ce poți schimba de la distanță și ce cere un build nou.

Pagina originală: [Guideline 2.3.1: funcții ascunse și actualizări OTA](https://devoria.fr/ro/blog/guideline-2-3-1-functii-ascunse-actualizari-ota)
Autor: [Mehdi Azizi](https://devoria.fr/ro/mehdi-azizi)
Publicare: 2026-11-04
Ultima revizuire a conținutului: 2026-11-04


Guideline 2.3.1 interzice funcțiile ascunse, inactive sau nedocumentate: tot ce face aplicația ta trebuie să fie vizibil pentru utilizator și pentru reviewer. Fiecare noutate se descrie precis în notele de review. **O actualizare de la distanță poate corecta ce a văzut Apple, niciodată nu poate adăuga ce Apple n-a văzut.**

Îmi public aplicațiile iOS cu Expo și fiecare include EAS Update încă de la primul build, ca să pot livra corecturi. Regula mea: nicio actualizare de la distanță cât timp o versiune e în review. Ghidul ăsta se bazează pe textul Apple, pe licența sa, pe documentația Expo și pe respingeri publicate.

## Ce spune guideline 2.3.1?

2.3.1 deschide partea 2.3 „Accurate Metadata” din [App Review Guidelines](https://developer.apple.com/app-store/review/guidelines/#2.3.1), în secțiunea 2 „Performance”. Textul începe așa: „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.” Pe scurt: nimic ascuns, adormit sau nedocumentat.

Continuarea vizează fiecare trimitere: „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.” **Fiecare noutate trebuie descrisă precis în notele de review și trebuie să fie accesibilă reviewerului.** Deci „Corecturi de buguri și îmbunătățiri” nu e suficient.

Același paragraf vizează marketingul înșelător: să promiți un conținut sau un serviciu care lipsește ori să afișezi un preț fals, în App Store sau în altă parte.

Partea asta mi-a fost utilă pe Nolera. Recitind pagina aplicației înainte de lansare, am găsit două fraze imposibil de verificat: „interfață doar în franceză”, care devenise falsă, și „cel mai ales pachet”, pentru o aplicație nepublicată încă. Notele pentru reviewer descriau și o stare depășită a produsului. Exact asta vizează partea asta. [2.3.10](https://devoria.fr/ro/blog/guideline-2-3-10-aplicatie-respinsa-metadate), în schimb, vizează mai ales pagina din App Store.

## Ce înseamnă mesajul de respingere 2.3.1?

Respingerea se numește „Guideline 2.3.1 - Performance”, uneori urmat de „Hidden Features”. Două mesaje publicate de dezvoltatori React Native:

- **Martie 2024**, într-un [issue GitHub CodePush](https://github.com/microsoft/react-native-code-push/issues/2680): „The app contains hidden features.”, fără alte detalii. Dezvoltatorul cere lămuriri și primește o completare în baza 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.” Issue-ul nu spune dacă aplicația a trecut ulterior.
- **Februarie 2023**, într-un [alt issue](https://github.com/microsoft/react-native-code-push/issues/2434), Apple vizează „CodePush-related remote code downloading/updating support” din binar.

Interpretarea mea: **reviewerul nu vede actualizările tale, vede codul capabil să le primească.** Ambele cazuri vizează CodePush. N-am găsit nicio respingere publică recentă care să vizeze EAS Update, ceea ce nu dovedește nimic.

## Actualizări de la distanță: ce permit 2.5.2 și licența

[Regula 2.5.2](https://developer.apple.com/app-store/review/guidelines/#2.5.2), despre care vorbesc și în ghidul despre [modurile de fundal](https://devoria.fr/ro/blog/guideline-2-5-4-mod-fundal-respins-apple), interzice aplicației să „download, install, or execute code which introduces or changes features or functionality of the app”.

Articolul 3.3.1(B) din [Apple Developer Program License Agreement](https://developer.apple.com/support/terms/apple-developer-program-license-agreement/#b331) interzice codul executabil descărcat, dar precizează: „Interpreted code may be downloaded to an Application”. Cu trei condiții: codul nu schimbă scopul principal al aplicației, nu ocolește nici semnătura, nici sandbox-ul, nici protecțiile sistemului și nu creează un magazin de alte aplicații.

JavaScript-ul unei aplicații Expo e cod interpretat: după mine, EAS Update intră în cadrul ăsta. [Documentația](https://docs.expo.dev/eas-update/introduction/) sa amintește că actualizările respectă regulile App Store și că „changes to your app's behavior need to be reviewed”. Pentru un bug critic, Expo propune corectura de la distanță, apoi o nouă trimitere care o include.

**Linia mea: să corectezi și să ajustezi ce există, da. Să schimbi ce este aplicația sau ce vinde, nu.**

## Ce poți schimba de la distanță, ce cere un build nou

Grila pe care o aplic, extrasă din paginile Apple și Expo citate aici. Rândul „gratuit care devine plătit” și ultimele două sunt interpretarea mea.

| Schimbare                        | Cale                       | De ce                       |
| -------------------------------- | -------------------------- | --------------------------- |
| Bug JavaScript                   | Actualizare de la distanță | Utilizare prevăzută de Expo |
| Text, traducere, stil            | Actualizare de la distanță | Utilizare prevăzută de Expo |
| Prețul unui abonament            | App Store Connect          | Niciun cod modificat        |
| Text promoțional                 | App Store Connect          | Fără trimitere nouă         |
| Achiziție de un tip deja validat | Review doar pe achiziție   | Regulă App Store Connect    |
| Prima achiziție de un tip        | Versiune nouă              | Regulă App Store Connect    |
| Funcție nouă                     | Versiune nouă              | 2.3.1 și 2.5.2              |
| Gratuit care devine plătit       | Versiune nouă              | Pagina și notele de revăzut |
| Permisiune, Info.plist           | Build nou                  | Fișier din binar            |
| Modul nativ, SDK Expo            | Build nou                  | Cod nativ schimbat          |
| Comutator care dezactivează      | Configurare la distanță    | Tolerat dacă e temporar     |
| Comutator care dezvăluie         | Interzis                   | Funcție niciodată revizuită |

Textul promoțional se schimbă „without requiring an updated submission”, conform paginii Apple despre [informațiile de versiune](https://developer.apple.com/help/app-store-connect/reference/app-information/platform-version-information). Prima achiziție de fiecare tip pleacă împreună cu o versiune nouă, următoarele singure, conform ajutorului despre [trimiterea achizițiilor](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/submit-an-in-app-purchase). Expo pune codul nativ, permisiunile și versiunea SDK printre lucrurile care cer un binar nou, ca la [ITMS-90683](https://devoria.fr/ro/blog/itms-90683-missing-purpose-string-expo). Un comutator care oprește o funcție defectă nu adaugă nimic nou, atâta timp cât nu ia ce au plătit abonații.

## Comutatoare de la distanță fără respingere

Un comutator de la distanță, sau feature flag, nu e interzis în sine: totul depinde de ce ascunde. Regulile mele:

- **Tot ce poate afișa un comutator e prezent și activat pentru reviewer**, și numit în notele de review.
- Un test A/B compară două variante pe care reviewerul le poate vedea, niciodată o variantă revizuită și una nouă.
- **Niciun cod nu detectează review-ul ca să se comporte altfel.** Asta e chiar definiția unei funcții ascunse.
- Un paywall controlat de la distanță arată doar produse validate, iar fiecare variantă respectă [regula 3.1.2](https://devoria.fr/ro/blog/guideline-3-1-2-aplicatie-respinsa-abonament).

## Mod demo și conturi de test

[Guideline 2.1](https://devoria.fr/ro/blog/guideline-2-1-app-store-respingere) cere un cont demo dacă aplicația ta are autentificare, cu serverul pornit. Dacă obligații legale sau de securitate te împiedică să oferi unul, un mod demo integrat îl poate înlocui, dar doar „with prior approval by Apple”, și trebuie să arate toate funcțiile. Pagina Apple despre informațiile de versiune adaugă: contul nu expiră, iar conturile suplimentare merg în note, limitate la 4.000 de octeți.

Legătura cu 2.3.1: **un mod demo sau un cont de test care deschide ecrane altfel invizibile trebuie descris.** Un gest secret, un cod sau un cont special nesemnalat e o funcție ascunsă. Numește fiecare acces special în note, împreună cu ce deschide.

## Regula mea: nicio actualizare de la distanță în timpul review-ului

De ce EAS Update e peste tot la mine: pe Solys, alarma mea, un bug JavaScript lăsa aplicația fără sunet de îndată ce un efect sonor eșua o singură dată. Corectura avea trei rânduri, dar era nevoie de un build complet și de un review ca s-o livrez. De atunci, toate aplicațiile mele includ expo-updates încă de la primul build: e un modul nativ, iar un binar compilat fără el nu va primi niciodată nimic. Configurarea mea, în `app.json`:

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

Cu `fingerprint`, o actualizare ajunge doar la binarele al căror cod nativ corespunde ([versiuni de runtime](https://docs.expo.dev/eas-update/runtime-versions/)). Dar cât timp o versiune așteaptă sau trece prin review, nu public nimic. Două motive.

1. **Reviewerul n-ar vedea corectura.** Cu `fallbackToCacheTimeout` la 0, o instalare nouă pornește pe codul inclus și aplică actualizarea la următoarea lansare ([documentația expo-updates](https://docs.expo.dev/versions/latest/sdk/updates/)). Reviewerul instalează, lansează o dată și testează binarul. Nolera a fost respinsă cu o corectură deja livrată de la distanță: povestesc asta în ghidul despre 2.1.
2. **Ce testează reviewerul trebuie să rămână ce primesc utilizatorii.** Dacă schimbi comportamentul în timpul review-ului, creezi o diferență între versiunea văzută și cea livrată.

## Note de review precise

2.3.1 respinge descrierile generice. Modelul pe care l-aș folosi, în engleză:

```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.
```

## Cum răspunzi la o respingere 2.3.1?

Răspunde în App Store Connect, unde [răspunzi la mesajul App Review](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/reply-to-app-review-messages/).

- **Mesajul rămâne vag**: întreabă ce funcție e vizată, ca dezvoltatorul din issue-ul din 2024.
- **O funcție reală e prost descrisă**: dă calea exactă și un video scurt, apoi completează notele.
- **Un comutator dezvăluie ceva nou**: scoate-l sau activează-l și descrie-l, apoi refă build-ul.
- **Codul de actualizare e problema**: explică faptul că servește la corecturi, în cadrul articolului 3.3.1(B). În issue-ul din 2023, Apple cerea eliminarea lui.

## Checklist 2.3.1 înainte de trimitere

- Fiecare noutate din versiune e descrisă în note, cu calea ei.
- Fiecare comutator de la distanță e activat pentru review și numit în note.
- Niciun cod nu-și schimbă comportamentul pentru reviewer.
- Accesele speciale sunt descrise: mod demo, cont de test, gest.
- Pagina și paywall-ul nu promit nimic din ce build-ul nu face.
- Nu se publică nicio actualizare de la distanță în timpul review-ului.

## Verifică-ți dosarul înainte de trimitere

[Review Kit](https://devoria.fr/ro/kits/app-review) adună checklist-ul meu dinainte de trimitere, modele de note pentru tester și skills Claude Code care îți verifică proiectul. Pentru o privire umană, [rezervă o oră cu mine](https://devoria.fr/ro/coaching): îți verificăm împreună notele de review și configurarea actualizărilor, prin video. Demersul complet e pe pagina [aplicație respinsă de Apple](https://devoria.fr/ro/expertise/aplicatie-respinsa-de-apple).

Îți pregătești prima lansare? [Fă diagnosticul gratuit](https://devoria.fr/ro/diagnostic): pune pașii în ordine și îți trimite checklist-ul meu anti-respingere Apple.

## Întrebări frecvente

### Ce înseamnă „Guideline 2.3.1 - Performance - Hidden Features”?

Apple consideră că aplicația ta conține o funcție ascunsă, inactivă sau absentă din notele de review. Mesajul poate viza și un cod capabil să schimbe aplicația după review, uneori împreună cu o respingere 2.5.2.

### Este EAS Update permis de Apple?

Licența permite codul interpretat descărcat atâta timp cât nu schimbă scopul principal al aplicației. Să corectezi, da. Să adaugi o funcție nerevizuită, nu.

### Poți folosi feature flags într-o aplicație iOS?

Da, dacă tot ce pot afișa a fost revizuit. Activează fiecare comutator pentru review și descrie-l în note.

### Trebuie semnalat un mod demo reviewerului?

Da. Un mod demo integrat cere acordul prealabil al Apple și trebuie să arate toate funcțiile.

### Poți publica o actualizare de la distanță în timpul review-ului?

Nimic nu interzice asta explicit. Dar reviewerul n-ar vedea-o la prima lansare și creează o diferență față de versiunea revizuită. Eu mă abțin mereu.


## Proiectul tău

[Review Kit](https://devoria.fr/ro/kits/app-review): Checklistul meu de review App Store, respingerile mele de la Apple rezolvate, checklistul pentru Google Play și trei skilluri Claude Code. 259 RON.

[iOS & Android Kit](https://devoria.fr/ro/kits/ios): Creează-ți aplicația de iPhone și Android cu Claude Code: codul de pornire al aplicațiilor mele, drumul până în store-uri și toate kiturile. 529 RON.

[Diagnostic: ce te desparte de aplicația ta de iPhone](https://devoria.fr/ro/diagnostic): 7 întrebări, 60 de secunde: afli ce te blochează de fapt să-ți publici aplicația de iPhone, traseul tău în 4 etape și kitul potrivit pentru tine.
