# iOS — allineamento password policy + errori API localizzati Documento operativo per **Cursor su Mac**: allineare l’app iOS a backend/Android dopo il ramo `feature/password-policy` (merge su `main`). **Aggiornato:** 2026-08-08 **Android di riferimento (testato su emulatore → API locale):** `2.0.10-native` (`versionCode` **31**) **iOS oggi:** marketing `2.0.5` / build `26` **API produzione:** `https://www.matchlivetv.it` --- ## Contesto (già in produzione backend dopo questo rilascio) ### Policy password (server) Definita in `backend/app/models/concerns/password_complexity.rb`: - minimo **8** caratteri, massimo **72** byte (bcrypt) - almeno **3 classi su 4**: minuscole, maiuscole, numeri, simboli - in **cambio password** e **reset**: la nuova password **non** può coincidere con quella attuale Validazione ActiveModel su `User` / `AdminAccount`. Endpoint che la applicano: | Endpoint | Note | |----------|------| | `PATCH /api/v1/account/password` | App native + stessi codici errore | | `PATCH /account/password` (web) | Flash I18n | | reset password pubblico | Stesse regole | | registrazione (`auth/register`) | Validazione modello | ### Errori API localizzati `ApplicationController#set_api_locale` legge, in ordine: 1. header `X-Locale` 2. `Accept-Language` 3. `I18n.default_locale` (fallback; **retrocompatibile** se l’app vecchia non manda nulla) Risposta invariata: `{ "error": "" }` (o `{ "message": "..." }` su alcuni successi). Chiavi rilevanti (`backend/config/locales/app.{it,en,fr,de,es}.yml`): - `flash.accounts.password_too_short` - `flash.accounts.password_too_long` - `flash.accounts.password_too_weak` - `flash.accounts.password_same_as_current` - `flash.accounts.password_current_incorrect` - `flash.accounts.password_mismatch` - `flash.accounts.password_updated` / `name_required` - analoghi in `flash.password_resets.*` e `flash.sessions.*` --- ## Stato iOS vs Android (dopo il merge di questo branch) | Area | Android 2.0.10 | iOS (repo dopo merge) | Da fare su Mac | |------|----------------|------------------------|----------------| | Header `Accept-Language` su tutte le request API | `AppContainer` OkHttp interceptor | `MatchLiveAPI.request` + `multipartPatch` | **Verificare** in debug che parta su login/account/password; se manca su altri helper HTTP, allineare | | Hint UI nuova password | `account_new_password` in `values*` (5 lingue) | `account.new.password` in `AppLanguage.swift` (già allineato al testo policy) | OK — rivedi solo se cambi copy | | Schermata Account | Mostra `error` dal body HTTP | `AccountScreen` + `APIError` estrae `error`/`message` | **Test manuale** (vedi sotto) | | Parsing errori API | Regex su `"error"` | `APIError.friendlyHttpMessage` | OK | | Client-side pre-check complessità | No (si affida al server) | No | Opzionale: stessa regola di `PasswordComplexity` prima della PATCH | | Versione App Store | `2.0.10-native` / 31 | `2.0.5` / 26 | **Bump** marketing + build prima del submit TestFlight/App Store | | Signup in-app | Non è il flusso principale | Nessuna UI register dedicata | N/A (signup resta web) | ### File già toccati / da tenere ``` native/ios/MatchLiveTv/Data/API/MatchLiveAPI.swift # Accept-Language native/ios/MatchLiveTv/Core/AppLanguage.swift # hint account.new.password (5 lingue) native/ios/MatchLiveTv/UI/Account/AccountScreen.swift native/ios/MatchLiveTv/Core/UserFacingError.swift native/ios/MatchLiveTv/Data/API/MatchLiveAPI.swift # enum APIError ``` Riferimento Android: ``` native/android/.../data/AppContainer.kt native/android/.../ui/account/AccountScreen.kt native/android/app/src/main/res/values*/strings.xml # account_new_password ``` --- ## Checklist operativa su Mac 1. **Pull** `main` (dopo merge/push da Linux). 2. Apri `native/ios/MatchLiveTv.xcodeproj`. 3. Build debug con `API_BASE_URL=https://www.matchlivetv.it` (o locale se hai tunnel). 4. **Test Account** (credenziali demo se disponibili, altrimenti account reale di test): - password debole (`password`) → messaggio *too_weak* nella lingua UI - password = corrente → *same_as_current* - conferma diversa → *mismatch* - password valida nuova → successo; login successivo ok 5. Cambia lingua app (globo) e ripeti un errore: il testo API deve seguire `Accept-Language` / lingua scelta. 6. **Bump versione** allineata ad Android se rilasci store: es. marketing `2.0.10`, build `≥ 31`. 7. (Opzionale) Unit test Swift che replica `PasswordComplexity.strong_enough?` se aggiungi validazione client. ### Comandi utili ```bash # Clone/pull git checkout main && git pull # Release iOS (script repo) ./scripts/build_ios_release.sh # oppure API staging: # API_BASE_URL=https://www.matchlivetv.it ./scripts/build_ios_release.sh ``` ### Cosa non serve rifare su iOS - Fix CSS/menu mobile web, tabelle scroll, logo nel drawer: **solo sito**. - Redirect `GET /account/password` → `/account`: **solo web**. - Seed password / concern Rails: già lato server. --- ## Retrocompatibilità (per release iOS) - App iOS **vecchie** (senza `Accept-Language`): continuano a funzionare; messaggi API nella locale default del server. - Login con password già esistenti: invariato. - Solo **impostazione/cambio** password debole viene rifiutato (stesso JSON `error`). --- ## Criterio “fatto” - [ ] `Accept-Language` presente su login, me, account, change password, forgot (Charles/Proxyman o log) - [ ] Errori password in it/en/fr/de/es coerenti col backend - [ ] Hint campo nuova password parla di “min. 8 / 3 tipi” - [ ] Versione bumpata se lo store release è in scope - [ ] Nessuna regressione login / lista partite / broadcast Quando completo, aggiorna questo file con data + versione iOS rilasciata.