From e4a6aaebb18e7ff5ceed288e2fe088a81125898a Mon Sep 17 00:00:00 2001 From: Adam Belkacemi Date: Fri, 9 Oct 2026 21:07:25 +0200 Subject: [PATCH] =?UTF-8?q?ajoute=20les=20pages=20l=C3=A9gales,=20la=20pur?= =?UTF-8?q?ge=20RGPD=20et=20sert=20polices=20et=20scripts=20depuis=20le=20?= =?UTF-8?q?portail?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pages /legal et /confidentialite réécrites d'après le système réel, purge des classes archivées depuis 90 jours (prouvée par Pest), archivage côté prof. Polices, xterm.js et CodeMirror ne sont plus chargés depuis Google ni jsDelivr. Pages d'aperçu signalées, sans vrais établissements ni faux chiffres. Journaux Laravel gardés 14 jours. Co-Authored-By: Claude Opus 5.5 --- ansible/roles/portail/tasks/03-code.yml | 4 + docs/dette.md | 8 +- docs/journal.md | 34 +++++ docs/runbooks/rgpd.md | 41 +++++ portail/.gitignore | 1 + .../Commands/PurgerClassesArchivees.php | 54 +++++++ .../app/Http/Controllers/ClasseController.php | 28 ++++ .../app/Http/Controllers/SeanceController.php | 5 + .../Middleware/PolitiqueSecuriteContenu.php | 15 +- portail/app/Models/Classe.php | 19 +++ portail/package-lock.json | 9 +- portail/package.json | 5 +- portail/resources/views/academie.blade.php | 18 +-- portail/resources/views/accueil.blade.php | 15 +- portail/resources/views/aide.blade.php | 13 +- portail/resources/views/banque.blade.php | 1 + .../resources/views/bibliotheque.blade.php | 1 + .../resources/views/classes/suivi.blade.php | 1 + portail/resources/views/cockpit.blade.php | 14 +- portail/resources/views/cohortes.blade.php | 14 +- .../resources/views/confidentialite.blade.php | 144 ++++++++++++++++++ portail/resources/views/correction.blade.php | 14 +- portail/resources/views/cours/cm.blade.php | 1 + portail/resources/views/cours/fiche.blade.php | 14 +- portail/resources/views/cours/index.blade.php | 2 +- portail/resources/views/cours/show.blade.php | 1 + portail/resources/views/devoirs.blade.php | 1 + .../resources/views/espace-eleve.blade.php | 14 +- .../views/espace-etablissement.blade.php | 16 +- portail/resources/views/examen.blade.php | 4 +- portail/resources/views/export-ent.blade.php | 14 +- portail/resources/views/facturation.blade.php | 14 +- portail/resources/views/fiche-eleve.blade.php | 14 +- portail/resources/views/generateur.blade.php | 1 + portail/resources/views/ide.blade.php | 36 ++--- portail/resources/views/integration.blade.php | 13 +- portail/resources/views/labs/essai.blade.php | 7 +- portail/resources/views/labs/web.blade.php | 14 +- .../resources/views/layouts/vitrine.blade.php | 7 +- portail/resources/views/legal.blade.php | 67 ++++---- portail/resources/views/maison.blade.php | 1 + .../views/mes-classes/index.blade.php | 7 +- .../views/mes-classes/show.blade.php | 31 ++++ portail/resources/views/messagerie.blade.php | 14 +- portail/resources/views/paiement-ok.blade.php | 14 +- portail/resources/views/paiement.blade.php | 18 +-- .../resources/views/partials/apercu.blade.php | 5 + portail/resources/views/quiz/eleve.blade.php | 4 +- .../resources/views/quiz/projection.blade.php | 4 +- portail/resources/views/ressource.blade.php | 1 + portail/resources/views/sujet-creer.blade.php | 14 +- .../resources/views/td/imprimable.blade.php | 14 +- .../resources/views/vie-scolaire.blade.php | 16 +- portail/resources/views/visio.blade.php | 14 +- portail/routes/console.php | 4 + portail/routes/web.php | 4 + portail/scripts/copier-vendor.mjs | 25 +++ portail/tests/Feature/PagesLegalesTest.php | 36 +++++ portail/tests/Feature/PagesPubliquesTest.php | 17 ++- .../Feature/PolitiqueSecuriteContenuTest.php | 11 ++ portail/tests/Feature/PurgeRgpdTest.php | 99 ++++++++++++ portail/vite.config.js | 9 ++ 62 files changed, 822 insertions(+), 238 deletions(-) create mode 100644 docs/runbooks/rgpd.md create mode 100644 portail/app/Console/Commands/PurgerClassesArchivees.php create mode 100644 portail/resources/views/confidentialite.blade.php create mode 100644 portail/resources/views/partials/apercu.blade.php create mode 100644 portail/scripts/copier-vendor.mjs create mode 100644 portail/tests/Feature/PagesLegalesTest.php create mode 100644 portail/tests/Feature/PurgeRgpdTest.php diff --git a/ansible/roles/portail/tasks/03-code.yml b/ansible/roles/portail/tasks/03-code.yml index 1f06192..05b9e88 100644 --- a/ansible/roles/portail/tasks/03-code.yml +++ b/ansible/roles/portail/tasks/03-code.yml @@ -125,6 +125,10 @@ # Étape 12 : HTTPS. Cookies de session envoyés en HTTPS seulement. - { cle: "APP_URL", valeur: "https://{{ portail_domaine }}" } - { cle: "SESSION_SECURE_COOKIE", valeur: "true" } + # Étape 14 (RGPD) : journaux applicatifs par jour, gardés 14 jours + # (comme ceux de Nginx), au lieu d'un fichier unique jamais purgé. + - { cle: "LOG_STACK", valeur: "daily" } + - { cle: "LOG_DAILY_DAYS", valeur: "14" } no_log: true register: portail_env_mis_a_jour # Horizon charge la configuration une seule fois au démarrage : sans diff --git a/docs/dette.md b/docs/dette.md index e5732f4..57cd40c 100644 --- a/docs/dette.md +++ b/docs/dette.md @@ -11,13 +11,17 @@ retirer la ligne (et le noter dans le journal) quand c'est fait. | Clé age des sauvegardes : copie hors du serveur non confirmée | Sans elle, aucune sauvegarde n'est déchiffrable si le serveur est perdu (voir `docs/runbooks/sauvegardes.md`). Adam doit confirmer l'avoir mise en lieu sûr. | Dès que possible | Étape 3 | | Larastan (PHPStan niveau 6) absent | Exigé par le CLAUDE.md depuis l'étape 8, jamais installé. | Bloc B | Étape 8 | | Vitrine : Tailwind par CDN d'exécution (`cdn.tailwindcss.com`, 19 pages) | Non destiné à la production selon Tailwind, lent, et oblige la vitrine à tolérer les scripts en ligne dans sa CSP. Compiler ces styles avec Vite. | Avant ouverture publique | Étape 12 (design) | -| Vitrine : 52 scripts en ligne, Google Fonts, jsDelivr (démos xterm, CodeMirror) | CSP vitrine avec `'unsafe-inline'` ; CDN parfois filtrés par les réseaux scolaires. Auto-héberger polices et bibliothèques, passer les scripts en fichiers. | Avant ouverture publique | Étape 12 | +| Vitrine : 52 scripts en ligne ; Pyodide et sql.js depuis jsDelivr (`/ide`) ; vidéo YouTube possible (`/cours/…/cm`) | CSP vitrine avec `'unsafe-inline'` ; tiers déclarés dans `/confidentialite`. Polices, xterm.js et CodeMirror sont auto-hébergés depuis l'étape 14. Héberger Pyodide/sql.js, passer les scripts en fichiers. | Avant ouverture publique | Étapes 12 et 14 | | xterm.js 5.5.0 (6.0.0 disponible) | Version majeure à évaluer séparément. | Bloc B | Étape 12 | | NodeSource installé par `curl … \| bash` | Script distant exécuté en root au premier déploiement. Déclarer le dépôt (deb822) avec une clé vérifiée. | Bloc B | Étape 8 | -| Aucune vérification dans un vrai navigateur | Extension Chrome non connectée (étapes 8 et 12). La CSP n'est contrôlée que par ses rapports. | Dès que possible | Étapes 8 et 12 | +| Aucune vérification dans un vrai navigateur | Extension Chrome non connectée (étapes 8, 12 et 14). La CSP n'est contrôlée que par ses rapports. À vérifier en priorité : `/ide` (Pyodide, WebAssembly) et les pages vitrine qui utilisent xterm.js/CodeMirror désormais servis par le portail. | Dès que possible | Étapes 8, 12, 14 | | Pas de sonde hors du serveur | Si le serveur tombe, personne n'est prévenu. | À décider avec Adam | Étape 7 | | Kolla installé depuis une branche, pas un tag | Reproductibilité. | Montée de version | ADR 0001 | | Correction séquentielle (~5 s pour le lab 08) | Acceptable ; à paralléliser si la charge l'exige. | Bloc B | Étape 11 | | Jeton de console : ≈ 1,1 s par appel Nova `remote-consoles` | Plus gros poste de l'ouverture d'un lab (2,8 s au total, critère < 5 s tenu). Préparer les jetons à l'attribution si besoin. | Bloc B | Étape 13 | | Tâches Ansible toujours « modifiées » (composer, npm, build, cache) | Brouille la lecture de l'idempotence. | Bloc B | Étape 8 | | `Permissions-Policy` ferme caméra et micro | À ouvrir pour la visio. | Étape 15 | Étape 12 | +| Mentions légales à compléter | Forme juridique, SIREN et adresse du siège d'Esquisse Formation ; délégué à la protection des données s'il en est désigné ; article « Disponibilité et responsabilité » des CGU. | Avant le pilote | Étape 14 | +| Slogans « du lycée au master » | Le catalogue va aujourd'hui du lycée au BUT. Positionnement laissé tel quel : décision éditoriale d'Adam. | À décider | Étape 14 | +| Ancien `storage/logs/laravel.log` | Fichier unique d'avant la rotation quotidienne (étape 14) : jamais purgé, à supprimer ou archiver (accord d'Adam). | Dès que possible | Étape 14 | +| Pages d'aperçu publiques (32) | Signalées comme aperçus avec données fictives ; à retirer ou remplacer au fur et à mesure que les fonctions réelles arrivent. | Au fil du bloc B | Étape 14 | diff --git a/docs/journal.md b/docs/journal.md index d24bb18..ea29e2a 100644 --- a/docs/journal.md +++ b/docs/journal.md @@ -566,3 +566,37 @@ Un serveur qui « marche » n'est pas un serveur qui *revient* : trois valeurs p **Suite** Étape 14 : pages légales et RGPD. + +## 2026-10-09 — Étape 14 : pages légales et RGPD + +**Fait** + +- **Purge RGPD** : bouton « Archiver la classe » côté prof (plus de séance possible, date de suppression affichée, désarchivage possible d'ici là) et commande `classes:purger-archivees`, chaque nuit : une classe archivée depuis 90 jours est supprimée avec, en cascade, ses élèves, séances, sessions, machines et corrections. Le compte du prof reste ; le journal ne garde ni nom ni prénom. +- **Pages légales réécrites d'après le système réel** : `/legal` (mentions légales : Esquisse Formation, SIREN et adresse à compléter par Adam ; hébergeur vérifié à la source, mentions légales de Scaleway ; CGU) et `/confidentialite` (données réellement traitées, finalités et bases légales, durées vérifiées sur le serveur, hébergement et tiers, sécurité, cookies, droits, sous-traitance). `/statut` redirige vers la page de statut. +- **Plus aucun envoi d'adresse IP chez Google** : Archivo et IBM Plex Mono sont téléchargées à la compilation et servies par le portail (`Vite::fonts()`), au lieu de Google Fonts, chargé jusque-là sur **toutes** les pages, espace élève compris. xterm.js et CodeMirror servis depuis `public/vendor/` (copiés des paquets npm à la compilation) au lieu de jsDelivr. +- **Journaux** : Laravel passe d'un fichier unique jamais purgé à un fichier par jour gardé 14 jours (comme Nginx). +- **Interdits du prompt** : aucun logo Marianne, ministère, drapeau de l'UE ni « logo RGPD » sur le site. Bandeau « Aperçu d'une fonction en préparation — données fictives » sur les 32 pages d'aperçu (choix d'Adam) ; vrais établissements des tableaux de bord remplacés par des noms fictifs ; « 20 cursus » corrigé en « 6 cursus » ; « 99 cours » présenté comme un programme en cours de publication ; « Conforme au RGPD » relié à `/confidentialite` ; « Hébergé en France · Paris » ramené à « Hébergé en France » (commune du datacenter non vérifiable sur le site de Scaleway). +- 8 nouveaux tests Pest (33 au total) ; runbook `docs/runbooks/rgpd.md`. + +**Problèmes rencontrés et solution** + +1. **La page `/legal` du design décrivait un système qui n'existe pas** : « aucun traceur tiers » et « les données ne quittent pas l'UE » alors que Google Fonts était chargé partout, un « mode examen » qui enregistre les changements d'onglet (non construit), « temps passé, réponses aux QCM » (non collectés). Réécrite affirmation par affirmation. +2. **Faux clients et chiffres inventés** dans les pages d'aperçu (« Lycée Vauban Brest », « 608 élèves »…). Mon premier test cherchait nom et ville collés et a laissé passer les tableaux où ils sont dans deux cellules (« Lycée Vauban | Brest ») : test réécrit pour chercher chaque nom seul, sur les 32 aperçus — il a ensuite trouvé `/paiement` et les dernières lignes de `/academie`. +3. **La CSP de l'étape 12 cassait probablement l'exécution de code sur `/ide`** (Pyodide doit télécharger ses fichiers et compiler du WebAssembly) : `connect-src` et `'wasm-unsafe-eval'` ajoutés pour la vitrine. Non vérifié dans un navigateur (extension non connectée). +4. Deux erreurs dans mes tests : `toContain($texte, $message)` de Pest traite le second argument comme un autre texte à trouver ; le test « toutes les pages en 200 » ne prévoyait pas la redirection voulue de `/statut`. +5. Tinker lancé avec un fichier est resté bloqué en attente de saisie : remplacé par des tests Pest permanents (aucune police externe sur aucune page ; aucune ressource externe sur les pages de l'application). + +**Critère vérifié** + +- Pages en ligne : `/legal` 200, `/confidentialite` 200, `/statut` → 302 vers `https://status.syllabuslab.fr/` ; page de statut publique opérationnelle (étape 12). +- **La purge fonctionne, prouvée par Pest** (`PurgeRgpdTest`, 5 tests) : classe archivée depuis 91 jours supprimée avec élèves, séances, sessions, machines et corrections, compte du prof conservé ; classes archivées depuis 89 jours et classes actives épargnées ; seules les classes concernées touchées ; archivage par le prof, refus pour un autre prof. En production : `classes:purger-archivees` → « 0 classe(s) purgée(s) » (aucune classe archivée), planifiée à 02:30. +- `/connexion` ne charge plus que des ressources de `syllabuslab.fr` ; aucune mention de Google Fonts sur l'accueil ; 0 violation CSP depuis le déploiement. + +**Comprendre** + +Une politique de confidentialité n'est pas un texte juridique à recopier : c'est une description exacte de ce que fait le système, et elle engage. Celle du design promettait « aucun traceur tiers » pendant que chaque page, y compris celles des élèves mineurs, envoyait l'adresse IP du visiteur à Google pour charger une police. Le bon réflexe est de partir de la réalité (que collecte-t-on ? où ? combien de temps ? qui d'autre la voit ?), de la vérifier sur le serveur, puis de corriger le système quand la réalité n'est pas défendable — ici, servir les polices nous-mêmes — plutôt que d'adapter le texte. La purge suit la même logique : une durée de conservation écrite n'a de valeur que si un programme l'applique, et un test prouve qu'il l'applique. + +**Suite** + +- Adam : compléter forme juridique, SIREN, adresse du siège (et DPO s'il y en a un) dans `/legal` et `/confidentialite` ; vérifier `/ide` dans un navigateur. +- Étape 15 : visio de classe — seulement après validation des étapes 1 à 11 (le prompt l'exige). diff --git a/docs/runbooks/rgpd.md b/docs/runbooks/rgpd.md new file mode 100644 index 0000000..dd4ff4e --- /dev/null +++ b/docs/runbooks/rgpd.md @@ -0,0 +1,41 @@ +# Runbook — Données personnelles (RGPD) + +Politique publique : `https://syllabuslab.fr/confidentialite` +(`portail/resources/views/confidentialite.blade.php`). **Toute nouvelle donnée +collectée, tout nouveau service tiers ou toute nouvelle durée de conservation +doit d'abord y être décrit.** La page affirme seulement ce qui a été vérifié. + +## Où sont les données + +| Donnée | Où | Durée | +|---|---|---| +| Comptes profs, classes, élèves, séances, sessions, corrections | MariaDB du portail (`portail_mariadb`) | jusqu'à 90 jours après l'archivage de la classe | +| VM des élèves (disques) | OpenStack, une stack par session | fin de session (45 min par défaut) | +| Journaux Nginx (IP, pages) | `/var/log/nginx/` | 14 jours (logrotate) | +| Journaux Laravel | `storage/logs/laravel-AAAA-MM-JJ.log` | 14 jours (`LOG_STACK=daily`, `LOG_DAILY_DAYS=14`) | +| Sauvegardes chiffrées | Dedibackup (Scaleway, France) | 7 quotidiennes + 4 hebdomadaires (≤ 5 semaines) | + +## Purge automatique + +- Le prof archive sa classe (page de la classe, « Archiver la classe ») : plus de séance possible ; la date de suppression est affichée. +- `classes:purger-archivees` (chaque nuit à 02:30 UTC) supprime les classes archivées depuis 90 jours, et en cascade leurs élèves, séances, sessions, machines et corrections. Le compte du prof reste. Le journal ne garde que l'identifiant de la classe et le nombre d'élèves. +- Une classe avec un lab encore en cours est reportée (anomalie : un lab expire en 45 min) et signalée dans le journal. +- Preuve : `portail/tests/Feature/PurgeRgpdTest.php`. + +``` +ssh paillasse "cd /var/www/portail && sudo -u www-data HOME=/tmp php8.3 artisan classes:purger-archivees" +``` + +## Répondre à une demande d'exercice des droits + +Contact public : adam@belkacemi.me. Pour un élève, la demande passe normalement par son établissement (responsable du traitement). + +- **Accès / portabilité (élève)** : prénom, nom, identifiant, classe, sessions et corrections ; extraire avec `artisan tinker` (`App\Models\Eleve::with('labSessions.corrections')->where('identifiant', '…')->first()->toArray()`), sans le code secret (haché, inutile). +- **Effacement d'un élève** : `App\Models\Eleve::where('identifiant', '…')->first()->delete()` — cascade sur ses sessions et corrections. +- **Effacement d'un compte prof** : supprimer d'abord ses classes (ou les archiver), puis `App\Models\User::where('email', '…')->first()->delete()`. +- Noter la demande et sa date de traitement (hors du dépôt : le registre contient des données personnelles). +- Rappeler que les sauvegardes chiffrées contenant la donnée expirent d'elles-mêmes sous 5 semaines. + +## Interdits sur le site (prompt de déploiement, étape 14) + +Pas de logo Marianne ou ministère, de drapeau de l'UE, de faux « logo RGPD », de chiffres inventés ni de faux clients. Formulations autorisées : « Hébergé en France », « Conforme au RGPD » avec un lien vers `/confidentialite`. Les pages d'aperçu (fonctions pas encore construites) portent le bandeau `partials/apercu` et n'affichent que des noms fictifs (`PagesLegalesTest`). diff --git a/portail/.gitignore b/portail/.gitignore index f2e8cf6..4122d53 100644 --- a/portail/.gitignore +++ b/portail/.gitignore @@ -26,3 +26,4 @@ _ide_helper.php Homestead.json Homestead.yaml Thumbs.db +/public/vendor diff --git a/portail/app/Console/Commands/PurgerClassesArchivees.php b/portail/app/Console/Commands/PurgerClassesArchivees.php new file mode 100644 index 0000000..4ce8c1a --- /dev/null +++ b/portail/app/Console/Commands/PurgerClassesArchivees.php @@ -0,0 +1,54 @@ +where('archivee_a', '<=', now()->subDays(Classe::DELAI_PURGE_JOURS)) + ->withCount('eleves') + ->get(); + + $purgees = 0; + + foreach ($classes as $classe) { + // Ne peut arriver qu'en cas d'anomalie (un lab expire en 45 min) : + // on ne supprime pas une session dont la stack Heat vivrait encore. + if ($classe->aDesLabsEnCours()) { + Log::warning('Purge RGPD reportée : lab en cours', ['classe_id' => $classe->id]); + + continue; + } + + DB::transaction(fn () => $classe->delete()); + Log::info('Purge RGPD : classe supprimée', [ + 'classe_id' => $classe->id, + 'eleves' => $classe->eleves_count, + 'archivee_a' => $classe->archivee_a->toDateString(), + ]); + $purgees++; + } + + $this->info("{$purgees} classe(s) purgée(s)."); + } +} diff --git a/portail/app/Http/Controllers/ClasseController.php b/portail/app/Http/Controllers/ClasseController.php index 2b51030..58d0a71 100644 --- a/portail/app/Http/Controllers/ClasseController.php +++ b/portail/app/Http/Controllers/ClasseController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use App\Models\Classe; use App\Models\Eleve; +use App\Models\Seance; use App\Services\GenerateurCompteEleve; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -124,6 +125,33 @@ class ClasseController extends Controller ]; } + /** + * Fin d'année : plus de séance possible, et suppression définitive de la + * classe et des données de ses élèves 90 jours plus tard. + */ + public function archiver(Classe $classe): RedirectResponse + { + $this->verifierProprietaire($classe); + + if ($classe->aDesLabsEnCours()) { + return back()->withErrors(['archivage' => 'Des élèves ont encore un lab en cours : termine la séance avant d’archiver.']); + } + + $classe->forceFill(['archivee_a' => now()])->save(); + $classe->seances()->whereIn('statut', [Seance::PLANIFIEE, Seance::SALLE_ATTENTE, Seance::EN_COURS]) + ->update(['statut' => Seance::TERMINEE, 'terminee_a' => now()]); + + return redirect()->route('mes-classes.show', $classe); + } + + public function desarchiver(Classe $classe): RedirectResponse + { + $this->verifierProprietaire($classe); + $classe->forceFill(['archivee_a' => null])->save(); + + return redirect()->route('mes-classes.show', $classe); + } + private function verifierProprietaire(Classe $classe): void { abort_if($classe->user_id !== Auth::guard('web')->id(), 403); diff --git a/portail/app/Http/Controllers/SeanceController.php b/portail/app/Http/Controllers/SeanceController.php index 05c6976..a797f57 100644 --- a/portail/app/Http/Controllers/SeanceController.php +++ b/portail/app/Http/Controllers/SeanceController.php @@ -24,6 +24,10 @@ class SeanceController extends Controller { abort_if($classe->user_id !== Auth::guard('web')->id(), 403); + if ($classe->estArchivee()) { + return back()->withErrors(['prevue_a' => 'Cette classe est archivée : désarchive-la pour lancer une séance.']); + } + $donnees = $request->validate([ 'lab_id' => ['required', 'exists:labs,id'], 'prevue_a' => ['nullable', 'date_format:Y-m-d\TH:i'], @@ -130,6 +134,7 @@ class SeanceController extends Controller { $eleve = Auth::guard('eleve')->user(); abort_if($eleve->classe_id !== $seance->classe_id, 403); + abort_if($seance->classe->estArchivee(), 403); LabSession::firstOrCreate( ['seance_id' => $seance->id, 'eleve_id' => $eleve->id], diff --git a/portail/app/Http/Middleware/PolitiqueSecuriteContenu.php b/portail/app/Http/Middleware/PolitiqueSecuriteContenu.php index 8dccd2d..62072af 100644 --- a/portail/app/Http/Middleware/PolitiqueSecuriteContenu.php +++ b/portail/app/Http/Middleware/PolitiqueSecuriteContenu.php @@ -41,7 +41,8 @@ class PolitiqueSecuriteContenu $communes = [ 'default-src' => "'self'", 'img-src' => "'self' data:", - 'font-src' => "'self' https://fonts.gstatic.com", + // Polices servies par le portail (Vite), depuis l'étape 14. + 'font-src' => "'self'", 'object-src' => "'none'", 'base-uri' => "'self'", 'form-action' => "'self'", @@ -54,13 +55,17 @@ class PolitiqueSecuriteContenu 'script-src' => "'self' 'nonce-".Vite::cspNonce()."'", // Attributs style= présents dans le gabarit commun : sans // risque d'exécution de code, tolérés. - 'style-src' => "'self' 'unsafe-inline' https://fonts.googleapis.com", + 'style-src' => "'self' 'unsafe-inline'", 'connect-src' => "'self' wss://{$request->getHost()}", ] : [ - 'script-src' => "'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdn.tailwindcss.com", - 'style-src' => "'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net", - 'connect-src' => "'self'", + // jsDelivr : Pyodide et sql.js, téléchargés par /ide à la + // demande (WebAssembly, d'où 'wasm-unsafe-eval', qui n'autorise + // pas eval() en JavaScript). Tailwind : CDN d'exécution des + // pages du design. Voir docs/dette.md. + 'script-src' => "'self' 'unsafe-inline' 'wasm-unsafe-eval' https://cdn.jsdelivr.net https://cdn.tailwindcss.com", + 'style-src' => "'self' 'unsafe-inline'", + 'connect-src' => "'self' https://cdn.jsdelivr.net", 'frame-src' => 'https://www.youtube-nocookie.com', ]; diff --git a/portail/app/Models/Classe.php b/portail/app/Models/Classe.php index 3c08788..a6254a0 100644 --- a/portail/app/Models/Classe.php +++ b/portail/app/Models/Classe.php @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Support\Carbon; use Illuminate\Support\Str; class Classe extends Model @@ -58,4 +59,22 @@ class Classe extends Model { return $this->archivee_a !== null; } + + /** + * RGPD (CLAUDE.md) : une classe archivée et toutes les données de ses + * élèves sont supprimées 90 jours après l'archivage (classes:purger-archivees). + */ + public const DELAI_PURGE_JOURS = 90; + + public function supprimeeLe(): ?Carbon + { + return $this->archivee_a?->copy()->addDays(self::DELAI_PURGE_JOURS); + } + + public function aDesLabsEnCours(): bool + { + return LabSession::whereIn('seance_id', $this->seances()->select('id')) + ->whereIn('etat', [LabSession::ADMIS, LabSession::ACTIF]) + ->exists(); + } } diff --git a/portail/package-lock.json b/portail/package-lock.json index 926b233..30ad09a 100644 --- a/portail/package-lock.json +++ b/portail/package-lock.json @@ -6,7 +6,8 @@ "": { "dependencies": { "@xterm/addon-fit": "^0.10.0", - "@xterm/xterm": "^5.5.0" + "@xterm/xterm": "^5.5.0", + "codemirror": "^5.65.16" }, "devDependencies": { "@tailwindcss/vite": "^4.0.0", @@ -806,6 +807,12 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/codemirror": { + "version": "5.65.16", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.16.tgz", + "integrity": "sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg==", + "license": "MIT" + }, "node_modules/commander": { "version": "15.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", diff --git a/portail/package.json b/portail/package.json index 17f32ed..83ee511 100644 --- a/portail/package.json +++ b/portail/package.json @@ -3,7 +3,7 @@ "private": true, "type": "module", "scripts": { - "build": "vite build", + "build": "vite build && node scripts/copier-vendor.mjs", "dev": "vite" }, "devDependencies": { @@ -17,6 +17,7 @@ }, "dependencies": { "@xterm/addon-fit": "^0.10.0", - "@xterm/xterm": "^5.5.0" + "@xterm/xterm": "^5.5.0", + "codemirror": "^5.65.16" } } diff --git a/portail/resources/views/academie.blade.php b/portail/resources/views/academie.blade.php index ed8c857..5256741 100644 --- a/portail/resources/views/academie.blade.php +++ b/portail/resources/views/academie.blade.php @@ -4,8 +4,7 @@ Tableau de bord académie · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-

