# Notes — Journal des décisions (ADR)

> Chaque décision structurante = une entrée. Format léger : Contexte · Décision · Conséquences. Ne jamais réécrire une décision passée ; en ajouter une nouvelle qui la remplace (statut *remplacé par*).

---

## ADR-001 — Modèle multi-tenant : base centrale autoritaire + projection POS
- **Statut** : accepté (2026-07)
- **Contexte** : besoin d'une source de vérité unique pour la gestion/analytics, tout en alimentant des sites e-commerce par client.
- **Décision** : la base centrale contient **toutes** les données (dont POS) ; chaque base client reçoit une **projection en lecture** des données POS.
- **Conséquences** : synchronisation central→client à concevoir (recommandé : événements Messenger) ; base client jamais autoritaire ; isolation e-commerce forte. Voir `portail-manager/docs/ARCHITECTURE_MULTITENANT.md`.

## ADR-002 — RBAC : rôles/permissions par boutique, rétro-compatible
- **Statut** : accepté (2026-07)
- **Contexte** : passer de 3 rôles fixes à des permissions granulaires, sans casser l'existant ni l'auth JWT.
- **Décision** : entités `Role`/`Permission`, portées par `UserCompany.boutiqueRole` ; `PermissionResolver` central ; `User::getRoles()` inchangé (rôles globaux) en phase 1. Bascule vers l'autorité par boutique = phase 2 délibérée.
- **Conséquences** : les modules doivent utiliser les codes de permission (`pos.sell`…).

## ADR-003 — Chiffrement des secrets au repos
- **Statut** : accepté (2026-07)
- **Contexte** : le projet stockait les credentials en clair.
- **Décision** : `EncryptionService` (libsodium) ; tout secret (mot de passe DB client, futures clés de paiement) est chiffré.
- **Conséquences** : clé `APP_ENCRYPTION_KEY` par environnement (hors dépôt) ; prévoir rotation (phase ultérieure).

## ADR-004 — Montants en centimes XOF (entiers)
- **Statut** : accepté (2026-07)
- **Contexte** : éviter les erreurs d'arrondi monétaires.
- **Décision** : stocker et calculer les montants en **entiers (centimes)**, devise `XOF`.
- **Conséquences** : conversions à l'affichage ; helpers de formatage.

## ADR-005 — Vente anonyme par défaut
- **Statut** : accepté (2026-07)
- **Contexte** : la majorité des ventes POS se font sans client identifié.
- **Décision** : `Sale.customer` est **nullable** ; le parcours d'encaissement n'exige pas de client.
- **Conséquences** : rapports et fidélité gèrent l'absence de client ; le client est un enrichissement optionnel.

## ADR-006 — Ventes/écritures append-only (pas de soft-delete)
- **Statut** : accepté (2026-07)
- **Contexte** : intégrité comptable et auditabilité.
- **Décision** : les ventes/paiements/mouvements ne sont **jamais supprimés** ; une annulation crée un avoir/mouvement inverse.
- **Conséquences** : pas de trait soft-delete sur ces entités ; statut + écritures compensatoires.

---

