# Installation sur PlanetHoster — PHP 8.3

Copyright 2026 Vincent Gallet - DOOZEN consulting

## 1. Préparer l'hébergement
Créer le sous-domaine licences.doozen.fr dans le panneau PlanetHoster, activer son certificat HTTPS et choisir PHP 8.3. Vérifier PDO MySQL et sodium. Les identifiants MySQL restent exclusivement sur l'hébergement.

Arborescence cible (adapter le chemin du compte) :
```
/home/VOTRE_COMPTE/doozen-licences/
  private/config.php
  private/bootstrap.php
  cli/manage.php
  public/api/v1/index.php
  public/api/v1/.htaccess
```
Définir la racine web du sous-domaine sur le dossier **public**, jamais sur doozen-licences. Si le panneau impose une autre racine, déplacer uniquement le contenu de public dans cette racine et adapter le chemin require de index.php vers private/bootstrap.php. Ne pas publier l'archive entière dans la racine web.

Les routes utilisent Apache/mod_rewrite et .htaccess. Si la réécriture est indisponible, faire configurer le routage vers index.php par l'hébergeur ; les routes demandées doivent être /api/v1/activate, /check et /deactivate.

## 2. Préparer MySQL
Créer de préférence une base dédiée. Importer schema.sql via phpMyAdmin. Les tables ont le préfixe dz_ ; aucune table existante n'est supprimée.
Créer un utilisateur MySQL limité à SELECT, INSERT, UPDATE et DELETE sur cette base. Ne pas lui accorder de droits sur les autres bases. Le même utilisateur est utilisé ici par la CLI privée.

Copier private/config.example.php en private/config.php puis renseigner nom de base, utilisateur et mot de passe. Le serveur MySQL est localhost, à confirmer dans ton panneau. Protéger config.php en lecture pour le seul compte d'hébergement (permissions 600 lorsque le mode d'exécution PHP le permet).

## 3. Générer la signature
Depuis le terminal/SSH de l'hébergement, dans doozen-licences :
```bash
php cli/manage.php keygen
```
Copier signing_secret dans private/config.php. Copier public_key dans chaque application cliente. Conserver la clé privée dans une sauvegarde protégée, jamais dans Git ; ne pas la transmettre au client. La commande imprime volontairement ces clés une seule fois : éviter une session enregistrée ou un journal partagé.

## 4. Créer et gérer une licence
```bash
php cli/manage.php create openbee-import "Société Exemple" 2027-12-31 2
php cli/manage.php status 1 suspended
php cli/manage.php status 1 active
php cli/manage.php status 1 revoked
```
La création affiche l'identifiant et la clé à remettre au client. Seule son empreinte SHA-256 est conservée. L'expiration correspond à 23:59:59 UTC de la date indiquée. La suspension bloque les prochains contrôles. Une licence revoked peut être réactivée volontairement par l'administrateur avec status active.

Créer une tâche cron nocturne exécutant :
```bash
php /home/VOTRE_COMPTE/doozen-licences/cli/manage.php cleanup
```
Elle nettoie la table de limitation des requêtes. Limite initiale : 60 appels/minute par IP, partagée entre les installations d'un même réseau. À ajuster selon la charge réelle. Le nettoyage réinitialise la fenêtre en cours ; l'exécuter à faible trafic. Compléter si nécessaire par une limite globale côté hébergement/WAF.

## 5. Intégrer dans Python
Installer clients/requirements.txt. Embarquer licence_client.py et la clé publique dans l'application. Créer un UUID une seule fois avec uuid.uuid4(), puis le conserver dans la configuration de cette installation. L'UUID est une liaison logique, pas un verrou matériel.

```python
from licence_client import ClientLicence

client = ClientLicence('openbee-import', UUID_CONSERVE, CLE_PUBLIQUE)
activation = client.activate(CLE_LICENCE_SAISIE)
jeton = activation['activation_token']
# Enregistrer le jeton via keyring dans le coffre système.
autorisation = client.check(jeton)
# Commencer le traitement uniquement après un contrôle réussi.
```
Les variables en majuscules sont à fournir par l'application. Lire config.example.ini avec configparser si souhaité ; le client fixe volontairement l'adresse HTTPS dans son code. Garder la clé publique dans le code distribué plutôt que dans un fichier modifiable par l'utilisateur.

Appeler activate seulement à la première configuration ou pour une réactivation volontaire. Une réactivation avec la même clé/UUID renouvelle le jeton et invalide l'ancien. En cas de perte de la réponse d'activation, répéter l'activation permet de récupérer un nouveau jeton sans consommer une place supplémentaire.

Appeler check au démarrage puis périodiquement (par exemple toutes les 24 h pour un daemon). Arrêter les nouveaux traitements sur LicenceRefusee ou LicenceIndisponible ; terminer proprement ceux déjà engagés. Le client livré fonctionne **en ligne**, sans cache hors connexion. L'autorisation signée de 72 h constitue une base pour un futur cache, mais n'active pas cette fonction. Un contrôle au démarrage est obligatoire même si l'application a précédemment fonctionné.

Le contrôle PHP des autres outils doit appeler ces mêmes routes depuis leur serveur via HTTPS et conserver le jeton hors racine web. Ne pas vérifier un simple champ JSON valid sans valider la signature et sa liaison à l'application.

## 6. Limites et recette
Cette version n'inclut ni tableau de bord web ni historique métier des contrôles. Gérer les licences par CLI et consulter les tables via phpMyAdmin réservé à l'administrateur. Sauvegarder base et configuration privée. Les installations actives restent comptées jusqu'à désactivation ; une suspension ne libère pas les places.

Configurer l'horloge des machines ; le client accepte un écart de cinq minutes. Ne pas copier UUID et jeton sur plusieurs postes. Un programme local modifié peut contourner les contrôles ; les opérations exécutées sur ton serveur doivent avoir leurs propres vérifications.

Exécuter tests/RECETTE.md avant mise en production. Ce paquet n'a pas été déployé sur licences.doozen.fr. Aucun identifiant réel n'a été inclus.

Référence de signature : https://www.php.net/manual/en/function.sodium-crypto-sign-detached.php
