# pilotage.ecovivo.fr : le dossier applicatif

Centre de pilotage interne d'EcoVivo. Seconde application PHP/MySQL sur
mutualisé OVH, sur le modèle de l'espace client (`../../Espace-client/site`),
mêmes contraintes : pas de framework, pas de chaîne de build, pas de cron,
dépendances externes au strict minimum, tout le calcul côté serveur.

**Les lots L0, L1 et L2 sont écrits.** Le socle, la trésorerie avec son moteur
de projection, le CRM, la grille de mission et le générateur de PTF. Notes de
cadrage : `../03-note-socle-L0.md`, `../04-note-tresorerie-L1.md`,
`../05-note-crm-ptf-L2.md`.

## Mise en service, dans cet ordre

1. **La racine web** du sous-domaine `pilotage.ecovivo.fr` pointée sur
   `site/public`.
2. **La base.** Importer `migrations/000-schema-complet.sql`, puis
   `migrations/004-grille-mission.sql`. Remplacer l'adresse du compte de départ
   dans le premier fichier **avant** de l'importer : sans acteur, personne ne
   peut entrer.
3. **La configuration.** Copier `app/config-exemple.php` en `app/config.php` et
   renseigner `db_mdp`. Le reste fonctionne avec ses valeurs de départ.
4. **Vérifier** sur `https://pilotage.ecovivo.fr/pilotage/sante` : les deux
   bases, la version de PHP, l'état des deux ponts, l'expiration du secret Azure.
5. **Se connecter** sur `/connexion`. Le premier lien conduit à l'enrôlement du
   second facteur : la clé s'affiche une fois, à recopier dans une application
   d'authentification.

## Contenu

```
site/
  public/                 racine web à exposer (docroot)
    index.php             front controller : configuration, session, table de routage
    .htaccess             HTTPS forcé, réécriture vers index.php, X-Robots-Tag noindex
    .user.ini             réglages PHP (envois modestes : justificatifs, exports)
    robots.txt            Disallow: /
    assets/
      css/design-system.css   tokens de la charte, identiques à l'espace client (+ --beige-sable-light)
      css/style.css           composants de l'espace client, plus ceux du pilotage en fin de fichier
      css/polices.css         @font-face servis depuis le domaine (RGPD)
      fonts/                  10 .woff2 (Lora, Raleway, Quicksand)
      js/ecovivo-grille.js    grille de mission RÉELLE, reprise verbatim, à ne pas modifier
      logo.png, favicon.ico
  app/
    config-exemple.php    modèle de config : bases, ponts, Graph, session 7j + 2FA, paramètres
    db.php                bdd() pilotage, bdd_client() lecture seule, pont_client_lire()
    routeur.php           routage, rendu, échappement, barre latérale à cinq familles
    services/
      journal.php         actions sensibles, en ajout seul
      securite.php        jeton anti-rejeu des formulaires, messages d'un écran à l'autre
      session.php         session de 7 jours, glissante
      totp.php            le second facteur à six chiffres, sans dépendance
      auth.php            lien nominatif, puis code ; gardes d'accès par module
      modules.php         les quinze modules, leur famille, leur route, qui les voit
      parametre.php       valeurs éditables et leur caractère provisoire
      format.php          montants, dates, barres, tiret doré, étiquettes
      menage.php          durées de conservation, appliquées au fil des requêtes
      graph-mailer.php    envoi par Microsoft Graph, repris de l'espace client
      projection.php      LE MOTEUR : 12 mois, 3 trajectoires, point bas, courbe SVG
      grille.php          la grille de mission, l'échéancier, la charge en heures
      pont-client.php     lecture, et bascule d'une PTF signée vers un chantier
      notion.php          reprise unique du CRM, puis Notion s'archive
    modeles/              acteur, scenario, charge, facture, affaire, contact, ptf
    controleurs/          connexion, accueil, tresorerie, charges, budget, facturation,
                          scenarios, commercial, relationnel, projets, ptf, reglages
    vues/                 gabarit, connexion, erreur, et pilotage/ pour les écrans
    .htaccess             Require all denied
  migrations/
    000-schema-complet.sql   LE FICHIER À IMPORTER : 38 tables, paramètres, scénarios
    001-socle.sql            \
    002-tresorerie.sql        > produits depuis 000 par outils/generer-migrations.pl
    003-crm-ptf.sql          /  (rattrapage d'une base créée à un lot précédent)
    004-grille-mission.sql   la grille, produite par outils/semer-grille.pl
  outils/
    verifier-tout.ps1     enchaîne tous les contrôles, trouve perl tout seul
    verifier-php.pl       lexeur PHP (le poste n'a pas de php -l)
    verifier-js.pl        équilibre des délimiteurs JavaScript
    verifier-schema.pl    liste de purge complète, enfants avant parentes
    generer-migrations.pl découpe 000 en migrations numérotées
    semer-grille.pl       lit ecovivo-grille.js, écrit 004 ; refuse si le total sort de 100 %
    servir.pl             petit serveur HTTP statique, pour voir le rendu réel
    polices-locales.pl    régénère polices.css et les .woff2
  stockage/               hors racine web : justificatifs, PTF et décomptes PDF
```