## ADR-007 — Canaux e-commerce : base projetée OU WooCommerce connecté
- **Statut** : accepté (2026-07)
- **Contexte** : certains clients n'ont pas de site (→ base Symfony projetée), d'autres ont **déjà** un WordPress/WooCommerce et veulent gérer leurs produits + le POS dans un seul système.
- **Décision** : offrir **deux canaux** e-commerce, choisis par boutique — (a) [projection](../modules/ecommerce-projection.md) vers une base client (site Symfony), (b) [connecteur WooCommerce](../modules/woocommerce-connector.md) (push produits/prix/stock via l'API REST WooCommerce + pull des commandes). Même philosophie (central autoritaire, upsert idempotent, événements Messenger), cibles différentes.
- **Conséquences** : le central reste la source de vérité ; les secrets WooCommerce (clés API, secret de webhook) sont chiffrés (`EncryptionService`) ; patron réutilisable pour d'autres connecteurs (Shopify, PrestaShop). Une boutique choisit son/ses canal(aux).

## ADR-008 — Connecteur WooCommerce en mode *pull* + licences (révise ADR-007)
- **Statut** : accepté (2026-07-26)
- **Contexte** : mise en œuvre du canal WooCommerce (E1). Deux besoins nouveaux : un **plugin** installé par la boutique sur son site, et une **licence** pilotée par l'admin conditionnant l'accès au connecteur.
- **Décision** : (1) **inverser le sens d'appel** — le **plugin WordPress tire** le catalogue depuis l'API yima avec sa **clé de licence** et **pousse les commandes** vers yima (au lieu de yima appelant l'API REST WooCommerce). yima **ne stocke pas** les clés API WooCommerce du site. (2) Introduire une **licence par boutique** (control plane admin, E1‑A) : clé (hash + chiffrée), statut, expiration, site lié ; l'API connecteur (E1‑B) valide la licence + une **signature HMAC**. (3) Le **compte client = la boutique**, provisionnée par l'admin ; les comptes acheteurs restent WooCommerce.
- **Conséquences** : philosophie inchangée (central autoritaire, upsert idempotent par SKU, commandes → `Sale channel=online`) ; la licence gate le **canal e-commerce**, pas le POS ; endpoint public signé (`^/api/connector`, hors JWT) ; secrets (clé de licence, secret HMAC) chiffrés via `EncryptionService`. La fiche [connecteur WooCommerce](../modules/woocommerce-connector.md) est à lire avec cette révision.

## ADR-009 — Design des sites clients par plugin de kits Elementor (pas de thème sur mesure)
- **Statut** : accepté (2026-07-26)
- **Contexte** : l'apparence des sites clients est conçue à la main site par site — poste le plus coûteux et le moins reproductible de l'offre, alors que la donnée est industrialisée depuis E1. Il fallait trancher entre un **thème WordPress maison** et un **plugin d'habillage**.
- **Décision** : (1) un **second plugin**, `yima-wc-design/`, frère du connecteur et **indépendant** de lui — le connecteur pilote la donnée, celui-ci le design ; le client reste libre de son thème. (2) Cible **Elementor gratuit** : pas de Theme Builder, donc l'en-tête et le pied sont rendus par le plugin depuis des **modèles Elementor** (`elementor_library`), et l'en-tête/pied du thème actif est neutralisé par un adaptateur (Hello Elementor, Astra, OceanWP, GeneratePress) avec repli par masquage CSS. (3) Les **jetons de design** sont la source de vérité du style : publiés en variables CSS **et** recopiés dans les couleurs/polices globales d'Elementor, que les gabarits des kits référencent — jamais de couleur en dur. (4) Les kits sont des **gabarits Elementor importables** (JSON embarqués dans le plugin), importés de façon **idempotente**.
- **Conséquences** : re-skinner un site = changer la palette, sans rouvrir Elementor ni retoucher un kit ; ajouter un secteur ne coûte que du design, plus du code. Le plugin est **autonome par nécessité** — le backend yima ne stocke aucune donnée de branding (`StoreSetting` ne porte que WhatsApp, `Company.logo` est derrière un `MediaController` authentifié) ; le pont vers le connecteur se limite au numéro WhatsApp. Piloter le design depuis la PWA supposera d'étendre `StoreSetting` et `GET /api/connector/config` (voir [fiche Design & templates §11](../modules/design-templates.md)). Contrairement au connecteur, ce plugin charge des assets (`assets/`), versionnés par `YIMA_DESIGN_VERSION`. Écart assumé : dépendance à Elementor, qui devient un prérequis de l'offre design.

## Décisions ouvertes (à trancher)

- **ADR-OPEN-A** — Versionnement API : introduire `/api/v1` pour le métier (recommandé) — à acter au démarrage de la phase 5.
- **ADR-OPEN-B** — Périmètre exact de la projection POS (tables/colonnes exposées au site e-commerce) — phase 4.
- **ADR-OPEN-C** — Mécanisme de synchro : Messenger événementiel (recommandé) vs ETL planifié — phase 4.
- **ADR-OPEN-D** — Bases clients : même serveur vs instances dédiées ; utilisateur DB dédié par client (moindre privilège).
- **ADR-OPEN-E** — Multi-dépôt (warehouses) dès la v1 ou plus tard.
