# Rapport de session · 2026-07-30 · session 19 (`20260730_092724`)

## Tâche

**Sprint 6 · ERPNext Backend** — Générateur du **Chat OTOIA embarqué par portail**
(roadmap `04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md` l.63 : « ERPNext Backend : **Chat
OTOIA embedded dans chaque portail** »).

C'est le **deuxième volet réalisable en repo** de Sprint 6, après le SEO trilingue
(session 18). Le troisième volet Sprint 6 — **OTOIA voice Amélie pilote AEC complet**
(BIM/Faisabilité) — dépend d'API externes / desk VPS et reste hors périmètre worker
(#8). Le volet « chat embarqué » a en revanche une **tranche repo nette** : le
**carrier natif** et sa **config de montage** par portail, indépendants du backend
conversationnel réel.

## Décision d'architecture (#1 ERPNext natif)

Dans ERPNext v15, un bloc de contenu réutilisable inséré dans un `Workspace` **EST**
le DocType `Custom Block` (`frappe/desk/doctype/custom_block`). On ne fabrique donc
**aucun** framework de chat externe : on livre **un `Custom Block` par portail** (un
`<div>` de montage vide et déterministe) + la **config runtime** (`chat_mount.json`)
que le web-component OTOIA consommera. Chaque `Custom Block` s'ancre sur le `Workspace`
du portail produit par le hand-off Sprint 4 (`frontend/portails`).

## Fichiers créés — `05_deliverables_mvp/frontend/chat_otoia/`

- `chat_spec.json` — présentation + persona seules (persona Amélie sourcée, capabilities
  OTOIA sourcées, `ui_label` FR/EN/ES générique, `endpoint: null`, tokens de marque).
- `chatlib/{__init__,deps,frappe,knowledge,builder}.py` :
  - `deps` **réutilise** (#5) le validateur + `branding` Publiciste **et** le builder
    RBAC↔Workspaces (`frontend/portails/wslib/builder.py`) → même surface RBAC, zéro
    duplication ; dérive les langues du `seo_spec.json` (source unique).
  - `frappe` : connaissance du DocType natif `Custom Block` (`block_name` + `html`).
  - `knowledge` : `roles_allowed` / `knowledge_scope` par portail, dérivés du CONTRAT.
  - `builder` : assemblage déterministe du bundle.
- `chat_otoia_gen.py` — CLI `build`/`validate` · **14 invariants**.
- `chat.schema.json` — contrat de sortie draft-07.
- `out/{custom_block,chat_mount,MANIFEST}.json` — hand-off.
- `tests/test_chat_otoia.py` (**31 tests** dont 11 injections négatives) · `README.md`
  · `.gitignore`.

## Fichiers modifiés

- `.gitea/workflows/ci.yml` : job `chat-otoia-tests` + ajout au `gate`.

## Anti-invention (cœur · #6)

Le générateur ne fabrique **aucun fait** :
- **endpoint OTOIA = `null` (`a_confirmer`)** — jamais fabriqué ; un invariant refuse
  tout endpoint non-null et refuse toute URL (`http(s)://`) dans le HTML de montage.
- **portée de connaissance = surface RBAC EXACTE du portail** (`permissions_cibles`) :
  l'assistant ne peut ni prétendre ni exposer un DocType hors du périmètre du portail.
  Ajouter/retirer un DocType est rejeté par invariant.
- **rôles autorisés = rôles du portail**, et un invariant vérifie qu'ils sont
  **synchronisés avec les Has Role réels des Workspaces** (`portails/out/workspace.json`)
  → cohérence inter-livrables prouvée.
- persona (`Amélie`/`multilingual_v2`), capabilities (`aec/knowledge/prompt_engine/chat.py`)
  et langues (FR/EN/ES) repris de sources **sourcées** (CLAUDE.md, seo_spec), jamais
  inventés ; le HTML de montage ne contient **aucun chiffre**.

## Résultat

5 portails métier (`plateforme` exclu comme les Workspaces) · 5 `Custom Block` ·
**44 rôles couverts** (= total restreint des Workspaces) · **35 DocTypes de
connaissance uniques** · endpoint `a_confirmer`.

## Vérifs

- **31/31** tests du livrable ; `validate` = schéma + 14 invariants verts ; build
  déterministe.
- Gate CI local vert : guard des contraintes · docs (liens OK) · JSON bien formés.
- **Régression : 408 tests verts au total** (377 → +31).

## Hors périmètre worker (VPS · #8)

Import des fixtures `Custom Block` (bench) · insertion d'un bloc `custom_block` dans
le `content` de chaque Workspace (payload editor.js `a_confirmer` selon patch v15) ·
renseignement de l'endpoint OTOIA + chargement du web-component via le thème desk ·
application des tokens dark+doré → agents ERPNext Backend / Frontend.

## Auto-score 4Big : 96/100.
