# EmuLocal — cahier des charges, faisabilité et configuration

Version du 16 octobre 2026. Prototype PWA distinct de Point du Jour et EmuQuot.
Nom provisoire : EmuLocal. Signature : « Votre journée, chez vous. »

## Conclusion de faisabilité

Un brief regroupant publications Web, en-têtes Gmail et événements peut être préparé dans le navigateur avec des règles locales, sans appel à une IA distante. Une PWA peut fournir ce fonctionnement sur ordinateur, téléphone et tablette compatibles. La connexion et les recherches nécessitent Internet ; une PWA fermée ne peut pas garantir une collecte automatique en arrière-plan.

Il est impossible d’imposer « aucune clarification CASA » comme résultat garanti. Le cahier des charges impose plutôt des flux vérifiables, minimisés et sans transfert des données Google au serveur. Google conserve la décision sur l’évaluation et la vérification OAuth. Le nouveau nom ou projet ne doit pas servir à ignorer une obligation notifiée à Point du Jour.

## Invariants de confidentialité implémentés

1. Le navigateur obtient et conserve le jeton OAuth en mémoire seulement. Aucun refresh token.
2. Les requêtes Gmail/Calendar partent directement du navigateur vers Google.
3. Gmail : format `metadata`, projection de champs excluant `snippet`, corps et pièces jointes.
4. Le récit utilise uniquement le modèle local construit à partir des titres, en-têtes et dates.
5. Aucun contenu Gmail, événement, jeton ou récit personnel n’est écrit dans localStorage, IndexedDB ou une base serveur.
6. Les données personnelles sont retirées lors de la déconnexion, du changement de compte et de la fermeture de page. L’expiration est contrôlée toutes les dix secondes lorsque la page s’exécute. Un onglet suspendu ne permet pas une garantie de délai exact.
7. Le service worker ignore les appels externes et toutes les routes `/api/`.
8. `/api/search` refuse les champs autres que `subjects`, `keywords`, `sources`.
9. Les résultats sont rendus par `textContent` et liens HTTPS validés, pas par injection du HTML public.
10. Aucun SDK d’analytique, Gemini ou autre IA distante n’est intégré. Le script Google Identity Services est chargé après l’action de connexion.

Ces invariants ont des tests automatisés de non-transmission et de projection des données. Ils ne constituent pas un audit CASA, un test d’intrusion ou une preuve réseau avec votre compte connecté.

## Parcours

- Mon brief : récit court, publications récentes, messages du jour, agenda, événements à venir. Listes compactes de cinq éléments, surplus dépliable. Impression courte.
- Mes réglages : prénom local facultatif, sujets, mots-clés, sources, actualisation à l’ouverture facultative, connexion Google, image de fond et effacement.
- Comment ça marche : explication des flux et limites.
- Pages HTML dédiées : Confidentialité et Utilisation.
- Exemple fictif : montre les trois fonctions sans importer de données privées et sans présenter de fausses actualités comme réelles.

## Recherche effectivement disponible

Cette version n’a pas de clé de moteur payant et ne réalise aucun appel facturable. Elle collecte jusqu’à six sources RSS/Atom, les complète avec le flux Google Actualités puis conserve jusqu’à 24 résultats. Un lien Google général permet d’élargir la recherche.

Cette approche ne remplace pas un moteur Web général. Les offres d’emploi, restaurants, hébergements, produits et sujets non couverts par les flux peuvent ne pas donner de résultat. Google Actualités n’offre pas de garantie de disponibilité ; ses liens peuvent mener à une page intermédiaire.

Pour une recherche générale importée dans l’application, prévoir ensuite une clé éditeur Brave ou un service de recherche équivalent, avec quotas serveur et coût annoncé. Il ne doit recevoir que les critères publics. Aucun accès Google personnel n’est nécessaire pour ce moteur. Ne pas récupérer automatiquement une clé d’une autre application ni exposer une clé fournisseur dans le navigateur.

## Gmail et calendrier : périmètre et limites

- Scope Gmail : `https://www.googleapis.com/auth/gmail.metadata`.
- Scope Agenda : `https://www.googleapis.com/auth/calendar.events.readonly`.
- `gmail.metadata` est restreint : ce choix minimise les données, il ne supprime pas la vérification ni ne garantit une dispense CASA.
- Pas de requête `q` Gmail avec ce scope. Jusqu’à 100 messages récents sont examinés puis filtrés localement selon la journée Europe/Paris, les dates et catégories exclues. Cela n’est pas une lecture exhaustive de tous les messages du jour.
- Priorités : libellé Gmail IMPORTANT et mots du sujet. Pas de lecture du corps ni d’interprétation sémantique générative.
- Agenda principal seulement : aujourd’hui et les six jours suivants, 100 événements au maximum. L’alerte temporelle porte sur les prochaines 24 heures, elle ne garantit pas la détection des urgences réelles.
- Liens Gmail par Message-ID ou recherche de sujet ; liens d’événements `htmlLink` Google lorsque disponibles.
- Un compte par session ; comptes différents simultanés sur plusieurs appareils. Aucun historique personnel synchronisé.

## Configuration Google encore nécessaire

La première version est livrée sans client OAuth Google configuré. Elle n’utilise pas silencieusement celui d’EmuQuot.