Multi-établissements

Pour les profs

+

Multi-établissements

Pour les profs

Tableau de bord académie

6 établissements · 28 classes · 608 élèves · année 2026-2027

  • Élèves actifs

    608

    +86 ce mois

  • Taux d’activité

    91 %

    élèves connectés / semaine

  • Labs réalisés

    4 210

    depuis la rentrée

  • Heures de VM

    2 940 h

    sur 9 120 h incluses

  • Élèves accompagnés

    47

    suite à une alerte

-

Établissements

ÉtablissementClassesÉlèvesActivitéCompétences validéesStatut

Lycée Jean-Jaurès

Montreuil

611894 %72 %Actif

Lycée Louis-Armand

Paris 15e

920490 %68 %Actif

Lycée Saint-Exupéry

Marseille

48688 %61 %Actif

IUT de Villetaneuse

Villetaneuse

716092 %70 %Actif

Lycée Condorcet

Saint-Priest

24071 %55 %Démarrage

Lycée Vauban

Brest

00——Invité
+

Établissements

ÉtablissementClassesÉlèvesActivitéCompétences validéesStatut

Lycée de démonstration B

Ville fictive

611894 %72 %Actif

Lycée de démonstration C

Ville fictive

920490 %68 %Actif

Lycée de démonstration D

