# Chantier « fondations produit » — relecture, équipes, XLIFF (2026-08-29)

> Décision de la session : **aucune intégration DeepL**. Tout ce qui suit est
> 100 % moteur maison/LLM existants.

## 1. Fondation : persistance des segments par job

- **Modèle `TranslationSegment`** (`database/models.py`) : paires (source,
  traduction) par job et par utilisateur, avec statut de relecture
  (`pending | approved | edited`), texte relu, index, horodatages.
- **Migration `f7e8d9c0b1a2`** (alembic) : `translation_segments`,
  `workspaces`, `workspace_members`, `glossaries.workspace_id`. Appliquée et
  vérifiée sur base vierge (chaîne complète 001→tête) et sur la base de dev.
- **Capture** (`translators/segments.py`) : un `SegmentRecorder` est injecté
  par la route dans les 4 traducteurs (docx/xlsx/pptx/pdf). Il enregistre
  chaque paire unique dans l'ordre du document ; les paires identiques
  (non traduites) sont ignorées pour garder la liste actionnable.
- **Overrides** : `set_segment_overrides()` applique les traductions
  **relues par l'humain** mot pour mot lors de la reconstruction — priorité
  maximale (avant TM et provider), zéro appel API, zéro dérive.
- **Persistance** : après un job réussi, la route stocke les segments en
  base (best-effort, n'échoue jamais le job).

## 2. API de relecture (`routes/review_routes.py`)

| Endpoint | Rôle |
|---|---|
| `GET /api/v1/translations/{job_id}/segments` | Liste des segments + compteurs (accès propriétaire ou token du job) |
| `PATCH /api/v1/segments/{id}` | Éditer (`reviewed_text` + `status=edited`) ou approuver — alimente aussi la TM par utilisateur (les traductions relues sont réutilisées dans les jobs suivants) |
| `POST /api/v1/translations/{job_id}/rebuild` | Reconstruit le document avec les segments approuvés/modifiés (le texte relu est appliqué tel quel) puis pointe le téléchargement dessus |
| `GET /api/v1/translations/{job_id}/xliff` | Export **XLIFF 1.2** (les segments modifiés exportent leur texte relu) |
| `POST /api/v1/translations/{job_id}/xliff` | Import XLIFF : met à jour les segments (cible ≠ machine → `edited`, sinon `approved`) |

Note UX : la reconstruction nécessite le fichier source encore présent
(rétention 30 min). Au-delà, le messageInvite à re-téléverser — et les
segments approuvés étant dans la TM, la nouvelle traduction les réutilise
automatiquement.

## 3. Éditeur de relecture (frontend)

- **`/dashboard/reviews/[jobId]`** — tableau côte à côte Source |
  Traduction, édition inline, badges de statut, approbation unitaire ou
  « Tout approuver », **Reconstruire et télécharger** (blob authentifié),
  export/import XLIFF. Libellés 13 locales.
- **Lien « Relire et corriger la traduction »** sur l'écran de fin de
  traduction (`TranslationComplete`).

## 4. Espaces de travail équipes (`routes/workspace_routes.py`)

- Modèles `Workspace` / `WorkspaceMember` (rôles `owner | admin | member`).
- Endpoints : création (plan **Business** requis), liste (avec rôle,
  sièges utilisés/limite), ajout de membre **par e-mail** avec
  **application de la limite de sièges** du plan du propriétaire
  (Business = 5, Enterprise illimité), retrait (owner impossible à retirer).
- **Glossaires partagés** : `glossaries.workspace_id` — le contrôle d'accès
  (`get_glossary_terms`, `validate_glossary_access`) accepte désormais le
  propriétaire **et les membres du workspace**.
- **Page `/dashboard/teams`** : création d'espace, liste des membres,
  invitation (e-mail + rôle), retrait, compteur de sièges, gate Business.
- Facturation multi-sièges : v1 = application de la limite de sièges du
  plan. (La facturation au siège réel côté Stripe — subscription items —
  reste un chantier facturation à part.)

## 5. Tests & vérifications

- Nouveaux tests (`tests/test_review_foundation.py`, 11) : recorder,
  overrides, **capture→rebuild de bout en bout sur un vrai docx** (le texte
  relu atterrit dans le fichier reconstruit, le reste reste machine),
  structure XLIFF + échappement XML, sièges, CRUD workspace, glossaire
  partagé (membre OK / extérieur refusé).
- Suite backend complète : voir résultat final ci-dessous.
- `tsc --noEmit` OK sur les deux frontends ; navigation « Équipe » (Pro+)
  et lien « Relire » ajoutés.

## 6. Non livré (justifié)

- **IDML / DITA** : spécifications de formats complètes à part entière
  (structure InDesign / arbres DITA) — nouveaux parseurs dédiés, à
  chiffrer séparément.
- **Facturation Stripe au siège** (mètre temps réel des sièges) : la
  limite plan est appliquée ; le mètre Stripe nécessite des subscription
  items et un webhooks sièges.
- **Éditeur de relecture temps réel multi-utilisateur** (verrouillage de
  segment, présence) : nécessite WebSocket + verrous — v1 = relecture
  solo/équipe asynchrone.
