245 lines
24 KiB
Markdown
245 lines
24 KiB
Markdown
# Assistant V2.1 ObsiGate — Phase 3 : Le monde (connecteurs, synchronisation, client MCP)
|
||
|
||
| Champ | Valeur |
|
||
|---|---|
|
||
| Phase | **3 sur 5** — l'assistant se branche sur les services de Bruno |
|
||
| Document parent | `ASSISTANT-V2.1.md` — en particulier §11 (connecteurs, sync, replis, envoi encadré, client MCP), §9.6 (candidats mémoire), §15 (politiques) |
|
||
| Version | 1.0 — 9 octobre 2026 |
|
||
| Auteur | Spark, pour Bruno |
|
||
| Statut | Prêt à implémenter |
|
||
| Tranches | **#195** (cadre connecteurs + moteur de sync), **#196** (Google Calendar + Gmail + replis zéro-OAuth), **#197** (Microsoft Teams/Outlook), **#198** (Discord lecture + Notion + Drive), **#207** (ObsiGate client MCP) |
|
||
| Effort estimé | 17–23 jours |
|
||
| Prérequis | Phase 0 (politiques #213 — provenance et règles d'envoi ; runs #206), phase 1 (plan et tâches qui consomment l'agenda), phase 2 (bus d'événements #208 qui consomme la sync) |
|
||
| Dépendances | #195 ← — ; #196, #197 ← #195, #213 ; #198 ← #195 ; #207 ← #195, #213 |
|
||
| Débloque | Phase 4 (engagements détectés dans les courriels en mode candidats, préparation de réunions sur agenda réel), phase 5 (packs Communication/Voyages complets) |
|
||
|
||
> **Résultat visible à la fin de cette phase.** Le plan du jour voit le **vrai agenda** et les vrais courriels. Les connecteurs Google, Microsoft, Discord, Notion et Drive sont installés via le cadre unifié « Sources connectées » : OAuth2 + PKCE quand il le faut, mais aussi des **replis sans aucun projet cloud** (iCal, CalDAV, IMAP) qui débloquent l'agenda et le courriel dès l'installation. Un moteur de **synchronisation incrémentale** maintient un état local frais que consomment le plan, les rappels et les automatisations (événements `connector.object.*` enfin émis). L'assistant cherche et lit le courriel, crée des brouillons, et **envoie** — uniquement sur approbation renforcée du texte final exact, jamais depuis une tâche planifiée. Enfin, ObsiGate devient **client MCP** : les serveurs MCP externes de Bruno entrent dans le même registre, sous les mêmes politiques.
|
||
|
||
---
|
||
|
||
## Table des matières
|
||
|
||
1. [Objectif et principe directeur](#1-objectif-et-principe-directeur)
|
||
2. [Périmètre](#2-périmètre)
|
||
3. [État d'entrée](#3-état-dentrée)
|
||
4. [Modèle de données](#4-modèle-de-données)
|
||
5. [Tickets de travail](#5-tickets-de-travail)
|
||
6. [API livrée par la phase](#6-api-livrée-par-la-phase)
|
||
7. [Comportements détaillés](#7-comportements-détaillés)
|
||
8. [Tests et golden tasks](#8-tests-et-golden-tasks)
|
||
9. [Critères d'acceptation de la phase](#9-critères-dacceptation-de-la-phase)
|
||
10. [Risques spécifiques et vigilance](#10-risques-spécifiques-et-vigilance)
|
||
11. [Ordre d'exécution](#11-ordre-dexécution)
|
||
12. [Définition de « terminé »](#12-définition-de--terminé-)
|
||
|
||
---
|
||
|
||
## 1. Objectif et principe directeur
|
||
|
||
Le principe : **la prise de notes reste le vault ; les connecteurs nourrissent et exécutent, ils ne remplacent rien** (hérité de la V2, conservé). La phase ajoute deux corollaires propres à la V2.1 :
|
||
|
||
- **Un état frais ou un aveu d'état périmé.** Le plan, les déclencheurs et les réponses s'appuient sur le cache synchronisé ; si la sync a échoué, l'assistant le dit (« agenda non synchronisé depuis 2 h ») au lieu de planifier sur du vide.
|
||
- **L'écriture externe est un privilège d'exécution, pas une capacité de fond.** Créer un événement, un brouillon ou envoyer suit les niveaux d'autonomie et la politique de provenance (phase 0) : rien d'externe ne part d'un contenu lu sans validation humaine du résultat final.
|
||
|
||
## 2. Périmètre
|
||
|
||
### 2.1 Inclus
|
||
|
||
- #195 : cadre `backend/connectors/` (interface, registre, installations, secrets 0600/env, OAuth2 code + PKCE, refresh transparent, retry/backoff, rate-limit par connecteur, audit de chaque `call()`) ; migration des sources Gitea/GitHub existantes sous le cadre (même UX) ; UI « Sources connectées » étendue (statut, scopes, test, journal d'appels, budget) ; **moteur de sync incrémentale** (collections déclarées, curseurs, webhooks fournisseurs quand disponibles sinon polling adaptatif, cache d'objets normalisés, émission des événements bus, page santé des syncs).
|
||
- #196 : Google Calendar (lire/écrire) et Gmail (chercher/lire/brouillon/**envoyer** selon §7.3) sur le même consentement ; **replis zéro-OAuth** : iCal (lecture), CalDAV (lecture/écriture), IMAP (lecture courriel) ; guide d'installation Google pas-à-pas FR/EN.
|
||
- #197 : Microsoft Graph — Teams (lire les salons choisis, envoyer en WRITE confirmé) et Outlook (courriel et calendriers, envoi selon §7.3) sur le même jeton Entra ID.
|
||
- #198 : Discord en lecture par bot REST (pas de gateway en v1) en plus du webhook de sortie existant ; Notion (rechercher/lire/appendre, sync vers l'index de recherche) ; Drive (rechercher/lire, import vers le vault).
|
||
- #207 : client MCP (serveurs déclarés par Bruno ; outils préfixés `mcp.<serveur>.*` dans le registre ; niveau de confiance par serveur ; empreinte de schéma et suspension en cas de changement).
|
||
|
||
### 2.2 Exclu (phases ultérieures)
|
||
|
||
- La **détection d'engagements dans les courriels** en production (#211, phase 4) : la phase livre le réglage candidats mémoire (§9.6 du parent, défaut `off`) et le pipeline ; l'activation métier est en phase 4.
|
||
- Les packs qui consomment ces connecteurs au-delà du socle (Voyages, Communication avancée — phase 5).
|
||
- Slack (option future, inchangé depuis la V2), l'envoi SMTP direct (l'envoi passe par les APIs Google/Microsoft), toute écriture Discord autre que le webhook existant.
|
||
- La visioconférence et l'enregistrement de réunions : phase 4 (#209) pour la préparation et les comptes rendus, sur l'agenda livré ici.
|
||
|
||
## 3. État d'entrée
|
||
|
||
| Élément | Usage en phase 3 |
|
||
|---|---|
|
||
| Sources connectées Gitea/GitHub (#92/#103), `connected.py`, `secrets.py` | Précédent à généraliser ; migration sans perte d'UX |
|
||
| Moteur de politiques + provenance (#213, phase 0) | Toute donnée connecteur entre avec `connector:<id>` ; les règles d'envoi et de sensibilité s'appliquent telles quelles |
|
||
| Runs et approbation renforcée (phase 0/1) | Envois et écritures externes sont des steps de runs, approuvés dans la file unifiée |
|
||
| Plan, tâches, automatisations (phases 1–2) | Consommateurs de l'agenda synchronisé et des événements `connector.object.*` |
|
||
| Scheduler amendé (phase 2) | Les jobs de sync sont des tâches planifiées système (visibles, journalisées) |
|
||
|
||
## 4. Modèle de données
|
||
|
||
```sql
|
||
-- data/connectors_cache.sqlite3 (reconstructible par re-sync complète)
|
||
CREATE TABLE sync_state (
|
||
user_id TEXT NOT NULL, connector_id TEXT NOT NULL, collection TEXT NOT NULL,
|
||
cursor TEXT, -- token/page/date du fournisseur
|
||
last_sync_at TEXT, last_error TEXT, status TEXT NOT NULL DEFAULT 'ok',
|
||
PRIMARY KEY (user_id, connector_id, collection)
|
||
);
|
||
CREATE TABLE synced_objects (
|
||
user_id TEXT NOT NULL, connector_id TEXT NOT NULL,
|
||
external_id TEXT NOT NULL, type TEXT NOT NULL, -- event|message|chat|page|file
|
||
title TEXT, starts_at TEXT, ends_at TEXT,
|
||
participants_json TEXT, excerpt TEXT, -- extrait borné, JAMAIS le corps complet
|
||
link TEXT, updated_at TEXT NOT NULL,
|
||
PRIMARY KEY (user_id, connector_id, external_id)
|
||
);
|
||
```
|
||
|
||
Installations et secrets : fichiers existants du patron V2 (`data/connectors.json` pour le public, `data/connector_secrets.json` 0600 ou variables `OBSIGATE_CONNECTOR_SECRET_<ID>` ; jetons OAuth chiffrés avec `data/secret.key`). Les collections synchronisables et leurs fenêtres (agenda ±30 j ; courriel : dossiers choisis, 14 j glissants ; Teams : salons choisis) sont déclarées par chaque connecteur, réglables dans l'UI.
|
||
|
||
## 5. Tickets de travail
|
||
|
||
*Convention : chaque ticket est indépendamment testable ; « Fichiers » donne les points d'ancrage d'après la V2.1 — à confirmer contre le code réel au démarrage du ticket. Les fournisseurs sont développés et testés contre des **simulateurs** (le harnais golden de la phase 0), les appels réels étant vérifiés en recette manuelle documentée par connecteur.*
|
||
|
||
### Cadre & sync — #195
|
||
|
||
**P3-T01 — Interface connecteur et registre.**
|
||
Fichiers : `backend/connectors/base.py`, `backend/connectors/registry.py`, `backend/connectors/oauth.py`.
|
||
Travail : `ConnectorInterface` (id, label, URL de doc, scopes, capabilities nommées, collections synchronisables) ; installation/désinstallation ; flux OAuth2 code + PKCE générique (endpoints d'allowlist codée par fournisseur) avec redirect `/api/connectors/{id}/callback`, échange + stockage du refresh token chiffré, refresh anticipé et 1 retry sur 401 dans `call()` ; auth par token statique pour les connecteurs qui s'y prêtent ; timeouts httpx 15 s, retry backoff, rate-limit par connecteur, cache GET court (TTL 5 min) pour le contexte de chat.
|
||
Acceptation : un connecteur de test (fixture OAuth complète) s'installe, se teste, se rafraîchit et se désinstalle de bout en bout ; aucun secret n'apparaît dans les logs ni les retours d'outils (redaction vérifiée).
|
||
|
||
**P3-T02 — UI Sources connectées et migration Gitea/GitHub.**
|
||
Fichiers : `backend/routers/connectors.py`, page Configurations.
|
||
Travail : cartes par connecteur (statut, scopes accordés, boutons Connecter/Tester/Déconnecter, journal des derniers appels depuis l'audit, budget) ; migration interne de `connected.py` : Gitea/GitHub deviennent deux connecteurs du cadre, configurations existantes relues sans ressaisie ; les outils historiques gardent leurs noms.
|
||
Acceptation : une installation avec Gitea/GitHub configurés « à l'ancienne » fonctionne après migration sans intervention ; la page montre les appels récents des deux sources.
|
||
|
||
**P3-T03 — Moteur de synchronisation incrémentale.**
|
||
Fichiers : `backend/connectors/sync.py`, jobs scheduler système.
|
||
Travail : pour chaque installation et collection : sync initiale bornée puis incrémentale par curseur ; réception webhook fournisseur quand le connecteur le déclare (Google/Microsoft), sinon polling adaptatif (défaut 15 min, ralenti la nuit, accéléré à l'approche d'un événement) ; normalisation des objets (§4) ; émission `connector.object.created|updated` sur le bus de la phase 2 ; erreurs → `last_error` + statut, jamais d'exception silencieuse ; re-sync complète manuelle depuis l'UI.
|
||
Acceptation : un événement créé côté fournisseur (simulateur) apparaît dans le cache et émet l'événement bus en moins d'un cycle de polling ; la suppression côté fournisseur retire l'objet du cache (pas de fantôme dans le plan).
|
||
|
||
**P3-T04 — Santé des connecteurs.**
|
||
Travail : agrégation par connecteur (dernière sync, retard, taux d'erreur, quota estimé) exposée dans la carte et au centre de contrôle ; signal de dégradation consommé par le plan et le briefing (le consommateur affiche « données périmées » avec l'âge) ; un connecteur déconnecté retire ses outils du registre présenté au modèle (`list_tools` filtré par capabilities actives, comme le prévoit la V2 pour Tauri).
|
||
Acceptation : couper la sync (simulateur en échec) fait apparaître l'âge des données dans le plan du jour suivant, sans bloquer le plan.
|
||
|
||
### Google — #196
|
||
|
||
**P3-T05 — Calendar : lecture et écriture.**
|
||
Travail : capabilities `gcal.list_events` (READ), `gcal.get_event` (READ), `gcal.create_event` (WRITE), `gcal.update_event` (WRITE), toutes avec post-conditions `verify` (relecture de l'événement) et inverses (suppression de l'événement créé) ; le plan du jour (phase 1) bascule sa source d'agenda sur le cache synchronisé quand le connecteur est actif ; les blocs validés du plan peuvent être écrits dans l'agenda (option « plan → agenda », désactivée par défaut).
|
||
Acceptation : « bloque 2 h jeudi pour la présentation » crée l'événement vérifié, visible au plan ; le désactiver (déconnexion) rend le plan à sa source vault sans erreur.
|
||
|
||
**P3-T06 — Gmail : chercher, lire, brouillonner.**
|
||
Travail : `gmail.search_messages` (syntaxe du fournisseur), `gmail.read_message`, `gmail.create_draft` (WRITE, inverse = suppression du brouillon) ; citation systématique dans les réponses (expéditeur, date, lien) ; le contenu lu porte la provenance `connector:gmail` et ne peut pas, seul, justifier une action externe (politique phase 0 — test dédié).
|
||
Acceptation : « ai-je une réponse du dentiste ? » répond depuis le cache + lecture à la demande, avec citation ; aucun fait mémoire n'est créé depuis un courriel sans passer par le mode candidats (§9.6, défaut `off`).
|
||
|
||
**P3-T07 — Envoi encadré.**
|
||
Travail : `gmail.send` (DANGEROUS) selon le parent §11.4 : brouillon d'abord (T06), carte d'approbation **renforcée** sur le texte final exact (destinataires, objet, corps ; toute modification régénère la carte), interdiction structurelle depuis tâches planifiées et automatisations (la politique refuse avant même la carte), journalisation en step de run avec inverse = néant affiché.
|
||
Acceptation : les trois refus sont prouvés par tests (envoi en tâche planifiée ; envoi dont le corps est une copie d'un courriel reçu sans reformulation validée ; envoi après modification du brouillon sans nouvelle carte) ; un envoi approuvé part une fois (idempotence).
|
||
|
||
**P3-T08 — Replis zéro-OAuth : iCal, CalDAV, IMAP.**
|
||
Fichiers : `backend/connectors/ical.py`, `caldav.py`, `imap.py`.
|
||
Travail : iCal par URL secrète (lecture, sync par le moteur T03) ; CalDAV (lecture + création/màj d'événements, mot de passe d'application comme secret) ; IMAP (lecture : recherche et lecture, collections = dossiers choisis) ; ces connecteurs apparaissent dans la même matrice et la même UI, avec leurs limites affichées (« lecture seule » pour iCal/IMAP).
|
||
Acceptation : un agenda iCloud/Nextcloud de test est lisible dans le plan sans aucun projet Google/Microsoft ; un compte IMAP de test répond à `mail.search` en lecture seule (toute tentative d'écriture est absente du registre, pas seulement refusée).
|
||
|
||
### Microsoft — #197
|
||
|
||
**P3-T09 — Graph : socle et Teams.**
|
||
Travail : client Graph minimal (auth Entra ID via le cadre OAuth, pagination, erreurs typées) ; `teams.list_chats` (READ, salons choisis), `teams.read_messages` (READ), `teams.send_message` (WRITE avec confirmation affichant le salon et le texte exact — même régime que l'envoi courriel, adapté : pas de brouillon côté Teams, la carte tient lieu de relecture).
|
||
Acceptation : lire un salon et y répondre via carte fonctionne sur tenant de test ; un salon non choisi n'est ni synchronisé ni lisible par l'outil.
|
||
|
||
**P3-T10 — Outlook : courriel et calendriers.**
|
||
Travail : `outlook.search_messages`, `outlook.read_message`, `outlook.create_draft`, `outlook.send` (même ticket de politique que P3-T07 — factoriser, ne pas dupliquer la logique d'approbation), `outlook.list_events` alimentant le cache d'agenda au même titre que gcal (le plan fusionne les calendriers actifs en signalant la source de chaque événement).
|
||
Acceptation : un plan peut mélanger événements Google et Outlook sans doublon quand le même événement existe des deux côtés (dédup par titre+horaires signalée en carte, jamais de fusion silencieuse).
|
||
|
||
### Discord, Notion, Drive — #198
|
||
|
||
**P3-T11 — Discord en lecture.**
|
||
Travail : bot token (secret) ; `discord.list_messages` et `discord.search` en REST sur les salons choisis ; le webhook de sortie existant (#168) devient la capability `discord.send` du connecteur (WRITE via notify, pas de doublon de code) ; pas de gateway websocket (limite affichée : pas de temps réel, sync par polling).
|
||
Acceptation : la recherche dans un salon de test retrouve un message cité ; les salons non choisis sont inaccessibles aux outils.
|
||
|
||
**P3-T12 — Notion : lire, appendre, synchroniser la recherche.**
|
||
Travail : API key (token interne) ; `notion.search`, `notion.read_page`, `notion.append_blocks` (WRITE confirmé) ; les pages choisies sont synchronisées vers l'**index de recherche** d'ObsiGate (elles deviennent trouvables par la recherche et le recall, marquées `connector:notion` — jamais copiées dans le vault sans demande explicite d'import).
|
||
Acceptation : « cherche dans Notion et dans mes notes » répond des deux sources distinguées ; un append est vérifié par relecture.
|
||
|
||
**P3-T13 — Drive : chercher, lire, importer.**
|
||
Travail : `drive.search`, `drive.read_file` (Docs/Sheets convertis en texte/markdown via l'API) ; import explicite vers le vault (`drive.read_file` → proposition de note, propose/apply existant) rattaché au backlog d'import ; lecture seule stricte (aucune écriture Drive cette phase).
|
||
Acceptation : importer un document Drive crée une note du vault citant sa source ; l'original Drive n'est jamais modifié.
|
||
|
||
### Client MCP — #207
|
||
|
||
**P3-T14 — Branchement de serveurs MCP externes.**
|
||
Fichiers : `backend/connectors/mcp_client.py`.
|
||
Travail : déclaration de serveurs (URL/transport, authentification par secret) ; découverte des outils à la connexion ; enregistrement dynamique préfixé `mcp.<serveur>.*` avec risque déclaré par le serveur **plafonné** par la politique (un outil déclaré READ par le serveur mais à effets inconnus démarre au niveau d'autonomie 0–1) ; les contenus MCP portent la provenance `mcp:<serveur>` ; aucun contenu `sensitivity ∈ {private, sensitive}` n'est transmissible à un outil MCP externe (politique phase 0, test dédié).
|
||
Acceptation : un serveur MCP de test expose un outil utilisable en conversation au niveau 1 ; tenter de lui passer un fait `sensitive` est refusé et journalisé.
|
||
|
||
**P3-T15 — Empreintes de schéma et suspension.**
|
||
Travail : empreinte (hash canonique du schéma de chaque outil) stockée à la validation du serveur ; à chaque session, comparaison : un schéma modifié suspend l'outil (retiré du registre présenté au modèle) et crée une carte de revalidation montrant le diff de schéma ; la revalidation est manuelle, par serveur.
|
||
Acceptation : modifier le schéma d'un outil du serveur de test suspend exactement cet outil, pas les autres, et l'assistant explique la suspension au lieu d'échouer en silence.
|
||
|
||
### Finitions
|
||
|
||
**P3-T16 — Guides d'installation des fournisseurs.**
|
||
Travail : `docs/GUIDES/CONNECTEURS_GOOGLE_MS.md` pas-à-pas FR/EN (création des applications Google Cloud et Entra ID, écrans de consentement, URI de redirection) + section replis zéro-OAuth (où trouver l'URL iCal, créer un mot de passe d'application) ; fiches `docs/features/` pour #195–#198 et #207 ; clés i18n des Sources connectées et des cartes d'envoi.
|
||
Acceptation : un lecteur suivant le guide seul aboutit à un connecteur Google testé vert ; DoD du §12 pour le reste.
|
||
|
||
## 6. API livrée par la phase
|
||
|
||
| Route | Rôle | Ticket |
|
||
|---|---|---|
|
||
| `GET /api/connectors` · `POST /api/connectors/{id}/install|test|disconnect` | Installations et statut | P3-T01/T02 |
|
||
| `GET /api/connectors/{id}/authorize` · `GET /api/connectors/{id}/callback` | Flux OAuth2 + PKCE | P3-T01 |
|
||
| `GET /api/connectors/{id}/health` · `POST /api/connectors/{id}/sync` | Santé et re-sync manuelle | P3-T03/T04 |
|
||
| `GET/POST /api/connectors/mcp-servers` · `POST /api/connectors/mcp-servers/{id}/revalidate` | Serveurs MCP externes et revalidation | P3-T14/T15 |
|
||
|
||
Les capabilities connecteurs sont des outils `@tool` ordinaires (donc exposés au serveur MCP d'ObsiGate sous les mêmes politiques) ; il n'y a pas d'API REST par capability.
|
||
|
||
## 7. Comportements détaillés
|
||
|
||
### 7.1 Ce que la sync ne fait jamais
|
||
|
||
Le corps complet d'un courriel n'est **jamais** synchronisé (extrait borné seulement) ; rien de synchronisé n'entre dans le vault ni dans la mémoire sans le pipeline candidats (§9.6, défaut `off`) ; désinstaller un connecteur purge son cache et ses curseurs (les secrets sont retirés, l'audit conserve la trace des appels passés sans contenu).
|
||
|
||
### 7.2 Fuseaux et calendriers multiples
|
||
|
||
Les événements synchronisés conservent leur fuseau d'origine ; le plan les projette dans `OBSIGATE_TZ` en affichant l'heure d'origine quand elle diffère (voyage). Un événement « toute la journée » reste ancré à sa date, jamais converti en minuit UTC décalé.
|
||
|
||
### 7.3 L'envoi, en une phrase
|
||
|
||
**Brouillon toujours, envoi jamais sans le texte final sous les yeux, et jamais en automatique** : ces trois règles sont codées dans la politique (phase 0) et testées en P3-T07/T10 ; le réglage d'activation de l'envoi (décision ouverte n° 2 du parent) peut le désactiver par connecteur sans toucher au code.
|
||
|
||
### 7.4 Tauri et hors-ligne
|
||
|
||
Sans token installé, les capabilities sont absentes du registre présenté au modèle (pas d'outils fantômes) ; hors-ligne, l'assistant répond depuis le cache synchronisé en annonçant son âge ; aucune tentative réseau n'a lieu au démarrage (P8 du parent).
|
||
|
||
## 8. Tests et golden tasks
|
||
|
||
- Simulateurs : chaque fournisseur a un double HTTP (réponses figées + scénarios d'erreur : 401, 429, pagination, webhook) utilisé en CI ; aucun test CI ne dépend d'un vrai compte.
|
||
- Recette manuelle : par connecteur, un pas-à-pas de vérification sur compte réel, archivé dans la fiche de tranche (captures expurgées).
|
||
- Golden tasks nouvelles de la phase : **G9** — « événement créé côté fournisseur → présent au plan, et plan honnête si la sync tombe » ; **G10** — « envoi refusé en tâche planifiée, accepté en interactif sur texte exact » ; **G11** — « schéma d'outil MCP modifié → outil suspendu, autres intacts ». (Numérotation à la suite de G1–G8 du parent.)
|
||
- Non-régression : les sources Gitea/GitHub et les canaux de notification existants fonctionnent à l'identique après migration au cadre.
|
||
|
||
## 9. Critères d'acceptation de la phase
|
||
|
||
1. Google **ou** un repli zéro-OAuth suffit à alimenter le plan en agenda réel ; la fraîcheur des données est affichée, jamais présumée.
|
||
2. Une recherche de courriel répond avec citation ; un brouillon se crée ; un envoi n'a lieu que sur approbation renforcée du texte final, et jamais en planifié.
|
||
3. Désinstaller un connecteur retire ses outils, purge son cache et ses secrets, et dégrade proprement les consommateurs (plan, briefing).
|
||
4. Un serveur MCP externe fonctionne sous politique ; un changement de schéma suspend l'outil concerné avec une carte de revalidation.
|
||
5. G9, G10 et G11 sont verts en CI sur simulateurs.
|
||
|
||
## 10. Risques spécifiques et vigilance
|
||
|
||
| Risque | Vigilance |
|
||
|---|---|
|
||
| Création des applications OAuth = friction d'installation | Les replis zéro-OAuth (P3-T08) débloquent l'usage avant tout projet cloud ; le guide T16 est testé par un lecteur naïf |
|
||
| Quotas et changements d'API des fournisseurs | Tout passe par `call()` (rate-limit, backoff, audit) ; les échecs de sync dégradent, ne cassent pas (§7, P3-T04) |
|
||
| Double agenda = double vérité | Le cache distingue les sources ; la dédup d'affichage est signalée, jamais silencieuse (P3-T10) |
|
||
| Un connecteur compromis devient un canal d'injection | La provenance `connector:<id>` et les règles de la phase 0 s'appliquent à 100 % du contenu sync et lu ; les extraits synchronisés sont traités comme des données, jamais des instructions |
|
||
|
||
## 11. Ordre d'exécution
|
||
|
||
```
|
||
P3-T01 → T02 → T03 → T04 (#195 — la sync avant les connecteurs qui s'en servent)
|
||
P3-T05 → T06 → T07 ; T08 (#196 — T08 indépendant, parallélisable après T01)
|
||
P3-T09 → T10 (#197 — T10 réutilise la politique d'envoi de T07)
|
||
P3-T11 ; T12 ; T13 (#198 — parallélisables entre eux)
|
||
P3-T14 → T15 (#207 — après T01 et la politique phase 0)
|
||
P3-T16 (clôture)
|
||
```
|
||
|
||
## 12. Définition de « terminé »
|
||
|
||
DoD du document de phase 0 §12, inchangée, plus : recette manuelle sur compte réel archivée par connecteur ; toute capability d'écriture déclare sa post-condition et son inverse (exigence du parent §21) ; les golden tasks G9–G11 vertes en CI.
|