1. Dans Google Cloud, créer ou choisir le projet réellement destiné à EmuLocal. Ne pas changer de projet pour contourner une décision existante : décrire honnêtement la nouvelle architecture et les applications associées.
2. Activer les API Gmail et Google Calendar.
3. Configurer Google Auth Platform : nom EmuLocal, email support, audience et testeurs. Déclarer les deux scopes ci-dessus et justifier la lecture des en-têtes et événements.
4. Créer un client OAuth de type « Application Web ».
5. Ajouter comme origine JavaScript exacte `https://emulocal.bastiaan31.chatgpt.site`, sans chemin ni barre finale. Si un domaine propre est ensuite raccordé, ajouter son origine exacte aussi.
6. Relever uniquement l’identifiant public `…apps.googleusercontent.com`. Aucun secret client dans cette PWA.
7. Dans EmuLocal > Mes réglages > Configurer la connexion Google, saisir cet identifiant. Il est gardé localement. Alternative éditeur : définir `GOOGLE_CLIENT_ID` dans les variables d’hébergement puis republier ; `/api/config` ne fournit que cet identifiant public.
8. Cocher l’autorisation, cliquer Connecter. Le premier clic charge Google Identity Services ; un second clic ouvre le consentement, afin de respecter les restrictions des fenêtres contextuelles.
9. Tester avec un compte test sans données sensibles. Fournir à Google la vidéo de consentement et les preuves de flux.
10. Avant commercialisation, rendre les pages de présentation et de confidentialité publiques sur un domaine vérifié, puis terminer la procédure Google applicable. Le prototype d’hébergement est initialement privé au propriétaire.

Le client public et la configuration de consentement ne peuvent pas être inventés ou validés par le code de l’application. La validation Google n’est pas incluse dans le déploiement technique.

## Preuve réseau à réaliser avant toute déclaration de dispense

Avec un compte de test : ouvrir l’onglet Réseau des outils du navigateur, se connecter, préparer le brief et consulter les destinations. Vérifier que les en-têtes Authorization Google vont uniquement aux API Google, et que `/api/search` ne contient que les trois critères autorisés. Tester déconnexion, refus partiel de scope, expiration, changement de compte, rechargement et révocation. Ne jamais diffuser un HAR brut contenant jetons ou données personnelles ; expurger les preuves.

## Contrôles réalisés automatiquement

- Rejet serveur de champs privés ou supplémentaires.
- Sérialisation de recherche sans nom, jeton, mail ni événement.
- Modèle des messages sans corps, extrait ou pièce jointe.
- Simulation des appels Google : destinations directes et projection metadata.
- Déconnexion : suppression du jeton et du compte.
- Dates Paris, fins exclusives à minuit et séparation des publications sans date.
- Vérification syntaxique des modules et compilation de la PWA.

À compléter : essai navigateur réel, recherche réseau réelle, connexion OAuth réelle après configuration, installation sur Xiaomi/PC/iPhone, revue de sécurité complète et décision Google. Aucun test avec vos vrais messages n’a été effectué pour cette version.

## Android et commercialisation

Commencer par valider cette PWA. Une distribution Android peut ensuite reprendre le site via une Trusted Web Activity avec association de domaine, paquet signé et tests du consentement. Un simple emballage APK ne supprime pas les exigences Google.

Aucun paiement ou droit premium n’est activé ici. Un futur service Stripe peut gérer achats et droits sans recevoir les données Gmail/Agenda. La protection commerciale d’une fonction intégralement locale est moins forte qu’un traitement serveur : ne pas déplacer les données Google vers un serveur pour protéger l’abonnement sans réexaminer la conformité et le périmètre CASA.

## Exécution et sources

Interface : `public/index.html`, `public/app.js`, `public/google-local.js`, `public/local-model.js`, `public/background.js`.
Service public : `app/api/search/route.ts`, contrat `lib/search-policy.mjs`.
Tests : `node --test tests/privacy.test.mjs`.
Construction : `node scripts/run-framework.mjs build` dans le projet préparé.

Références officielles vérifiées le 16 octobre 2026 :
- https://developers.google.com/identity/protocols/oauth2/production-readiness/restricted-scope-verification
- https://developers.google.com/workspace/gmail/api/auth/scopes
- https://developers.google.com/workspace/gmail/api/reference/rest/v1/users.messages/list
- https://developers.google.com/workspace/gmail/api/reference/rest/v1/users.messages/get
- https://developers.google.com/workspace/calendar/api/auth

Reprise autorisée de la scène d’émeus et de l’esprit translucide d’EmuQuot ; logo vectoriel EmuLocal distinct. Les applications existantes ne sont pas modifiées.

## Mise à jour du filtre et du logo

Les en-têtes List-Id, List-Unsubscribe et Precedence complètent les libellés Gmail pour filtrer localement les publicités et les listes. L’option de masquage des lettres de diffusion est activée par défaut mais réversible. Le filtre ne peut garantir de repérer toute publicité ; aucun message n’est supprimé. Le logo EmuLocal reprend l’émeu à lunettes de la scène, la signature au-dessus et le nom au-dessous. Le fichier `assets/EmuLocal.png` mesure exactement 120 × 120 pixels ; les icônes PWA sont déclinées en 192 et 512 pixels.
