# Dialog Orchestrator — Contexte, objectifs et tâches

Ce dossier décrit, cadre et suit l'introduction d'un **composant headless de dialogue** et d'un **orchestrateur multi‑instances** permettant:
- d'afficher des interactions système↔utilisateur de façon unifiée (confirmations, formulaires, parcours « tunnel »),
- de coexister avec plusieurs **embeds** (inertes, montés dans la page) et, si besoin, plusieurs **modales**,
- tout en garantissant qu'**une seule modale** est « focus‑trap » à un instant T (accessibilité forte),
- et en restant 100% **conforme V4** (UI sans logique métier; contrat HTTP/JSON canonique; mutations via `/api/commands`).

Le périmètre de cette passe se concentre sur l'Itération 1 (voir ci‑dessous): un noyau headless, un orchestrateur, des renderers par défaut (modal/inline), des helpers de remplacement `alert/confirm/prompt`, et l'intégration d'un premier flux réel côté Admin pour valider le pattern end‑to‑end.

## Pourquoi (Contexte & Motivation)
- Les interactions ad hoc (alert/confirm/prompt) sont limitées (a11y, i18n, tests) et hétérogènes.
- V4 impose « UI rend, moteur décide »: le back peut demander une interaction (200 OK + `interaction`), l'UI recueille des réponses et renvoie une **nouvelle commande**. Cela exige un composant générique robuste et testable.
- Besoin d'**embeds** prêts à agir (ex. dans une notification), coexistants avec des modales, sans « usine à gaz ».

## Vision & Principes V4
- **Headless**: état/validation/navigation, sans DOM ni métier.
- **Renderers**: modal (basée sur `<sb-modal>`) et inline/embeds (container ciblé), a11y stricte.
- **Orchestrateur**: registre d'instances, une modale active, embeds inertes activables; politiques simples.
- **Contrat JSON versionné**: schéma d'entrée/sortie minimal, extensible, avec DSL déclarative bornée pour conditions (visibleIf/next).

## Ce que nous livrons (Itération 1)
1) Engine headless + Orchestrateur
- API: `spawn/activate/close/list` + sucre `openDialog(def): Promise`.
- États: `idle → active → (completed|cancelled|expired)`.
- Politiques: defaults « modals=stack, embeds=coexist »; `maxOpenPerScope` (tous types confondus), `ttlMs`.
- Collisions: par défaut `LIMIT_REACHED` si (id,scope) dupliqués; `replace` autorisé seulement si `scope` ET `layout` identiques.

2) Renderers (par défaut)
- **Modal** (sb-modal): focus‑trap, `Esc`, aria‑labelledby/aria‑describedby, retour du focus invocateur.
- **Inline** (embed): monté sur `container:#id`, inerte (hors tab‑order) jusqu'à activation; fallback en modal si host introuvable.

3) Helpers
- `confirmDialog({ title, message, okLabel?, cancelLabel?, accent? })` → remplace confirm.
- `formDialog({ title, fields, defaults?, actions? })` → collecte de saisies simples.

4) Validations & DSL
- Champs: `required|min|max|pattern|message`.
- Cross‑field: `formValidation`.
- DSL bornée: `eq, ne, in, and, or, not` sur `$data` (réponses courantes) + `$ctx` (lecture seule), utilisée dans `visibleIf`/`next`.

5) Sécurité & limites (Itération 1)
- **Validateur de schéma** côté front (pré‑spawn): version supportée, champs inconnus, limites (taille/options), absence de cycles steps; logs dev avec codes normalisés: `SCHEMA_UNSUPPORTED_VERSION`, `SCHEMA_UNKNOWN_FIELD`, `SCHEMA_TOO_LARGE`, `SCHEMA_CYCLE_DETECTED`, `SCHEMA_INVALID_DSL`.
- `interactionId` **signé** + **TTL** (back): en cas d'expiration, fermer proprement (`INTERACTION_EXPIRED`) + toast.
- Aucune HTML injection; échappements systématiques.

6) Télémétrie minimale
- `interactionId`, `durationMs`, `path`, `meta.reason` (SUBMIT|CANCEL|EXPIRED|REPLACED) — sans données personnelles.

7) Conformité a11y (DoD)
- 1 seule modale active; autres modales = `inert + aria-hidden + tabindex=-1`.
- Embeds inertes: hors tab‑order jusqu'à activation.
- `Esc` ferme uniquement la **modale active** et respecte le **dirty‑guard** (`beforeClose`).
- Restauration du **focus invocateur** à la fermeture d'une modale.

## Ce que nous ne livrons pas (Itération 1)
- Queue/priorité/minimized avancés (peuvent venir en Itération 2 si le besoin se confirme).
- Champs riches complexes (tag‑picker, upload) et validations async (Itération 2+).

## Résumé du contrat I/O
- Entrée (schéma JSON versionné): `schemaVersion, id, layout, mode, size, title, fields/steps, actions, mount{host,activation}, policy{scope,concurrency,maxOpenPerScope,ttlMs}`.
- Sortie succés: `{ id, ok:true, values, meta:{ reason:"SUBMIT", durationMs, path } }`.
- Sortie annulation/expiration/remplacement: `{ id, ok:false, code, meta:{ reason:"CANCEL|EXPIRED|REPLACED" } }`.

## Plan & livrables (Itération 1)
- Orchestrateur + registre + renderers modal/embed + helpers confirm/form.
- Remplacement d'une confirmation réelle (Admin: suppression catégorie) pour valider la chaîne.
- Validateur de schéma; a11y (focus/inert/aria/ESC); fallback host testé; TTL.
- Tests unitaires de base; documentation (présent dossier).

## Où coder / Points d’intégration
- Front (packages UI): `public/assets/packages/ui/dialog.js` (engine/headless + orchestrateur + renderers), `public/assets/packages/ui/modal.js` (existant), éventuelles extensions CSS.
- Admin: remplacement d'un `confirm` existant (ex. suppression catégorie) par `confirmDialog`.
- Back: si besoin, exposer un `interaction` de test (200 OK) pour itérer sans impacter des handlers sensibles.

## Mode opératoire (contributeurs)
1) Lire PLAN.md (contrat I/O, a11y, policies) puis PROGRESS.md (checklist actualisée).
2) Implémenter Itération 1 en respectant V4 (UI sans métier; back = interaction/commande).
3) Ajouter/adapter les tests unitaires; documenter les décisions dans PROGRESS.md.
4) Soumettre en PR atomique; vérifier la DoD (a11y/fallback/validator/tests).

## Documents
- PLAN.md — Contexte, objectifs, design, schéma I/O, API, phases, DoD, tests, risques.
- PROGRESS.md — Journal, checklist, avancement (à tenir à jour durant l'implémentation).
