Files
nessar f1094ac0b6 docs: consolidate the lot #7 validation report (#13)
Add the dated lot-level report (versions, protocol, results, mobile and
keyboard checks, verified vs untested) and point the README at it. Prove
the Quick Connect API limitation on the real installed server by refusing
an unknown secret with 404, and check that no credential label remains.
2026-09-18 10:52:07 +02:00

9.3 KiB
Raw Permalink Blame History

Validation du lot #7 — connexion du compagnon par Quick Connect

Rapport du 18 septembre 2026. Ce document est le rapport de lot ; le détail ticket par ticket (contrat HTTP, mesures, revues) reste dans issue-8.md, qui couvre les lots #8 à #12. Aucun serveur de l'utilisateur n'a été touché : tout s'exécute sur un conteneur jetable supprimé en sortie.

Versions

Élément Version
Jellyfin Server 12.0.0, image jellyfin/jellyfin:12.0@sha256:baba630419915985442f315f08b0cf46d9f4c8a0cc4bd38e94a6d35751dd5ef5, Linux x64
Plugin Compagnon 0.5.0, archive dist/compagnon-0.5.0-jellyfin-12.0.0.zip, SHA-256 10917490c28b606f0395aa5efe51a7e3727b95e1bff4d880d96ee208b807c434
Interface compagnon servie par le plugin, Version="0.5.0" dans l'en-tête Jellyfin
Navigateur compagnon Chromium 149.0.7827.55 (headless), Playwright 1.61.1
Outils Node.js 24.18.0, .NET SDK 10 (image épinglée), ffmpeg du conteneur Jellyfin

Protocole

bash tests/run.sh                      # serveur jetable, paquet installé, tests réels
node --test tests/quick-connect.test.mjs   # frontière navigateur/API seule

tests/run.sh compile le plugin en Release (avertissements bloquants), construit l'archive, lance le serveur 12.0.0 sur un port local libre, crée un compte administrateur de préparation et deux comptes ordinaires (Alice, Bob), une vidéo de deux minutes avec timecode et des pistes SRT/VTT/ASS, active Quick Connect, puis installe l'archive et redémarre. Il vérifie d'abord que le plugin sert le compagnon sans préfixe, configure ensuite <BaseUrl>/jellyfin</BaseUrl> et exécute la suite complète sous /jellyfin. Le conteneur est supprimé en sortie.

Les scénarios à la frontière navigateur/API interceptent les routes avec Playwright pour produire les états qu'un serveur réel ne donne pas à la demande (code expiré par 404, Quick Connect désactivé, panne, 500 temporaire). Les scénarios installés utilisent le vrai serveur : approbation par un compte authentifié, révocation réelle de jeton, coupure réseau réelle (context.setOffline).

Résultats

Exécution complète du 18 septembre 2026 : compilation C# Release 0 erreur, 0 avertissement, vérification TypeScript réussie, 27 tests sur 27 en 97,4 s ; le contrôle sans préfixe réussit avant la suite sous /jellyfin. Les exécutions précédentes du rapport issue-8.md (17, 18, 20, 22, 25 puis 26 tests) étaient toutes réussies.

Critère du lot #7 Vérification
Le README décrit l'approbation Quick Connect, la reconnexion conservée et la déconnexion ; plus de mot de passe ni de jeton seulement en mémoire Section Installation (approbation dans un client connecté), puis conservation dans ce navigateur, refus de jeton, panne et « Se déconnecter » avec révocation ; le formulaire identifiant/mot de passe n'existe plus dans l'interface
Un rapport daté consigne versions, protocole, résultats et limites Ce document, avec le détail par ticket dans issue-8.md
Passage complet des tests installés, y compris derrière le préfixe de base tests/run.sh : contrôle sans préfixe puis 26/26 sous /jellyfin
Aucun contrôle identifiant/mot de passe, aucune requête d'authentification par mot de passe, aucun jeton visible noPassword() à la frontière (aucun input[type=password], #username, #login, aucun libellé identifiant/mot de passe, aucun AuthenticateByName) ; journal réseau installé sans AuthenticateByName ; jeton absent de l'URL, des messages affichés et de la console (compagnon.connexion ne contient que jeton, compte, appareil)
Contrôles mobile (375 px) et clavier des écrans de connexion, d'expiration et de déconnexion consignés Tableau ci-dessous ; les scénarios navigateur utilisent 375 × 812 et les écrans de connexion, d'expiration et de déconnexion vérifient l'absence de débordement horizontal
Environnement installé indisponible : écart rapporté Non rencontré : l'image est épinglée et l'exécution complète a eu lieu ; si Docker est absent, tests/run.sh échoue sans conclure
Limite de l'API Quick Connect de la version supportée rapportée avec preuves Voir « Limite observée » ci-dessous ; aucun repli par mot de passe ni jeton de Jellyfin Web n'a été ajouté