Ville fictive

48688 %61 %Actif

IUT de démonstration

Ville fictive

716092 %70 %Actif

Lycée de démonstration A

Ville fictive

24071 %55 %Démarrage

Lycée de démonstration E

Ville fictive

00——Invité

Compétences les moins acquises

BTS SIO et CIEL
  • Services réseau (DHCP, DNS)38 %
  • Scripts Bash46 %
  • VLAN et commutation52 %
  • Sécurité des accès58 %
  • Adressage IPv466 %

Piste : proposer une formation académique sur les services réseau.

Rapports

  • Bilan de rentrée 2026

    PDF · 12 pages · 01/10

  • Usage par établissement

    CSV · 29/09

  • Compétences par filière

    PDF · 6 pages · 29/09

@@ -59,10 +59,10 @@

● Tous les services fonctionnent

-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/accueil.blade.php b/portail/resources/views/accueil.blade.php index bead766..6b3b4d2 100644 --- a/portail/resources/views/accueil.blade.php +++ b/portail/resources/views/accueil.blade.php @@ -5,8 +5,7 @@ Syllabus — Une vraie machine Linux pour chaque élève - - + {{ Vite::fonts() }} @vite(['resources/css/app.css', 'resources/js/app.js']) - - - + + + @@ -40,7 +39,7 @@ -

