15 KiB
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 :
- 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. »
- 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. »
- 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)
- API publique Laravel versionnée (
/api/v1), documentée en OpenAPI, tests Pest, jetons Sanctum, quotas et limites de débit dans Redis. - Cache Redis sur les lectures lourdes (catalogue, tableau de bord prof) ; mesure avant/après dans Grafana.
- Optimisation MariaDB : index,
EXPLAIN, requêtes N+1 supprimées, jeu de données de charge (ex. 500 classes, 20 000 élèves). - 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
- 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. - Clé SSH dédiée à Claude Code (
~/.ssh/paillasse_claude), révocable. Jamais la clé personnelle d'Adam. - Projet Hetzner séparé pour Paillasse, jetons d'API aux droits minimaux. Ne touche jamais au serveur
tripoli-cloudni à ses ressources. - 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. - 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).
- Commandes et dépenses : jamais par Claude. Adam commande à la main.
- 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.
- Anti-abus : trafic sortant des VM bloqué par défaut, quotas CPU/RAM/durée, journaux.
- 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).
- Pas de
--dangerously-skip-permissionssur 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
- encre
- 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
- Jetons d'abord, puis une page
/designqui montre tous les composants. - Base de l'application : shadcn/ui restylé avec nos jetons.
- 21st.dev surtout pour les pages vitrines, chaque composant adapté aux jetons.
- 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.