Mobile (375 px) et clavier

Écran Contrôle Résultat
Connexion Code affiché dans un role="status" aria-live, visible à 375 px sans débordement ; aucun champ ni libellé identifiant/mot de passe Vérifié (frontière « stay usable by keyboard at 375 px » ; noPassword)
Connexion Approbation réelle par un compte authentifié puis suivi d'une lecture réelle, à 375 px Vérifié (installé « real playback is followed… », « ordinary account logs in… »)
Expiration « Générer un nouveau code » focalisé, activé par Entrée seule, nouveau code affiché ; sur le serveur installé, un vrai code régénéré est approuvé Vérifié (frontière « stay usable by keyboard… » ; installé « an expired code is replaced… »)
Déconnexion Depuis le sélecteur focalisé, Tab puis Entrée atteignent « Se déconnecter », l'état « Déconnecté. » s'affiche et « Se connecter » prend le focus Vérifié (frontière « stay usable by keyboard… » ; installé « explicit disconnect revokes… », « ordinary account logs in… »)
Déconnexion Révocation réelle du jeton, autres clients intacts, message si la révocation n'est pas confirmée Vérifié (installé, « explicit disconnect revokes… »)

Jeton et absence de mot de passe

  • Aucun champ ni libellé d'identifiant/mot de passe ne subsiste : le formulaire a été remplacé par le panneau Quick Connect, et les contrôles le vérifient sur le HTML servi comme sur le journal réseau.
  • Le compagnon n'émet aucune requête Users/AuthenticateByName ; le mot de passe n'est utilisé que par les tests pour préparer les comptes et le client approbateur (commentaire en tête de tests/installed.test.mjs).
  • Le jeton du compagnon n'apparaît ni dans l'URL de la page, ni dans un message affiché, ni dans la console ; seul compagnon.connexion le conserve, avec l'identifiant de compte et d'appareil, et il est effacé à la déconnexion comme à un refus d'authentification.

Limite observée dans l'API Quick Connect 12.0

GET QuickConnect/Connect?secret= répond 404 aussi bien pour un secret inconnu que pour un code expiré : le serveur ne fournit pas de signal distinct d'expiration. Le compagnon interprète donc tout 404 comme « Ce code a expiré. Générez un nouveau code. », ce qui reste sûr (aucune approbation possible) mais ne distingue pas un secret invalide d'un code périmé. Preuves : contrat relevé dans issue-8.md, refus réel d'un secret inconnu par le serveur 12.0 installé (installed.test.mjs, « an unknown Quick Connect secret is refused with 404 »), test frontière qui produit le 404 d'expiration (quick-connect.test.mjs, « an expired code is identified… ») et test installé qui force le même 404 sur le serveur réel, le délai d'expiration de dix minutes n'étant pas attendu (installed.test.mjs, « an expired code is replaced… »).

Aucune méthode de connexion de repli et aucun jeton de Jellyfin Web n'ont été introduits pour contourner cette limite, conformément au périmètre.

Cas non testés ou hors qualification

  • Interface d'approbation d'un vrai client Jellyfin : l'approbation est exercée par l'API authentifiée QuickConnect/Authorize, pas en pilotant l'écran « Réglages → Quick Connect » de Jellyfin Web.
  • Expiration réelle de dix minutes : non attendue ; l'état est obtenu par interception (frontière) ou 404 forcé sur le serveur réel.
  • Quick Connect désactivé côté serveur : obtenu par interception, pas en modifiant la configuration du serveur jetable.
  • Panne réseau : coupure réelle context.setOffline ; l'erreur serveur 500 est interceptée.
  • Appareil mobile physique : seulement un viewport 375 × 812 dans Chromium headless, pas un navigateur mobile réel ni un lecteur d'écran.
  • HTTPS, reverse proxy et fournisseurs SSO : hors qualification, comme aux lots précédents ; Quick Connect est le seul chemin de connexion.
  • Objectif de synchronisation < 500 ms : non atteint (voir issue-8.md), hors de ce lot.
  • Stream.json natif sans contrôle de droits : limite serveur déjà documentée et contournée par la route authentifiée du plugin, hors de ce lot.

Revue

Deux agents ont examiné séparément les axes normes et spécification. Normes : aucun écart aux règles écrites du dépôt ; le SHA-256, les versions et les durées du rapport correspondent à l'archive et au journal d'exécution ; les attributions de tests trop larges ont été corrigées. Spec : la limite Quick Connect n'était appuyée que sur des 404 simulés ; un contrôle réel de refus d'un secret inconnu sur le serveur installé a été ajouté, et le contrôle noPassword() vérifie désormais aussi l'absence de libellé identifiant/mot de passe. L'affirmation sur le débordement horizontal a été restreinte aux écrans réellement vérifiés. Aucun repli de connexion ni jeton de Jellyfin Web n'a été introduit.