## Avant tout envoi FTP

```powershell
powershell -ExecutionPolicy Bypass -File outils\verifier-tout.ps1 -NoPause
```

Il doit finir **vert**. Il enchaîne : syntaxe PHP de tous les fichiers, cohérence
du schéma complet, total de la grille de mission, et rattachement de chaque table
à un lot.

## Voir le rendu réel

Le volet d'aperçu du navigateur bloque les feuilles de style et les polices en
`file://`. Pour juger la charte :

```powershell
perl outils\servir.pl
```

puis `http://localhost:8787`. Ce serveur sert des fichiers, il n'exécute aucun
PHP : ce qu'on regarde est la charte, pas l'application.

## Séquence de construction

| Lot | Objet | État |
|---|---|---|
| **D0** | Design : maquettes et second handoff du 8 septembre | fait |
| **L0** | Socle : routeur, deux bases, gabarit, barre latérale, second facteur, modules par acteur, page de santé | **fait** |
| **L1** | Trésorerie : dépenses, charges, échéances, scénarios, moteur de projection | **fait** |
| **L2** | CRM, grille de mission, PTF, bascule vers l'espace client | **fait**, bascule préparée jusqu'à l'appel |
| **L3** | Microsoft 365 : historique unifié, rattachement d'un mail, SharePoint, alerte sur le secret | à écrire |
| **L4** | Chiffrage : économie de la construction, cascade ×1,346 | tables posées |
| **L5** | Tableau de bord : tuiles au choix | tableau de bord fixe en place |
| **L6** | Projection : rémunération, recrutement, statut, ressources humaines | tables posées, moteur commun prêt |

## Ce qui est repris de l'espace client, et pourquoi

- **La charte** (`design-system.css` pour les tokens, `style.css` pour les
  composants) : décision du dirigeant (`../02-reponses-dirigeant.md`, point 4).
  Toute correction se reporte dans les deux dossiers. Les composants propres au
  pilotage sont **ajoutés en fin de `style.css`**, sans modifier une seule règle
  reprise : les deux fichiers restent comparables ligne à ligne.
- **Les polices auto-hébergées** : charger Lora, Raleway et Quicksand depuis
  `fonts.googleapis.com` transmettrait l'IP de chaque visiteur à Google LLC.
- **Les services** : `graph-mailer.php` et `securite.php` repris tels quels ;
  `session.php`, `auth.php`, `journal.php` et `menage.php` adaptés (session de
  7 jours, second facteur, pas de `projet_id`).
- **Le filet perl** : le poste n'a ni `php` ni `python` en ligne de commande.

## Ce qui NE doit pas être porté

- Le prototype `../handoff-design/Pilotage EcoVivo.dc.html` : référence de
  design, pas du code de production. Il embarque un runtime de rendu.
  **Les formules**, elles, sont reprises fidèlement.
- La grille à 7 postes d'une première ébauche : fausse. La bonne grille est
  `assets/js/ecovivo-grille.js` (12 + 12 + 11 éléments).