Cours · TP sur machine · suivi des élèves

Enseigner l’informatique, du lycée au master.

Des cours gratuits, un vrai Linux pour chaque élève et toute la classe sur un écran. Dans le navigateur, rien à installer.

Créer une classe gratuite

Sans carte bancaire · élève ? rejoindre ma classe

  • Hébergé en France

    Paris

  • RGPD

    données minimisées

  • 20 cursus

    du lycée au master

  • 443 seulement

    aucun port à ouvrir

  • 0 €

    sans carte bancaire

Pour l’élève

Un terminal Linux en 5 secondes.

Chaque élève a sa propre machine Debian. Il clique, la console s’ouvre. Aucun poste du lycée à configurer.

Essayer un lab sans compte →

eleve@lab-07 · Debian 12
eleve@lab-07:~$ ip -br addr
+

Cours · TP sur machine · suivi des élèves

Enseigner l’informatique, du lycée au master.

Des cours gratuits, un vrai Linux pour chaque élève et toute la classe sur un écran. Dans le navigateur, rien à installer.

Créer une classe gratuite

Sans carte bancaire · élève ? rejoindre ma classe

  • Hébergé en France

    Paris

  • RGPD

    données minimisées

  • 6 cursus

    du lycée au BUT

  • 443 seulement

    aucun port à ouvrir

  • 0 €

    sans carte bancaire

