# 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:** `2.0.10-native` (`versionCode` **31**) **iOS (allineato):** marketing `2.0.10` / build `31` **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 | Area | Android 2.0.10 | iOS | Stato | |------|----------------|-----|-------| | Header `Accept-Language` su tutte le request API | OkHttp interceptor | `MatchLiveAPI.request` + `multipartPatch` | **OK** | | Hint UI nuova password | `account_new_password` | `account.new.password` | **OK** | | Schermata Account | AccountScreen | AccountScreen | **OK** | | Forgot password | ForgotPasswordScreen | ForgotPasswordScreen | **OK** | | Parsing errori API | body `error` | `APIError.friendlyHttpMessage` | **OK** | | Client-side pre-check complessità | No | No | N/A (come Android) | | Versione store | `2.0.10-native` / **31** | `2.0.10` / **31** | **OK** | | Signup in-app | Non principale | Nessuna UI register | N/A (signup web) | ### File iOS ``` native/ios/MatchLiveTv/Data/API/MatchLiveAPI.swift native/ios/MatchLiveTv/Core/AppLanguage.swift native/ios/MatchLiveTv/UI/Account/AccountScreen.swift native/ios/MatchLiveTv/UI/Login/ForgotPasswordScreen.swift native/ios/MatchLiveTv/Resources/Info.plist native/ios/generate_xcodeproj.py ``` --- ## Criterio “fatto” - [x] `Accept-Language` su login, me, account, change password, forgot (`MatchLiveAPI`) - [x] Hint campo nuova password parla di “min. 8 / 3 tipi” - [x] Catalogo stringhe account/forgot in it/en/fr/de/es - [x] Versione bumpata a `2.0.10` / `31` - [ ] QA manuale errori password in lingua UI (weak / same / mismatch / success) Quando rilasci su TestFlight/App Store, conferma la build `31`.