# Phase 0 — Audit du dépôt

Audit mené le 25/10/2026 avant toute modification, conformément au cahier des charges
[self_hosted_analayctics_observability.md](https://github.com/waxland/saclay-research/blob/main/self_hosted_analayctics_observability.md).

## Ce que le dépôt est

| Point                   | Constat                                                                                               |
| ----------------------- | ----------------------------------------------------------------------------------------------------- |
| Gestionnaire de paquets | pnpm 10.30.3 ; `pnpm-workspace.yaml` présent mais **sans clé `packages:`** — ce n'est pas un monorepo |
| Framework               | Next.js 16.4.3, App Router, React 19, Mantine 7, export statique par instance                         |
| Déploiement             | Un dossier de build et un port par instance (`scripts/instance.mjs`) ; artefact `standalone`          |
| Authentification        | **Aucune.** Site public en lecture seule, sans compte ni session utilisateur                          |
| Notion de tenant        | `instance` (saclay, paris1), pas d'organisation ni d'utilisateur                                      |
| CI                      | Un seul workflow, `.github/workflows/ci.yml`                                                          |
| Docker                  | `docker-compose` **v1.29.2** uniquement ; le plugin `docker compose` v2 est absent                    |
| Ressources              | 31 Gio de RAM (26 disponibles), 8 cœurs                                                               |

## Instrumentation déjà en place

- **Matomo auto-hébergé**, `src/features/observability/` : sans cookie, sans User ID, sans détection
  des fonctionnalités du navigateur, URL suivies sans query string. Paramétré pour l'exemption de
  consentement CNIL.
- **Compteurs Prometheus** (`prom-client`) dans `src/server/observability/`, exposés sur `/api/metrics`
  derrière un jeton.
- **Route d'ingestion** `/api/telemetry` : vocabulaire **fermé** (catégorie de lien sortant, issue de
  recherche), corps plafonné à 256 octets, rien n'est journalisé.
- **Nettoyage des termes de recherche** (`src/utils/telemetry.ts`) : e-mails, URL, suites de chiffres
  et ORCID remplacés par `[filtré]`.
- **Pile d'observabilité** `ops/observability/` : Prometheus, Grafana, Blackbox, profil `matomo`.
- **Aucune dépendance OpenTelemetry.**

## Conflits entre le cahier des charges et ce dépôt

Trois points du cahier des charges contredisent des décisions déjà prises ici. Ils sont traités par
configuration plutôt que par renoncement, de sorte que les paquets restent réutilisables ailleurs.

### 1. `identify(userId, traits)` contre l'ADR 006

L'[ADR 006](/decisions/analytics) interdit explicitement toute collecte de donnée
identifiante, et le site n'a de toute façon ni compte ni session. Le cahier des charges demande une
API `identify()` et un catalogue d'événements centré sur des utilisateurs (`user_signed_up`,
`workspace_created`).

**Traitement** : `identify()` existe dans l'interface, pour la portabilité, mais la configuration de
cette instance pose `identity.allowIdentify: false`. Tout appel est alors refusé et compté comme
rejet, sans interrompre l'application. Le catalogue d'événements de ce dépôt est son propre
catalogue, pas celui de l'exemple.

### 2. Trois fournisseurs simultanés contre le double comptage

Le cahier des charges demande Rybbit, Umami et Matomo activables ensemble ; il demande aussi, dans la
même page, de « réutiliser l'instrumentation existante et d'éviter le double comptage ».

**Traitement** : le `MatomoTracker` existant reste l'unique source des vues de page Matomo. L'adaptateur
Matomo du nouveau paquet ne réémet pas de vue de page quand le traqueur historique est actif ; il se
limite aux événements. Tous les fournisseurs sont **désactivés par défaut**.

### 3. OpenObserve contre Prometheus/Grafana déjà déployés

Le cahier des charges demande de ne pas déployer Grafana ni Prometheus par défaut. Ils sont déjà ici,
documentés, avec des tableaux de bord générés (`pnpm ops:k8s`).

**Traitement** : la nouvelle pile vit sous `infra/analytics/`, séparée de `ops/observability/`, qui
n'est pas modifié. OpenObserve s'ajoute, ne remplace pas. La bascule éventuelle est une décision à
prendre plus tard, avec des mesures.

## Choix d'intégration

- **Pas de conversion en monorepo.** Le cahier des charges l'interdit explicitement. Les paquets
  vivent dans `packages/`, autonomes, et sont résolus par un alias `@workspace/*` dans `tsconfig.json`.
  Aucune clé `packages:` n'est ajoutée à `pnpm-workspace.yaml` : copier le dossier `packages/` dans un
  autre projet suffit à le réutiliser.
- **Compose v1.** Les fichiers évitent toute syntaxe propre à Compose v2. La convention `profiles:`
  du dépôt est reprise telle quelle.
- **Rien n'est actif par défaut.** Aucun fournisseur, aucun collecteur, aucun conteneur ne démarre
  sans variable d'environnement explicite.

## Registre de risques

| Risque                                                     | Portée                          | Atténuation                                                                                |
| ---------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------ |
| Double comptage Matomo                                     | Chiffres d'audience faux        | L'adaptateur n'émet pas de vue de page si le traqueur historique est actif                 |
| Fuite de donnée personnelle via les propriétés d'événement | RGPD, validation DPO en attente | Liste blanche de propriétés, rejet à la validation, caviardage avant envoi                 |
| Clés d'ingestion dans le bundle navigateur                 | Sécurité                        | Seules les variables `NEXT_PUBLIC_*` sont exposées ; les jetons d'écriture restent serveur |
| Trois bases de données supplémentaires                     | Exploitation                    | Profils Compose indépendants ; mesure de l'empreinte réelle documentée                     |
| Compose v1 sans `docker compose` v2                        | Reproductibilité                | Validation `config` en CI avec la version installée                                        |

## Hypothèses

1. Le POC vise la réutilisation sur un autre projet ; ce dépôt sert de banc d'essai, pas de cible de
   production pour les trois fournisseurs à la fois.
2. Aucune donnée réelle d'audience n'est produite : le POC émet des événements de test.
3. La validation DPO reste requise avant toute activation en production, quelle que soit la qualité
   technique du POC. L'auto-hébergement ne vaut pas conformité.