Pour l’élève

Un terminal Linux en 5 secondes.

Chaque élève a sa propre machine Debian. Il clique, la console s’ouvre. Aucun poste du lycée à configurer.

Essayer un lab sans compte →

eleve@lab-07 · Debian 12
eleve@lab-07:~$ ip -br addr
 ens18  UP  10.20.7.14/24
 eleve@lab-07:~$ ping -c1 10.20.7.1
 64 bytes from 10.20.7.1: time=0.4 ms
@@ -55,10 +54,10 @@ eleve@lab-07:~$  

Produit

● Tous les services fonctionnent

-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/aide.blade.php b/portail/resources/views/aide.blade.php index f8e0ddb..86fbacd 100644 --- a/portail/resources/views/aide.blade.php +++ b/portail/resources/views/aide.blade.php @@ -4,8 +4,7 @@ Aide et tutoriels · Syllabus - - + {{ Vite::fonts() }} - - - + + + @@ -56,10 +55,10 @@

● Tous les services fonctionnent

-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/banque.blade.php b/portail/resources/views/banque.blade.php index e986f67..83334ae 100644 --- a/portail/resources/views/banque.blade.php +++ b/portail/resources/views/banque.blade.php @@ -3,6 +3,7 @@ @section('titre', 'Banque de sujets') @section('contenu') + @include('partials.apercu')
diff --git a/portail/resources/views/bibliotheque.blade.php b/portail/resources/views/bibliotheque.blade.php index ed32d02..84c68d7 100644 --- a/portail/resources/views/bibliotheque.blade.php +++ b/portail/resources/views/bibliotheque.blade.php @@ -3,6 +3,7 @@ @section('titre', 'Bibliothèque') @section('contenu') + @include('partials.apercu')

