### **1. Architecture Générale et Structure du Dépôt**

#### **1.1. Vue d'ensemble**

Le système comporte quatre briques déployables et deux paquets partagés. Sa colonne vertébrale est le contrat JSON de parcours (chapitre 2) : l'extension le produit, le backend le stocke et le distribue, le SDK l'exécute. Aucune brique ne connaît les autres, toutes connaissent le contrat.

```mermaid
flowchart TB
    subgraph edition [Poste de l administrateur]
        Ext[Extension d edition]
        Dash[Dashboard]
    end
    subgraph circuy [Infrastructure Circuy]
        API[Backend Hono]
        DB[(PostgreSQL)]
    end
    subgraph client [Site du client]
        Host[Page hote]
        SDK[SDK Circuy]
    end

    Ext -->|POST authentifie| API
    Dash -->|POST authentifie| API
    API --> DB
    SDK -->|GET avec cle publique| API
    SDK -->|Beacon| API
    Host -.->|charge| SDK
```

**Frontières de confiance.** Quatre franchissements exigent une validation explicite, détaillée au chapitre 8 :

1. **Page hôte vers SDK.** Le SDK s'exécute dans un contexte JavaScript qu'il ne contrôle pas et dont le CSS lui est hostile. Il n'accorde aucune confiance au DOM environnant et ne suppose jamais qu'un élément ciblé existe.
2. **SDK vers page hôte.** Symétriquement, le SDK ne doit jamais casser le site du client. Toute défaillance interne dégrade en silence : l'absence de guidage est acceptable, une page cassée ne l'est pas.
3. **SDK vers backend.** Ces requêtes portent une clé publique, lisible par quiconque inspecte la page. Tout ce qui en provient est traité comme non fiable, en particulier les événements de télémétrie.
4. **Extension vers backend.** Ces requêtes sont authentifiées, mais leur charge utile contient du contenu rédigé par un administrateur qui finira injecté dans le navigateur d'utilisateurs finaux. Ce contenu est assaini à la publication et au rendu.

#### **1.2. Structure du monorepo**

```
circuy/
├── apps/
│   ├── api/            Backend Hono, accès aux données Drizzle, service du dashboard
│   ├── dashboard/       Application monopage Vite + React + Tailwind
│   └── extension/       Extension WXT + React + Tailwind
├── packages/
│   ├── contracts/       Schémas de validation et types, source unique de vérité
│   └── sdk/             Moteur d'exécution et de rendu embarqué chez les clients
└── specifications/      Cahiers des charges fonctionnel et technique
```

**Règles de dépendance, vérifiées mécaniquement en intégration continue :**

| Paquet | Peut dépendre de |
| --- | --- |
| `contracts` | rien d'interne |
| `sdk` | `contracts`, en types uniquement |
| `api` | `contracts` |
| `dashboard` | `contracts` |
| `extension` | `contracts`, `sdk` |

Aucune application ne dépend d'une autre application. Une dépendance croisée entre `api`, `dashboard` et `extension` signalerait qu'un morceau de logique appartient en réalité à `contracts` ou à `sdk`.

`sdk` est le seul paquet dont le poids est surveillé : il est chargé sur les sites des clients. `extension` en dépend pour garantir que la prévisualisation utilise exactement le moteur de production (section 4.5).

#### **1.3. Le paquet partagé `contracts`**

Ce paquet contient les schémas de validation du contrat de parcours, des requêtes d'API et des événements de télémétrie, écrits une fois et dérivés en types TypeScript.

**Contrainte structurante :** le SDK importe de `contracts` **uniquement des types**, jamais un validateur. Les types disparaissent à la compilation, une bibliothèque de validation non. Embarquer un validateur dans le SDK ajouterait plusieurs kilooctets chez chaque visiteur de chaque site client pour revalider des données que le backend a déjà validées à la publication.

```typescript
// Dans packages/sdk : autorisé, aucun coût à l'exécution
import type { Tour, Step } from '@circuy/contracts';

// Dans packages/sdk : interdit, embarquerait le validateur dans le bundle client
import { tourSchema } from '@circuy/contracts';
```

Cette règle est vérifiée par une règle de lint, et non laissée à la vigilance : c'est le genre d'import qu'une complétion automatique ajoute sans qu'on le remarque.

La validation s'exerce donc là où elle a un sens : dans l'extension avant l'envoi, et dans le backend avant l'écriture. Le SDK, lui, consomme un document déjà validé et se contente de dégrader proprement s'il rencontre une forme qu'il ne comprend pas, ce qui arrive légitimement lorsqu'un SDK ancien rencontre un parcours récent (section 7.1).

#### **1.4. Outillage**

| Besoin | Outil | Remarque |
| --- | --- | --- |
| Exécution serveur | Node.js 22 LTS | Version épinglée par le champ `engines` et un fichier `.nvmrc` |
| Gestionnaire de paquets | pnpm workspaces | Fichier de verrouillage engagé, installation reproductible |
| Langage | TypeScript en mode strict | `strict` activé partout, sans exception locale |
| Compilation du SDK | tsup | Sortie unique, minifiée, en modules ES et UMD |
| Compilation du dashboard | Vite | Sortie statique servie par le backend |
| Compilation de l'extension | WXT | Manifest V3, cible Chrome en V1 |
| Formatage et lint | Biome | Un seul binaire et une configuration par défaut, au lieu d'un formateur et d'un linter distincts |
| Tests unitaires | Vitest | Chapitre 9 |
| Tests de bout en bout | Playwright | Chapitre 9 |

Aucune configuration n'est personnalisée sans nécessité démontrée. Les réglages par défaut de ces outils font autorité ; toute dérogation est commentée à l'endroit où elle est introduite.
