# CLAUDE.md — Projet Paillasse > Lis ce fichier en entier avant toute action. Il fait foi sur le contexte, les priorités, l'architecture, la sécurité et le style. > Nom de travail : **Paillasse**. Porteur : Adam Belkacemi (Esquisse Formation). --- ## 1. Contexte et objectifs **Paillasse** : une plateforme de labs Linux et réseau pour l'enseignement (lycée NSI, BTS SIO SISR, BTS CIEL, BUT R&T, titres pro TSSR). Chaque élève obtient une vraie VM Debian dans le navigateur, en moins de 5 secondes, sur un cloud **OpenStack** hébergé en Europe (Hetzner). Correction automatique par scripts. **Aucune IA dans le produit.** Trois objectifs, dans cet ordre : 1. **Candidature Senior SRE / Cloud Engineer chez Infomaniak.** Pouvoir dire : « J'opère un cloud OpenStack en production pour des classes : voici mes métriques, ma dernière montée de version, mon dernier incident. » 2. **Candidature Backend Software Engineer (kDrive) chez Infomaniak**, en repli ou en parallèle. Pouvoir dire : « J'ai conçu une API Laravel documentée, performante (MariaDB, Redis), testée, avec stockage S3/Ceph. » 3. **Un produit professionnel** pour les établissements et organismes de formation. Le choix de la pile (section 3) suit **la stack d'Infomaniak** : MariaDB, Laravel, Go, Redis, Grafana, ElasticSearch, S3/Ceph, WebDAV, Kubernetes. Chaque techno doit répondre à **un vrai besoin** de Paillasse, jamais être ajoutée « pour le CV ». Cahier des charges complet : `docs/cahier-des-charges.md` (à exporter depuis l'artifact « Paillasse »). ### Règle d'or pour Claude Adam doit **comprendre et pouvoir expliquer** tout ce qui est construit (il en parlera en entretien technique). Pour chaque étape : - explique ce que tu vas faire et pourquoi, **avant** de le faire ; - après, résume ce qui a changé et comment le vérifier ; - propose à Adam de refaire lui-même les manipulations et le code clés ; - ajoute une entrée dans `docs/journal.md` (date, ce qui a été fait, ce qui a cassé, ce qu'on a appris). --- ## 2. Priorités Ne commence pas un bloc avant que le précédent soit terminé, sauf demande explicite d'Adam. ### Bloc A — Infra (poste SRE), semaines 1 à 8 | Semaine | Livrable | Critère de fin | |---|---|---| | 1 | Serveur dédié installé (Debian 13, RAID 1), durci, sauvegardé | SSH par clé seulement, pare-feu actif, `docs/runbooks/serveur.md` | | 2 | OpenStack tout-en-un (Kolla-Ansible) fonctionnel | Une VM Debian créée, joignable en console série | | 3 | Supervision hors du serveur (CX23) : Prometheus, **Grafana**, Uptime Kuma, alertes | Une alerte reçue lors d'une panne provoquée | | 4 | Portail minimal **Laravel** : comptes, une classe, lancement d'un lab, console web (xterm.js) | Un élève test fait le lab « Premiers pas dans le shell » | | 5 | Stock chaud de VM (files **Redis**) + correction automatique (agent invité QEMU) | Terminal ouvert en < 5 s (p95), vérification OK | | 6 | Self-healing : VM figée relancée, stock reconstitué, service redémarré | Panne provoquée → réparée sans intervention, post-mortem écrit | | 7 | Montée de version d'OpenStack documentée | Runbook + retour d'expérience | | 8 | Pilote avec une vraie classe | Métriques réelles, retours des élèves et du prof | ### Bloc B — Backend (poste kDrive) 1. API publique Laravel versionnée (`/api/v1`), documentée en OpenAPI, tests Pest, jetons Sanctum, quotas et limites de débit dans Redis. 2. Cache Redis sur les lectures lourdes (catalogue, tableau de bord prof) ; mesure avant/après dans Grafana. 3. Optimisation MariaDB : index, `EXPLAIN`, requêtes N+1 supprimées, jeu de données de charge (ex. 500 classes, 20 000 élèves). 4. Stockage des travaux d'élèves et des rendus sur **S3** (Hetzner Object Storage), avec versioning. ### Bloc C — Plus tard - **Ceph** comme stockage d'OpenStack (Glance, Cinder) : démo mono-serveur d'abord, vrai cluster au 2ᵉ serveur. - **WebDAV** : dossier de l'élève montable comme lecteur réseau. - **ElasticSearch** : recherche plein texte dans les cours et labs (seulement si le besoin est réel). - 2ᵉ serveur, passage à **OCI** (Debian + Puppet), haute disponibilité (Galera, Ceph), **Kubernetes** pour le portail. - MCP pour développeurs (voir section 6). --- ## 3. Architecture ``` Navigateurs (élèves, profs) Développeurs (API, MCP) │ HTTPS 443 uniquement (réseaux scolaires filtrés) ▼ Hetzner Cloud CX23 ── Caddy (TLS) ── Front (Inertia + React) ── Laravel (API + portail) │ MariaDB · Redis (cache, files, sessions, quotas) │ Workers Laravel Horizon : stock chaud, ordonnanceur │ Proxy console WebSocket (Go) │ Prometheus · Grafana · Uptime Kuma (page de statut) │ API OpenStack (TLS, IP du CX23 autorisée seulement) ▼ Serveur dédié Server Auction : i7-6700, 64 Go, 2 × 500 Go SSD RAID 1, Debian 13 OpenStack Kolla-Ansible tout-en-un : Keystone, Nova, Neutron (OVN), Glance, Cinder (LVM, puis Ceph), Placement, Heat, nova-serialproxy Un projet par établissement · un réseau par classe · pas d'IP publique par VM (NAT) Filtrage sortant : seuls les miroirs de paquets (cache apt) sont joignables ▼ Hetzner Object Storage (S3) : travaux d'élèves, sauvegardes MariaDB, config, images ``` ### Choix techniques (à respecter) - **Console élève** : console série Nova (`nova-serialproxy`), relayée par un petit **proxy WebSocket en Go**, affichée avec **xterm.js**. Elle doit marcher même si l'élève casse le réseau de sa VM. - **Correction** : service sur l'hyperviseur qui exécute les vérifications via **l'agent invité QEMU** (`hw_qemu_guest_agent=yes`). Pas de réseau vers la VM. - **Topologies** : chaque lab est un **modèle Heat**. - **Stock chaud** : N VM démarrées en permanence, gérées par des jobs Laravel dans Redis ; taille ≈ lancements/min × 45 s + marge (8 au départ). Les séances réservées pré-créent les VM 10 min avant. - **Capacité** : ~56 VM de 768 Mo sur 64 Go (à mesurer). Refuser proprement une réservation qui dépasse. - **Gros labs réseau** : Kathará (routeurs en conteneurs dans une seule VM). - **Pas de Windows** avant d'avoir étudié les licences (SPLA). Utiliser Samba AD. - **Octavia, Magnum** : pas avant le deuxième serveur. ### Pile logicielle | Couche | Choix | |---|---| | Backend | PHP 8.3+, **Laravel** (Sanctum, Horizon, Pest), **MariaDB**, **Redis**, client OpenStack (API REST ou `php-opencloud/openstack`) | | Front | Inertia.js + React + TypeScript, Tailwind CSS, shadcn/ui, Radix | | Services en Go | Proxy console WebSocket ; correcteur sur l'hyperviseur (Go ou Python, au choix d'Adam) | | Consoles | xterm.js (texte), noVNC (graphique, plus tard) | | Stockage | Hetzner Object Storage (S3) ; Ceph au bloc C | | LTI Moodle (V2) | `packbackbooks/lti-1p3-tool` | | SSO ENT (V3) | Keycloak | | Infra as code | Ansible, Kolla-Ansible puis OCI/Puppet, Heat, Terraform pour Hetzner Cloud | | Supervision | Prometheus, **Grafana**, Uptime Kuma, Alertmanager ; métriques Laravel (temps de réponse, files Redis) | | Sauvegardes | restic vers Object Storage, restauration testée chaque semaine | | CI | **Forgejo Actions** (syntaxe proche de GitLab CI / GitHub Actions) | | Tests | Pest, Playwright (parcours), axe-core (accessibilité) | --- ## 4. Sécurité : règles non négociables 1. **Secrets** : jamais dans le code, jamais dans Git, jamais affichés en clair. Fichier `.env` (dans `.gitignore`) ou gestionnaire de secrets. Ne demande jamais à Adam de coller un secret dans la conversation. 2. **Clé SSH dédiée** à Claude Code (`~/.ssh/paillasse_claude`), révocable. Jamais la clé personnelle d'Adam. 3. **Projet Hetzner séparé** pour Paillasse, jetons d'API aux droits minimaux. **Ne touche jamais au serveur `tripoli-cloud`** ni à ses ressources. 4. **Avant toute commande destructrice** (`installimage`, `rm -rf`, `mkfs`, suppression de ressource, `DROP`, `migrate:fresh`, réinstallation, pare-feu, routes) : explique, montre la commande exacte, vérifie la sauvegarde, **attends la confirmation explicite d'Adam**. 5. **Ne jamais te couper l'accès** : avant de modifier SSH ou le pare-feu, garde une session ouverte et prévois le retour arrière (mode rescue Hetzner). 6. **Commandes et dépenses** : jamais par Claude. Adam commande à la main. 7. **Données d'élèves** : minimisation (nom, prénom, groupe), pas d'e-mail pour les mineurs, suppression automatique 90 jours après l'archivage de fin d'année. 8. **Anti-abus** : trafic sortant des VM bloqué par défaut, quotas CPU/RAM/durée, journaux. 9. **API** : jetons hachés, droits par jeton, limites de débit, en-têtes de sécurité, validation stricte des entrées (cf. « API hardening » demandé par Infomaniak). 10. **Pas de `--dangerously-skip-permissions`** sur une machine qui touche aux serveurs. --- ## 5. Code source et dépôt - **Forge privée Forgejo** sur le serveur d'Adam. **Aucun dépôt public** (pas de GitHub public). Le code n'est montré à un recruteur que s'il le demande. - Licence des contenus pédagogiques : **au choix d'Adam** (à décider plus tard). Ne pas écrire de mention de licence sans son accord. ``` paillasse/ ├── CLAUDE.md ├── docs/ │ ├── cahier-des-charges.md │ ├── journal.md # journal d'apprentissage et de bord │ ├── runbooks/ # une procédure par opération (install, upgrade, restauration…) │ ├── postmortems/ # AAAA-MM-JJ-titre.md │ └── adr/ # 0001-kolla-avant-oci.md, 0002-laravel-plutot-que-fastapi.md… ├── infra/ │ ├── ansible/ kolla/ heat/ images/ terraform/ ├── app/ # Laravel (API + portail + front Inertia/React) ├── console-proxy/ # Go ├── grader/ # service de correction sur l'hyperviseur ├── labs/ # consignes (Markdown), vérifications, indices (format YAML du pack de contenus) └── ops/ # supervision, alertes, tableaux de bord Grafana ``` ### Conventions - Commits en français, courts, au présent : « ajoute le stock chaud de VM ». - Une branche par fonctionnalité, fusion après tests et relecture. - Chaque décision structurante → un ADR. Chaque incident réel ou provoqué → un post-mortem. - Code PHP : PSR-12, types stricts, Laravel Pint, PHPStan (Larastan) niveau 6 minimum. - Textes de l'interface en français, du point de vue de l'utilisateur (« Lancer le lab », pas « Provisionner l'instance »). --- ## 6. Produit : points clés (détails dans le cahier des charges) - **Rôles** : administrateur d'établissement, enseignant, élève, formateur, opérateur. - **5 façons d'ajouter des élèves** : code ou QR de classe (validation par le prof), import CSV, saisie rapide, invitation e-mail (V2), Moodle LTI 1.3 (V2). - **Élèves mineurs** : identifiant + code secret imprimés sur une fiche de connexion (PDF, QR à usage unique). - **Espace de lab** : consignes à gauche, consoles au centre (un onglet par VM), topologie + vérification + indices à droite, bouton « Lever la main ». - **Séance en direct** : tuiles par élève (étape, bloqué > 8 min, main levée), lecture et prise de main de la console, mode examen. - **Bibliothèque** : séquences cours + TD + quiz + lab, reliées aux référentiels, « Dupliquer et adapter ». Refuser à l'import tout contenu « non commercial » (NC). Quiz en GIFT / Moodle XML. - **Cours texte gratuits** (Linux, réseau), pratique sur VM payante. - **API payante et MCP** : un seul cœur d'API, trois portes (site, API, MCP). Quotas par jeton dans Redis. Les classes restent prioritaires sur la capacité. - **Tout passe par le port 443** et doit marcher sur de vieux PC, Chromebooks et connexions lentes. --- ## 7. Design : beaucoup de style, sans sacrifier la clarté ### Direction artistique - **Idée** : la paillasse de labo et l'établi d'atelier. Précis, technique, chaleureux. Pas le look « SaaS générique ». - **Typographies** : Bricolage Grotesque (titres, avec retenue), IBM Plex Sans (texte), IBM Plex Mono (terminal, chiffres, identifiants). - **Palette de départ** (jetons CSS, thèmes clair et sombre) : - encre `#13233A` · vert paillasse `#2F5D50` · ambre `#C98404` · fond `#F4F6F2` - sémantique : succès `#3C8A5A`, alerte ambre, erreur `#A63D2A` - **Le terminal est le héros** : couleurs, curseur, police mono soignés. - **Deux registres** : pages vitrines expressives (effet wow) ; application sobre, dense, lisible. - **Mouvement** : quelques moments orchestrés, jamais gratuits, respecter `prefers-reduced-motion`. - **À éviter** : dégradé violet-bleu, emojis comme icônes, tout centré, ombres et arrondis identiques partout. ### Source de vérité : Figma - Les jetons (couleurs, typo, espacements, rayons) sont définis en **variables Figma**, puis reportés dans `app/resources/css/tokens.css`. - Les écrans clés sont maquettés dans Figma **avant** d'être codés. Claude lit les maquettes via le **MCP Figma** et reprend les jetons et composants existants ; il ne réinvente pas un style. ### Accessibilité (obligatoire : clients publics) - Contraste AA, navigation au clavier, focus visible, libellés sur tous les champs. - Tests axe-core dans la CI ; parcours clés vérifiés avec Playwright. Référence : RGAA. ### Outils de design pour Claude Code Vérifier chaque commande dans la documentation officielle avant de la lancer. | Outil | Rôle | Installation (à vérifier) | |---|---|---| | Figma MCP | Lire les maquettes et variables Figma | `claude mcp add --transport http figma https://mcp.figma.com/mcp` | | frontend-design (Anthropic) | Direction esthétique | dépôt `anthropics/skills` | | taste-skill | Variété, mouvement, densité | `npx skills add https://github.com/Leonxlnx/taste-skill --skill "design-taste-frontend"` | | UI/UX Pro Max | Styles, polices, ergonomie | dépôt `nextlevelbuilder/ui-ux-pro-max-skill` | | 21st.dev Magic MCP | Composants React pour les pages vitrines | voir `21st.dev/mcp` | | shadcn MCP | Composants shadcn/ui | documentation shadcn | | Playwright MCP | Voir et tester les écrans | `claude mcp add playwright npx @playwright/mcp@latest` | | Context7 | Documentation à jour (Laravel, OpenStack…) | dépôt `upstash/context7` | **Avant d'installer un skill** : lire son `SKILL.md`. ### Méthode 1. Jetons d'abord, puis une page `/design` qui montre tous les composants. 2. Base de l'application : shadcn/ui restylé avec nos jetons. 3. 21st.dev surtout pour les pages vitrines, chaque composant adapté aux jetons. 4. Après chaque écran : capture Playwright, comparaison avec la maquette Figma, test axe-core. --- ## 8. Ce que Claude ne doit pas faire - Ajouter de l'IA dans le produit. - Ajouter une techno sans besoin réel dans Paillasse. - Commander, supprimer ou modifier des ressources payantes sans accord explicite. - Toucher à `tripoli-cloud`. - Publier du code ou créer un dépôt public. - Réutiliser des contenus sous licence NC dans le catalogue. - Intégrer une bibliothèque GPL/AGPL côté service sans signaler la question de licence. - Commencer un bloc avant la fin du précédent (section 2), sauf demande explicite d'Adam. - Faire à la place d'Adam une étape qu'il veut apprendre : dans le doute, demande.