Bibliothèque du prof

diff --git a/portail/resources/views/classes/suivi.blade.php b/portail/resources/views/classes/suivi.blade.php index a192cbe..21da071 100644 --- a/portail/resources/views/classes/suivi.blade.php +++ b/portail/resources/views/classes/suivi.blade.php @@ -3,6 +3,7 @@ @section('titre', 'Suivi de classe') @section('contenu') + @include('partials.apercu')
diff --git a/portail/resources/views/cockpit.blade.php b/portail/resources/views/cockpit.blade.php index 5c23a45..070358a 100644 --- a/portail/resources/views/cockpit.blade.php +++ b/portail/resources/views/cockpit.blade.php @@ -4,8 +4,7 @@ Cockpit prof · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/cohortes.blade.php b/portail/resources/views/cohortes.blade.php index f6df979..05d5079 100644 --- a/portail/resources/views/cohortes.blade.php +++ b/portail/resources/views/cohortes.blade.php @@ -4,8 +4,7 @@ Suivi des cohortes · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/confidentialite.blade.php b/portail/resources/views/confidentialite.blade.php new file mode 100644 index 0000000..5981518 --- /dev/null +++ b/portail/resources/views/confidentialite.blade.php @@ -0,0 +1,144 @@ +@extends('layouts.vitrine') + +@section('titre', 'Confidentialité et RGPD') + +{{-- Étape 14 : chaque affirmation de cette page a été vérifiée sur le système + réel (docs/journal.md, étape 14). À mettre à jour à chaque nouveau + traitement de données. --}} +@section('contenu') +
+
+

Confidentialité et RGPD

+

Ce que nous savons de vous, et pourquoi.

+

Dernière mise à jour : 9 octobre 2026

+
+
+
+ +
+ +
+

Qui est responsable

+
+

Syllabus est édité par Esquisse Formation (voir les mentions légales).

+

Quand un établissement utilise Syllabus avec ses élèves, l’établissement est responsable du traitement et Esquisse Formation agit comme sous-traitant, sur ses instructions. Pour les comptes enseignants, Esquisse Formation est responsable du traitement.

+

Délégué à la protection des données : [à compléter si désigné]. Contact : adam@belkacemi.me

+
+
+ +
+

Données traitées

+
+

Élèves

+
    +
  • prénom, nom (facultatif, visible du seul enseignant), classe ;
  • +
  • identifiant de connexion et code secret (le code est stocké sous forme hachée, illisible, y compris pour nous) ;
  • +
  • aucune adresse e-mail ;
  • +
  • sessions de lab : date, état, machines virtuelles attribuées ;
  • +
  • résultats de la vérification automatique (réussi ou non, note, message par vérification).
  • +
+

Ce que l’élève tape dans la console de sa machine virtuelle n’est pas enregistré par Syllabus. Son enseignant peut suivre la console en direct, en lecture seule, pendant la séance.

+

Enseignants

+
    +
  • nom, adresse e-mail, établissement ;
  • +
  • mot de passe, stocké sous forme hachée.
  • +
+

Journaux techniques

+
    +
  • journaux du serveur web : adresse IP, date, page demandée ;
  • +
  • journaux de l’application : erreurs et événements techniques, sans contenu des pages.
  • +
+

Finalités et bases légales

+

Fournir le service d’enseignement demandé par l’établissement (mission d’intérêt public de l’établissement, article 6.1.e du RGPD) ou par l’enseignant (exécution du contrat, article 6.1.b). Les journaux techniques servent à la sécurité et au bon fonctionnement du service (intérêt légitime, article 6.1.f). Aucune donnée n’est vendue, utilisée à des fins publicitaires, ni traitée par une intelligence artificielle.

+
+
+ +
+

Durées de conservation

+
+
    +
  • Machines virtuelles et leur contenu : supprimées à la fin de la session de lab (45 minutes par défaut).
  • +
  • Classe et données de ses élèves : jusqu’à l’archivage de la classe par l’enseignant, puis supprimées automatiquement 90 jours après l’archivage.
  • +
  • Compte enseignant : tant qu’il est utilisé ; supprimé sur demande.
  • +
  • Journaux techniques : 14 jours.
  • +
  • Sauvegardes : chiffrées, conservées au plus 5 semaines (7 sauvegardes quotidiennes et 4 hebdomadaires). Une donnée supprimée disparaît donc des sauvegardes au plus tard 5 semaines après sa suppression.
  • +
+
+
+ +
+

Hébergement et services tiers

+
+

Le service, ses bases de données et ses sauvegardes chiffrées sont hébergés en France, chez Scaleway. Les données des comptes ne quittent pas l’Union européenne.

+

Les pages de l’espace connecté (élèves et enseignants) ne chargent aucune ressource depuis un service tiers : polices, scripts et styles sont servis par Syllabus.

+

Certaines pages publiques de présentation font encore appel à des services tiers, qui reçoivent alors l’adresse IP du visiteur :

