Analyse
Corico aide un enseignant à rendre un retour oral sur un devoir : il enregistre un mémo pour chaque copie, et l'élève l'écoute en scannant un QR code collé dessus.
Parcours
- L'enseignant choisit une classe et un devoir.
- Pour chaque copie, il choisit l'élève, enregistre, valide. Sur téléphone ou sur ordinateur.
- L'outil dépose le son sur le Nextcloud de l'ENT et crée un lien de partage public, qui expire le 30 juin de l'année scolaire.
- À la fin, il génère le PDF d'une planche d'étiquettes.
- L'enseignant colle chaque QR code sur la copie de l'élève. L'élève écoute sans compte ni application.
Décisions
- Stockage : le Nextcloud de l'ENT de l'enseignant, avec un mot de passe d'application. Vérifié sur
nc-lycees.netocentre.fr: un lien public se lit sur téléphone sans connexion à l'ENT. Le parcours complet y a été testé le 4 novembre 2026, depuis un ordinateur : dossier, nom neutre, lien en lecture seule, expiration au 30 juin. - Étiquettes : trois formats au choix, 35 × 35 mm par défaut, 48,5 × 25,4 mm et 38,1 × 21,2 mm. Le nom de l'élève est sur l'étiquette, sous le QR code sur une ligne, prénom d'abord et nom coupé par « … » si besoin, ou à côté, car les formats longs n'ont pas de place entre les étiquettes. Les trois grilles sont mesurées sur de vraies planches. Toutes sont réglables dans l'outil avec une feuille de calage.
- Liens sensibles : le lien d'un mémo n'est protégé ni par une connexion, ni par un code personnel. L'outil le rappelle partout où un QR code s'affiche et sur la page qui génère le PDF, avant le téléchargement (
src/LinkWarning.vue). - Élèves : liste de classe collée ou importée (CSV, texte), les colonnes des noms repérées par leur titre ; seuls les noms sont repris.
- Corriger et retirer : un devoir, une classe et un élève se renomment ou se retirent ; supprimer un devoir ou en retirer un élève supprime les mémos de Nextcloud (
docs/fr/guide/managing.md). C'est aussi le ménage de fin d'année. - Données locales : le navigateur travaille comme sur des fichiers du disque de l'enseignant. Il n'y a ni compte ni déconnexion : on relie son Nextcloud une fois, et le mot de passe n'est redemandé que s'il est refusé. Un bouton efface les données de cet appareil.
- Sauvegarde : les listes et le suivi sont dans un seul fichier chiffré du dossier
Corico, relu à l'ouverture et envoyé après chaque changement. Une écriture ne passe que sur la version lue (ETag) ; sinon, les deux versions sont fusionnées. Un fichier illisible (autre clé) n'est jamais écrasé sans demande explicite. - Brouillons : un mémo enregistré est gardé aussitôt dans le navigateur (IndexedDB), sans être déposé, et survit à un rechargement ou à un départ de la page en plein enregistrement. Les élèves se font dans n'importe quel ordre ; les brouillons se déposent un par un ou tous d'un coup.
- Appareil personnel ou partagé : demandé à la connexion et à l'association. Un appareil personnel garde l'accès, la clé, les listes et les brouillons dans le navigateur, scellés si l'enseignant pose un mot de passe local (Argon2id sur une clé AES-GCM tirée au hasard, qui scelle le tout ; 8 caractères au moins, verrouillé de nouveau après 30 minutes sans activité). Un appareil partagé les garde dans la mémoire de la page seulement, pas même dans
sessionStorage, que la restauration de session d'un navigateur rend : un rechargement déconnecte, le navigateur prévient avant, les mises à jour attendent, et 30 minutes sans activité font tout oublier sauf s'il reste des brouillons à déposer. - Recommencer : le nouvel enregistrement reste à part jusqu'à ce que l'enseignant, après avoir écouté les deux, le valide pour remplacer l'ancien. Un mauvais clic ne fait rien perdre.
- Publier au même endroit : un mémo déjà déposé et refait est écrit sur le même fichier. Nextcloud rattache un lien au fichier et non à son contenu : le lien et le QR code imprimé restent donc les mêmes. Vérifié sur l'ENT le 5 novembre 2026 : un ancien QR code joue le nouveau son.
- PDF :
pdf-lib, comme Kolekti, avec Fira Sans intégrée pour les noms accentués et les alphabets latins étendus. QR code de 28 mm, le reste de l'étiquette servant de zone de silence. Un nom trop long est réduit, puis coupé. - Chiffrement : tous les fichiers sauf les sons sont chiffrés dans le navigateur (AES-256-GCM, Web Crypto) par une clé créée à la première connexion.
- Association d'un appareil : un lien, ou le QR code de ce lien, contient les identifiants Nextcloud et la clé, après le
#pour ne jamais être envoyé au serveur. Ce contenu est chiffré par un code aléatoire de 8 caractères, en base 32 sans caractères ambigus, dérivé par Argon2id, à transmettre par un autre canal, et avec un nombre aléatoire que le relais garde en mémoire 10 minutes au plus et ne donne qu'une fois (server/pairing.ts) : passé ce délai, le lien et son code n'ouvrent plus rien. Un code, un sel et un nombre par association. - Public : l'enseignant d'abord, puis ses collègues avec leur propre compte.
- Noms de fichiers : les sons portent un nom aléatoire, dans un dossier par classe et, dedans, un par devoir, à leur nom (
src/shared/folders.ts) ;Mémos en lignedans une classe à un seul QR code pour l'année. Renommer déplace le dossier ; les mémos déposés avant les dossiers y sont rangés à l'ouverture. Deux classes, ou deux devoirs d'une classe, ne peuvent partager ni un nom ni un dossier.
Architecture
Navigateur → corico.infobrisson.fr page statique (hébergement français)
→ api.corico.infobrisson.fr relais Node (VPS)
→ nc-lycees.netocentre.fr Nextcloud de l'ENTLe relais est nécessaire : testé le 4 novembre 2026, le Nextcloud (34.0.5) n'envoie aucun en-tête CORS, donc une page web ne peut pas l'appeler directement. Il est décrit, avec ce qu'il voit et ce qu'il ne garde pas, dans la page de confidentialité.
- Stack : celle de MinOS et de Kolekti (Vue 3, Vite, TypeScript, Vuetify, Vitest, yarn 4, ESLint, Prettier). Relais en Hono, comme le serveur de Kolekti.
- Corps de requête : gardé en mémoire vive le temps de l'envoi, pour le transmettre avec sa taille plutôt qu'en flux : certains serveurs PHP perdent les corps envoyés en flux. La taille est bornée.
- Format audio : chaque mémo est converti en MP3 dans le navigateur avant le dépôt (mono, 64 kbit/s, environ 500 Ko par minute), car tous les téléphones le lisent, alors que ce qu'enregistrent les navigateurs diffère :
.oggsous Firefox, Opus sous Chromium, qui refuse l'AAC. L'encodeur est@breezystack/lamejs(LGPL-3.0), un portage de LAME en pur JavaScript : la page n'a pas besoin de WebAssembly pour cela. - PWA : un service worker garde les fichiers de l'application, jamais de données. Il cherche une nouvelle version au retour sur la page et toutes les 5 minutes, et la page se recharge dès que rien ne s'y oppose (
src/shared/version.ts). - Déploiement : la page et la documentation depuis un ordinateur (
yarn deploy), précompressées en Brotli et envoyées parrsyncà leur place, la CI de la forge ne contrôlant que le style et les tests, sans révisions datées ; le relais par un rôle Ansible de la configuration du serveur, comme Kolekti.
Un seul QR code par élève pour l'année
Une demande de Romain, une option par classe, le QR code par devoir restant le défaut. Le QR code d'un élève est un fichier public dans student.qr, réécrit à chaque publication, son lien ne changeant donc jamais ; les mémos d'un tel devoir (assignment.yearly, fixé à sa création) sont des fichiers sans lien. src/shared/year-qr.ts.
- Ce qui est en ligne l'est par élève, dans
qr.assignmentId: rien d'autre ne le note, et ce qui reste à faire après un échec s'en déduit. Publier un devoir donne les deux notes de musique à un élève sans mémo : un ancien mémo serait pris pour celui-ci. Un ancien mémo peut être remis pour un seul élève. - Un nouveau QR code crée un nouveau fichier qui fait entendre la même chose, puis supprime l'ancien, dont le lien meurt avec lui. S'il ne peut pas être supprimé, le nouveau fichier part et l'échec est dit : un code cru coupé serait pire.
- Le relais ne change pas : publier, c'est lire un fichier du dossier et en écrire un autre.
- Versions précédentes d'un fichier : Nextcloud les garde, comme pour un mémo republié au même endroit. Elles sont prévues pour le propriétaire du compte, et la page publique ne devrait proposer que le lecteur et le téléchargement. Vérifié par Romain sur le vrai ENT le 5 novembre 2026 : un lien republié, ouvert en navigation privée, ne donne pas accès aux versions précédentes.
Imprimer avant de corriger
Une demande de Romain : un enseignant au lycée avec l'imprimante, qui corrige chez lui et rend les copies le lendemain matin. Comme un fichier peut être réécrit sans changer son lien (la publication au même endroit), une place est réservée à l'avance : un fichier de deux brèves notes de musique et son lien public, marqués reserved dans le contenu (reserveMemos dans src/shared/deposit.ts). Un tel mémo ne compte ni comme déposé ni comme fait, mais s'imprime ; le dépôt écrit par-dessus. Deux appareils qui réservent chacun de leur côté laisseraient un fichier inconnu de l'outil, comme tout mémo fait à part.
Éditer et fusionner les mémos
Une demande de Romain.
- Plusieurs mémos pour une copie : un enseignant qui a oublié quelque chose ajoute un enregistrement. Il reste à part, et le dépôt est refusé tant qu'ils ne sont pas fusionnés, dans l'ordre choisi, ou que l'un n'est pas gardé. Au-delà de deux, ils se fusionnent un par un.
- Couper : un passage se retire d'un mémo, avant ou après une fusion, avec une annulation tant que la version n'est pas gardée.
- Le son pendant le travail : un brouillon est gardé en WAV, qui ne perd rien quel que soit le nombre de coupes (environ 5 Mo par minute), et ne devient un MP3 qu'au dépôt (
src/shared/sound.ts). Les brouillons d'avant sont des MP3, et le restent si on n'y touche pas. - Après le dépôt : le mémo est récupéré dans Nextcloud et redevient un brouillon, publié au même endroit. Son MP3 est décodé puis encodé une fois de plus : une génération de compression de plus, pas encore jugée à l'oreille.
Hors périmètre, définitivement
- D'autres ENT : une décision de Romain, l'outil ne sera jamais développé pour d'autres ENT que celui pour lequel il est configuré. Le relais parle à un seul Nextcloud et son filtre réseau ne lui laisse atteindre que celui-là.