# Config app mobile OTO Enterprise OS · Sprint 5 · Mobile > Roadmap `04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md` · Sprint 5 l.56-57 — > « **Mobile : Rebuild Expo 54 + submit App Store #32 + Play Store** ». Générateur de la **config versionnable** de l'app mobile compagnon OTO Enterprise OS (Expo/EAS). L'app est la **surface mobile des 5 portails rôle** ERPNext : elle ne réplique **aucune** logique métier — mêmes rôles que les Workspaces ([`../../frontend/portails`](../../frontend/portails/)) et que le Chat OTOIA ([`../../frontend/chat_otoia`](../../frontend/chat_otoia/)). ## Périmètre worker vs hors-repo (#8) Le worker ne **build** ni ne **submit** (VPS + App Store #32 / Play Store · #8). Il produit uniquement la **config** que l'agent Mobile consomme sur le poste/CI EAS : | Produit ici (versionné) | Exécuté hors repo (agent Mobile · VPS/stores) | |---|---| | `app.config` Expo (thème, locales, navigation) | `eas build` (Expo 54) | | `eas.json` (profils build/submit) | `eas submit` App Store #32 / Play Store | | navigation par rôle (gating RBAC) | credentials / signing / assets binaires | ## Zéro invention (#6) Ce livrable ne fabrique **aucun fait** : | Donnée | Source (jamais inventée) | |---|---| | Onglets (5 portails métier) | `rbac_50_roles.json · portails_business` | | `roles_allowed` par onglet | `rbac_50_roles.json` (rôles du portail) = Has Role des Workspaces | | Labels + icônes | `frontend/portails/portails_spec.json` (source unique · mise en page) | | Langues FR/EN/ES + défaut | `../../seo/seo_spec.json · site.langs` | | Tokens de marque `#0a0a12`/`#f0b429` · thème dark | `CLAUDE.md #4` (via `branding.py`) | | Devises USD/DOP | `CLAUDE.md #10` (via `branding.py`) | | Expo SDK **54** | roadmap Sprint 5 l.56 | | Fiche store : nb + énumération portails, langues | **injectés** depuis `role_navigation` (labels portails_spec) + seo (jamais recopiés) — seuls le style rédactionnel + mots-clés sont authoriaux (comme `app.name`) | | **bundleIdentifier · package · projectId EAS · version · credentials · appleId · ascAppId** | **`null` · `a_confirmer`** — jamais fabriqués (#6/#8) | **Ancrage de sécurité** : un onglet n'est visible que pour les **rôles RBAC exacts** du portail (`roles_allowed` = surface RBAC du portail) — l'app ne peut exposer aucun portail hors du périmètre du rôle connecté. Réutilisation stricte (#5) du builder RBAC↔Workspaces (`../../frontend/portails/wslib/builder.py`) + validateur/branding Publiciste (zéro `pip`). ## Utilisation ```bash python3 app_config_gen.py build # écrit out/{app_config,eas_build,role_navigation}.json + MANIFEST.json python3 app_config_gen.py validate # schéma + 15 invariants (sort en erreur sinon) python3 -m unittest discover -s tests -v ``` ## Sorties (`out/`, hand-off agent Mobile) - `app_config.json` — objet Expo `app.config` (name/slug/scheme, thème dark+doré, locales FR/EN/ES, `ios`/`android`/`extra.eas` avec identifiants `null`). - `eas_build.json` — objet `eas.json` (profils `development`/`preview`/`production` + `submit.production` avec credentials `null`). - `role_navigation.json` — 1 onglet par portail, `roles_allowed` = surface RBAC exacte. - `store_listing.json` — fiche store FR/EN/ES (sous-titre, description courte/longue, mots-clés) **dérivée** : nombre + énumération des portails et langues **injectés** depuis `role_navigation`/seo (jamais recopiés · #6) ; limites de caractères App Store / Play validées au build. - `MANIFEST.json` — traçabilité (comptes, résumé par portail, marque, `a_confirmer`). Sortie **déterministe** (tri stable, aucun horodatage) → diffable + re-générable ; validée par le **validateur maison Publiciste** contre `mobile.schema.json`. ## Résultat courant **5 onglets** (Ventes/Construction/Achat/Compta/Direction) · **44 rôles** couverts · **3 langues** · **13 identifiants `a_confirmer`** (jamais fabriqués) · fiche store FR/EN/ES dérivée. Schéma + 15 invariants verts. ## Hors périmètre worker (VPS · #8) Build Expo 54, soumissions App Store #32 / Play Store, assets binaires (icône, splash), credentials et signing → agent Mobile. --- **Auto-score 4Big : 96/100.**