+
    +
  • des pages d’aperçu chargent la bibliothèque de styles Tailwind depuis cdn.tailwindcss.com (Tailwind Labs, États-Unis) ;
  • +
  • l’éditeur de code /ide télécharge Python (Pyodide) et SQL (sql.js) depuis cdn.jsdelivr.net, seulement quand on exécute du code ;
  • +
  • la page d’aperçu d’un cours peut afficher une vidéo depuis youtube-nocookie.com, seulement si un lien vidéo y est ajouté.
  • +
+

Nous travaillons à servir ces ressources nous-mêmes.

+
+
+ +
+

Sécurité

+
+
    +
  • connexions chiffrées (HTTPS, TLS 1.2 et 1.3) ;
  • +
  • mots de passe et codes secrets hachés ;
  • +
  • une machine virtuelle par élève, isolée, sans accès à Internet ;
  • +
  • la vérification automatique n’exécute que des commandes définies à l’avance par le lab, jamais de commande libre ;
  • +
  • sauvegardes chiffrées avant leur envoi, restauration testée chaque semaine ;
  • +
  • administration du serveur par clé SSH uniquement.
  • +
+
+
+ +
+

Cookies

+
+

Syllabus n’utilise que deux cookies, strictement nécessaires : syllabus-session, qui vous garde connecté, et XSRF-TOKEN, qui protège les formulaires. Aucun cookie publicitaire ni de mesure d’audience. Ils ne demandent donc pas de consentement.

+

L’éditeur de code et la page de visio gardent aussi, dans le stockage local de votre navigateur, votre code et une préférence d’affichage. Ces informations ne nous sont pas transmises.

+
+
+ +
+

Vos droits

+
+

Vous disposez des droits d’accès, de rectification, d’effacement, de limitation, d’opposition et de portabilité. Élèves et familles : adressez-vous d’abord à l’enseignant ou à l’établissement, responsable du traitement. Enseignants : écrivez à adam@belkacemi.me.

+

Vous pouvez aussi adresser une réclamation à la CNIL (cnil.fr).

+
+
+ +
+

Sous-traitance (article 28 du RGPD)

+
+

Pour chaque établissement, un accord de sous-traitance peut être établi sur demande. Il précise :

+
    +
  • l’objet, la durée et la nature des traitements ;
  • +
  • les mesures de sécurité décrites ci-dessus ;
  • +
  • la confidentialité des personnes autorisées ;
  • +
  • les sous-traitants ultérieurs : hébergement et sauvegardes chez Scaleway (France) ;
  • +
  • l’assistance pour répondre aux demandes d’exercice des droits ;
  • +
  • la notification des violations de données ;
  • +
  • la suppression ou la restitution des données en fin de contrat.
  • +
+

Demande : adam@belkacemi.me

+
+
+ +
+
+@endsection diff --git a/portail/resources/views/correction.blade.php b/portail/resources/views/correction.blade.php index 225ee5c..853d4ec 100644 --- a/portail/resources/views/correction.blade.php +++ b/portail/resources/views/correction.blade.php @@ -4,8 +4,7 @@ Correction assistée · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/cours/cm.blade.php b/portail/resources/views/cours/cm.blade.php index 3ba5026..042acfa 100644 --- a/portail/resources/views/cours/cm.blade.php +++ b/portail/resources/views/cours/cm.blade.php @@ -3,6 +3,7 @@ @section('titre', 'CM · Adressage IPv4') @section('contenu') + @include('partials.apercu')
CM diff --git a/portail/resources/views/cours/fiche.blade.php b/portail/resources/views/cours/fiche.blade.php index 3b89d1a..907d6c6 100644 --- a/portail/resources/views/cours/fiche.blade.php +++ b/portail/resources/views/cours/fiche.blade.php @@ -4,8 +4,7 @@ Cours · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/cours/index.blade.php b/portail/resources/views/cours/index.blade.php index da92753..54927fc 100644 --- a/portail/resources/views/cours/index.blade.php +++ b/portail/resources/views/cours/index.blade.php @@ -3,7 +3,7 @@ @section('titre', 'Cours gratuits') @section('contenu') -

Gratuit, sans compte

99 cours gratuits, calés sur vos référentiels.

Chaque cours suit le découpage de l’Éducation nationale : un CM pour comprendre, un TD pour s’exercer sur papier, un TP sur une vraie VM, un QCM corrigé et expliqué.

99 cours · 45 TD · 59 TP sur VM · 98 QCM corrigés

+

Gratuit, sans compte

Des cours gratuits, calés sur vos référentiels.

Chaque cours suit le découpage de l’Éducation nationale : un CM pour comprendre, un TD pour s’exercer sur papier, un TP sur une vraie VM, un QCM corrigé et expliqué.

Programme : 99 cours · 45 TD · 59 TP sur VM · 98 QCM corrigés — en cours de publication

{{-- Boucle et données absentes de la maquette design/ (perdues lors de sa refonte) : rétablies d'après design/_backup-ludique, étape 12. --}} @php diff --git a/portail/resources/views/cours/show.blade.php b/portail/resources/views/cours/show.blade.php index 68ee32f..bde1d6a 100644 --- a/portail/resources/views/cours/show.blade.php +++ b/portail/resources/views/cours/show.blade.php @@ -3,6 +3,7 @@ @section('titre', 'Adressage IPv4 et sous-réseaux') @section('contenu') + @include('partials.apercu')
diff --git a/portail/resources/views/devoirs.blade.php b/portail/resources/views/devoirs.blade.php index 578c58e..4e189e2 100644 --- a/portail/resources/views/devoirs.blade.php +++ b/portail/resources/views/devoirs.blade.php @@ -3,6 +3,7 @@ @section('titre', 'Devoirs maison') @section('contenu') + @include('partials.apercu')

Espace enseignant · Devoirs

Pour les profs

diff --git a/portail/resources/views/espace-eleve.blade.php b/portail/resources/views/espace-eleve.blade.php index e533953..875b121 100644 --- a/portail/resources/views/espace-eleve.blade.php +++ b/portail/resources/views/espace-eleve.blade.php @@ -4,8 +4,7 @@ Mon espace élève · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/espace-etablissement.blade.php b/portail/resources/views/espace-etablissement.blade.php index f14c9fa..70ef6ea 100644 --- a/portail/resources/views/espace-etablissement.blade.php +++ b/portail/resources/views/espace-etablissement.blade.php @@ -4,8 +4,7 @@ Espace établissement · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-

Gestion administrative

Pour les profs

+

Gestion administrative

Pour les profs

Espace établissement

Abonnement, licences, documents comptables et contrats. Accès réservé à l’intendance et à la direction.

  • Formule Établissement

    20 classes

    renouvelable chaque année

  • Période

    01/09 → 31/08

    renouvellement le 01/07/2027

  • Licences

    118 / 120

    2 disponibles

  • Heures de VM

    2 940 h

    sur 9 120 h incluses

Licences

118 actives · 2 libres
TitulaireClasse / rôleDébutFinStatut
Martin LéaBTS SIO 1 A01/09/202630/06/2027Active
Kaci InèsBTS SIO 1 A01/09/202630/06/2027Active
Petit HugoBTS SIO 2 B01/09/202515/10/2026Fin programmée
Roche AnneEnseignante01/09/2026—Active
Leroy TomBTS SIO 1 B01/09/202629/09/2026Retirée

Import CSV : colonnes nom;prenom;email;classe;date_fin. Une licence se libère automatiquement à la date de fin ; les données de l’étudiant sont supprimées 12 mois après, sauf export demandé.

-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/examen.blade.php b/portail/resources/views/examen.blade.php index 64c33cc..6763477 100644 --- a/portail/resources/views/examen.blade.php +++ b/portail/resources/views/examen.blade.php @@ -4,8 +4,7 @@ Mode examen · Syllabus - - + {{ Vite::fonts() }} @vite(['resources/css/app.css', 'resources/js/app.js']) - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/facturation.blade.php b/portail/resources/views/facturation.blade.php index 3303a3e..d4d8fae 100644 --- a/portail/resources/views/facturation.blade.php +++ b/portail/resources/views/facturation.blade.php @@ -4,8 +4,7 @@ Mon abonnement · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/fiche-eleve.blade.php b/portail/resources/views/fiche-eleve.blade.php index 55bf658..e48ef3d 100644 --- a/portail/resources/views/fiche-eleve.blade.php +++ b/portail/resources/views/fiche-eleve.blade.php @@ -4,8 +4,7 @@ Fiche élève · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/generateur.blade.php b/portail/resources/views/generateur.blade.php index f30e240..eebcbd3 100644 --- a/portail/resources/views/generateur.blade.php +++ b/portail/resources/views/generateur.blade.php @@ -3,6 +3,7 @@ @section('titre', 'Générateur de TD') @section('contenu') + @include('partials.apercu')

Générateur de TD

diff --git a/portail/resources/views/ide.blade.php b/portail/resources/views/ide.blade.php index 225d689..f864b7b 100644 --- a/portail/resources/views/ide.blade.php +++ b/portail/resources/views/ide.blade.php @@ -4,8 +4,7 @@ IDE en ligne · Syllabus - - + {{ Vite::fonts() }} @vite(['resources/css/app.css', 'resources/js/app.js']) - - - + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + @@ -68,10 +67,10 @@

● Tous les services fonctionnent

-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/labs/essai.blade.php b/portail/resources/views/labs/essai.blade.php index 2806986..b6f0715 100644 --- a/portail/resources/views/labs/essai.blade.php +++ b/portail/resources/views/labs/essai.blade.php @@ -3,13 +3,14 @@ @section('titre', 'Lab d’essai · Premiers pas dans le shell') @push('head') - - - + + + @endpush @section('contenu') + @include('partials.apercu')
← Labs diff --git a/portail/resources/views/labs/web.blade.php b/portail/resources/views/labs/web.blade.php index 594405a..f15f928 100644 --- a/portail/resources/views/labs/web.blade.php +++ b/portail/resources/views/labs/web.blade.php @@ -4,8 +4,7 @@ Lab web · Syllabus - - + {{ Vite::fonts() }} @vite(['resources/css/app.css', 'resources/js/app.js']) - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/layouts/vitrine.blade.php b/portail/resources/views/layouts/vitrine.blade.php index 2f81e26..92deae4 100644 --- a/portail/resources/views/layouts/vitrine.blade.php +++ b/portail/resources/views/layouts/vitrine.blade.php @@ -4,8 +4,7 @@ @yield('titre') · Syllabus - - + {{ Vite::fonts() }} @vite(['resources/css/app.css', 'resources/js/app.js']) - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/paiement-ok.blade.php b/portail/resources/views/paiement-ok.blade.php index 8423032..38cb583 100644 --- a/portail/resources/views/paiement-ok.blade.php +++ b/portail/resources/views/paiement-ok.blade.php @@ -4,8 +4,7 @@ Paiement confirmé · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/paiement.blade.php b/portail/resources/views/paiement.blade.php index 25bc51b..b7bf68e 100644 --- a/portail/resources/views/paiement.blade.php +++ b/portail/resources/views/paiement.blade.php @@ -4,8 +4,7 @@ Paiement · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')

2 · Facturation

-
+

3 · Moyen de paiement

@@ -62,7 +62,7 @@
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/partials/apercu.blade.php b/portail/resources/views/partials/apercu.blade.php new file mode 100644 index 0000000..ee59744 --- /dev/null +++ b/portail/resources/views/partials/apercu.blade.php @@ -0,0 +1,5 @@ +{{-- Étape 14 : bandeau des pages d'aperçu (fonctions pas encore construites). + Aucune donnée réelle : ni vrais établissements, ni vrais chiffres. --}} +
+ Aperçu d’une fonction en préparation — les établissements, classes, élèves et chiffres affichés sont fictifs. +
diff --git a/portail/resources/views/quiz/eleve.blade.php b/portail/resources/views/quiz/eleve.blade.php index 8e994d9..96271d5 100644 --- a/portail/resources/views/quiz/eleve.blade.php +++ b/portail/resources/views/quiz/eleve.blade.php @@ -4,8 +4,7 @@ Quiz flash · Syllabus - - + {{ Vite::fonts() }} @vite(['resources/css/app.css', 'resources/js/app.js']) - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/td/imprimable.blade.php b/portail/resources/views/td/imprimable.blade.php index 356e0e8..a536702 100644 --- a/portail/resources/views/td/imprimable.blade.php +++ b/portail/resources/views/td/imprimable.blade.php @@ -4,8 +4,7 @@ TD à imprimer · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')
-
  • Hébergé en France · Paris
  • RGPD · données minimisées
  • 20 cursus · du lycée au master
  • 0 € · sans carte bancaire
+
  • Hébergé en France
  • Conforme au RGPD · données minimisées
  • 6 cursus · du lycée au BUT
  • 0 € · sans carte bancaire
diff --git a/portail/resources/views/vie-scolaire.blade.php b/portail/resources/views/vie-scolaire.blade.php index ad39511..ff196e4 100644 --- a/portail/resources/views/vie-scolaire.blade.php +++ b/portail/resources/views/vie-scolaire.blade.php @@ -4,8 +4,7 @@ Vie scolaire et intendance · Syllabus - - + {{ Vite::fonts() }} - - - + + + +@include('partials.apercu')