Journal des changements
Tout ce qui change dans ProtoFlix, le jour où ça change : ce qui est ajouté, corrigé, et ce qui a été essayé pour de vrai.
139 entrées
Ajouté Lire sur la TV et la piloter depuis le téléphone
- « Lire sur la TV » (ADR 0044) : depuis la fiche d'un film ou d'un épisode, ou depuis le lecteur du téléphone, on choisit une TV où ProtoFlix tourne et la lecture y démarre. Depuis la fiche, la TV reprend où son compte s'était arrêté ; depuis le lecteur, là où en était le téléphone, dont le lecteur se ferme. Essayé sur la TV de référence et le Pixel 9 Pro : Interstellar démarre sur la TV en quelques secondes, au bon endroit.
- Le téléphone comme télécommande : ce que lit la TV, en direct (titre, position, lecture ou pause) ; lecture et pause, ±10/30 s, la barre de progression, épisode suivant et précédent, pistes audio et sous-titres, volume de la TV, et en secours les flèches, OK, Retour et Accueil (dans ProtoFlix). Une barre en bas de l'application suit la TV pilotée. Sur la TV, un bandeau discret dit qui la pilote.
- Tout passe par le serveur, aussi hors de la maison : la TV s'annonce, les commandes lui arrivent par le flux d'événements, à elle seule (
/api/v1/remote/…, migration 00044). Le compte connecté sur la TV la pilote sans rien demander ; un autre compte du serveur doit être accepté une fois sur la TV (« Accepter / Refuser »), et peut être retiré dans ses réglages. - La TV reste joignable ProtoFlix fermé : un service démarre avec elle. Pour qu'un envoi ouvre ProtoFlix depuis l'écran d'accueil d'Android, la TV doit l'autoriser à « afficher par-dessus les autres applications » (Réglages > Compte de ProtoFlix) ; sans cela, le téléphone dit d'ouvrir ProtoFlix d'abord. Depuis l'économiseur de ProtoFlix, l'envoi l'ouvre sans autorisation. Pas de Google Cast.
Ajouté Économiseur d'écran de la TV, partie serveur
- Module « Économiseur d'écran » (
screensaver, ADR 0043), éteint de base. Il rend pour chaque compte la scène que la TV dessine (GET /api/v1/screensaver/scene?client=tv) : jusqu'à 60 images de fond des films et séries que la personne peut voir, limite d'âge comprise, mélangées et gardées dans le même ordre une heure ; les réglages de l'horloge et de la veille de nuit ; et des bulles. Module éteint : 404module_disabled, la TV garde l'économiseur du système. - Bulles : « Ce soir sur ProtoFlix » (le prochain épisode à regarder et les derniers ajouts) ; la météo d'Open-Meteo, sans compte : la ville est située une fois, puis seules des coordonnées arrondies au dixième de degré partent, et la réponse est gardée 15 minutes ; Home Assistant : les entités choisies, avec une étiquette si on veut, mises en forme par le serveur (« 1,2 kW », « À la maison »), et une bulle de tâches par liste
todo.*. Home Assistant n'est lu que pendant qu'une TV demande la scène, au plus toutes les 30 s ; son jeton est un secret qui ne quitte pas le serveur. Le module peut joindre l'adresse de Home Assistant même locale, et elle seule. Un connecteur en panne retire sa bulle, sans casser la scène. - Photos privées en fond, en option : celles de la personne connectée à la TV, seules ou en alternance avec les films. Désactivées de base.
- Module « Économiseur d'écran » (
Ajouté Économiseur d'écran de la TV, partie TV
- Économiseur d'écran sur la TV (ADR 0043). Les images de fond des films et des séries défilent, très assombries, désaturées et vignettées, avec un fondu lent. Au premier plan : une horloge à aiguilles, l'heure en grand et la date, et des bulles d'information. Pour ne pas marquer l'écran, l'ensemble se décale chaque minute et l'horloge change de côté chaque heure. La nuit, il est plus sombre encore.
- Lancement : dans l'application après quelques minutes sans touche, jamais pendant un film ou une chaîne ; et comme économiseur du système Android TV, à choisir dans les réglages de la TV. Un aperçu est dans Réglages > Affichage.
- Musique : elle laisse maintenant l'écran se mettre en veille. L'économiseur montre ce qui joue.
- La scène vient du module
screensaverdu serveur (GET /api/v1/screensaver/scene, contrat dansapi/screensaver/). Sans ce module, l'aperçu et l'économiseur du système prennent les fonds de la bibliothèque, et l'application ne se met pas en veille d'elle-même.
Amélioré TV : moins de conversions, son à l'heure
- Sous-titres image dessinés par la TV. Un sous-titre PGS, DVB ou DVD choisi dans un film envoyé tel quel reste dans le fichier : la TV le décode et le dessine à sa place sur l'image, au lieu que le serveur convertisse tout le film pour l'incruster. Forrest Gump en 4K HDR se lit maintenant sans conversion avec ses sous-titres du Blu-ray. Seule une application qui le déclare (
capabilities.subtitles) en profite ; une plus ancienne garde l'incrustation. - Décodeurs DTS et TrueHD de la TV réparés. La version publiée de l'application ne chargeait pas les décodeurs de FFmpeg (une fonction appelée par le code natif était retirée à la construction) : chaque film en DTS était converti par le serveur. Interstellar se lit maintenant tel quel.
- Son et image à l'heure. Le lecteur de la TV passe en mode tunnel quand la TV le permet : c'est elle qui cale l'image sur le son qu'elle joue vraiment. Mesuré en filmant la TV (flash et bip), le son s'est rapproché de son image de 53 à 64 ms. Un réglage « Synchro du son » dans le panneau des pistes, par pas de 25 ms et gardé par la TV, compense en plus une barre de son lente.
- Sous-titres image dessinés par la TV. Un sous-titre PGS, DVB ou DVD choisi dans un film envoyé tel quel reste dans le fichier : la TV le décode et le dessine à sa place sur l'image, au lieu que le serveur convertisse tout le film pour l'incruster. Forrest Gump en 4K HDR se lit maintenant sans conversion avec ses sous-titres du Blu-ray. Seule une application qui le déclare (
Modifié Le domaine du projet : protoflix.club
- Le dépôt officiel des modules est maintenant
https://modules.protoflix.club. Les fichiers signés n'ont pas changé ; l'ancienne adressemodules.klarvi.frsert encore le même dépôt le temps que les serveurs installés prennent cette version. - Le relais de notifications est en ligne à
https://push.protoflix.club. Un serveur l'utilise avecPROTOFLIX_PUSH_RELAY=https://push.protoflix.club: ses téléphones reçoivent alors les notifications tout de suite, par Firebase. - Le service de soumission des modules prendra l'adresse
soumettre.modules.protoflix.club.
- Le dépôt officiel des modules est maintenant
Corrigé Icônes de l'app TV
- Quatre icônes de l'app TV étaient mal tracées : Effacer, Cercle coché et Image perdaient une partie de leur dessin, hors du cadre, et Zap était écrite dans une notation que tous les lecteurs ne lisent pas. « trash-2 » montre maintenant une corbeille, comme sur le site, et non plus la touche Effacer.
Amélioré Conversion plus rapide, tons HDR sur l'iGPU Intel
- Tons HDR sur l'iGPU Intel. Avec un iGPU Intel, les tons HDR10 se calculent maintenant sur la carte, quand le film décrit son écran de mastering. Sur un UHD 750, 30 s de 4K HDR se convertissent en environ 4,5 s au lieu de 14 à 17 s, avec presque pas de processeur. Le démarrage passe à 0,5 s et les sauts à moins d'une seconde, deux fois mieux que Jellyfin sur la même machine. La luminosité est corrigée pour égaler celle de la table du processeur.
- Sur le processeur. x264 a des réglages plus légers (17 % plus rapide, différence de qualité négligeable), l'image est réduite par
zscaleau lieu descale, et la table de tons travaille en virgule flottante. Une conversion 4K vers 1080p est environ 25 % plus rapide qu'avant. - Les mesures face à Jellyfin et Emby sont dans
docs/testing/benchmarks/ovh-protoflix-jellyfin-emby.md. En HDR sans carte graphique, ProtoFlix reste plus lent que Jellyfin.
Ajouté Migration depuis Emby
- La migration accepte maintenant Emby comme source, en plus de Jellyfin. Elle a été essayée contre un vrai Emby 4.10.2 : films retrouvés par leur chemin, et pour chaque compte, films vus, positions et favoris importés. Un second import ne change rien. L'interface web ne propose encore que Jellyfin ; l'API prend
"source": "emby". - La même série d'essais a validé la migration depuis Jellyfin 12.4 : chaque compte qui a son équivalent dans ProtoFlix récupère ce qu'il a vu, ses positions et ses favoris. Un compte sans équivalent est laissé de côté.
- La migration accepte maintenant Emby comme source, en plus de Jellyfin. Elle a été essayée contre un vrai Emby 4.10.2 : films retrouvés par leur chemin, et pour chaque compte, films vus, positions et favoris importés. Un second import ne change rien. L'interface web ne propose encore que Jellyfin ; l'API prend
Modifié FFmpeg 5.1 suffit : Debian 12
- ProtoFlix fonctionne maintenant avec FFmpeg 5.1, celui de Debian 12, au lieu de 6.1 minimum. Le paquet accepte ce FFmpeg, et la chaîne VAAPI y marche avec le FFmpeg et le pilote Intel de la distribution.
- Avant FFmpeg 6.0, le moteur ne sait pas lire le fichier que le serveur lui ouvre : il le rouvre par
/dev/fd/3, et seuls les formats de fichiers multimédias lui sont permis. Une liste de lecture piégée ne peut donc pas lui faire lire d'autres fichiers. Sous Landlock, le lanceur ne lui permet de relire que ce fichier-là. - Avant FFmpeg 6.1, une conversion ne prend pas d'avance au démarrage : elle travaille aussi vite qu'elle peut, et elle est mise en pause quand elle a trop d'avance sur le lecteur.
- Toute la suite de tests du moteur passe sous FFmpeg 5.1 et 7.1. Le paquet n'a pas encore été installé sur un Debian 12 vierge, et Ubuntu 22.04 (FFmpeg 4.4) reste refusé.
Corrigé Couleurs saturées en HDR sous FFmpeg 7.1
- Sous FFmpeg 7.1, celui de Debian 13, la conversion HDR sans table de tons (HLG, pic du film inconnu, aperçus) rendait certaines couleurs très saturées n'importe comment : un bleu vif sortait presque noir. Ces couleurs sont maintenant ramenées au bord de la gamme avant la dernière étape, comme le faisaient déjà les versions plus récentes. La chaîne ralentit d'environ 15 %.
Ajouté Accélération VAAPI : graphismes Intel et AMD
- Le serveur se sert maintenant de la partie graphique intégrée aux processeurs Intel et AMD, la plus courante sur un serveur domestique, par VAAPI. Elle décode le H.264 et le HEVC (10 bits compris), réduit l'image et l'encode en H.264, presque sans processeur. Les tons HDR restent sur le processeur, comme avec Nvidia, mais la réduction se fait sur la carte avant.
- Au démarrage, chaque carte trouvée dans
/dev/driest essayée sur quelques images. Si un essai échoue, la conversion reste sur le processeur. Il faut le pilote VAAPI de la carte :intel-media-va-driver-non-freepour Intel,mesa-va-driverspour AMD. L'utilisateur du service doit être dans le grouperender, ce que fait déjà le paquet. - Mesuré sur un Intel UHD 750 : six conversions 4K vers 1080p tiennent ensemble le temps réel. La limite est fixée à quatre (
docs/testing/benchmarks/vaapi-intel-uhd750.md). Les Radeon n'ont pas encore été essayées sur du vrai matériel.
Ajouté Docteur de lecture et Accueil des proches
- Deux nouveaux modules intégrés, éteints par défaut, dans Modules > Système (ADR 0040).
- Docteur de lecture : pendant une lecture, Infos puis « Pourquoi ça saccade ? » dit si la lecture est fluide, combien de fois et combien de temps elle a attendu, et d’où vient le problème : réseau trop lent, serveur qui ne convertit pas assez vite, appareil qui peine, accélération matérielle qui a lâché. Chaque constat a son remède, et les raisons du plan de lecture s’y ajoutent. Les lectures en cours et l’historique de l’administration ont aussi leur diagnostic. Allumé, le module garde un résumé des mesures de chaque lecture (débit reçu, réserve, vitesse de conversion, attentes pendant que la conversion était en retard), au plus une écriture par minute.
- Accueil des proches : une invitation se partage avec un QR code et un message prêt à envoyer, sur l’adresse publique du serveur et avec un mot d’accueil, tous deux réglés dans le module. L’invité voit ce mot, puis arrive sur
/bienvenue: il y mesure sa connexion (« la Full HD passe sans souci… ») et suit un guide pour sa TV Android, son téléphone, son ordinateur ou un autre appareil. Le débit mesuré apparaît sous son nom dans la page des comptes. - Serveur :
GET /api/v1/playback/sessions/{id}/diagnosis,GET /api/v1/welcome,POST /api/v1/me/welcome/speed,GET /api/v1/admin/welcome/checks; la consultation d’une invitation ajoutewelcome. Migration 00043 (playback_health,welcome_checks). - La TV et le téléphone n’ont encore ni l’un ni l’autre.
Ajouté Application mobile : musique
- Un onglet « Musique » dans l’application du téléphone, quand le serveur en a : écoutés récemment, listes du compte, albums, artistes. La musique continue écran éteint, avec ses commandes dans la notification, sur l’écran verrouillé et aux boutons du casque ; une barre au-dessus des onglets dit ce qui joue. La recherche trouve aussi les artistes, albums et titres. Construit et vérifié côté serveur, pas encore essayé sur un téléphone.
Ajouté Application mobile : mise à jour depuis le serveur
- L’application du téléphone se met à jour depuis son serveur, comme celle de la TV : le paquet du serveur la porte, un point sur le bouton du compte signale une nouvelle version, « Mettre à jour » la télécharge et Android demande confirmation. Version 0.2.0 de l’application.
- Serveur :
GET /api/v1/clients/android-mobileet/apk;deploy/package/build.shajoute l’APK du téléphone avecPROTOFLIX_MOBILE_APK_DIR. - La version optimisée de l’application se construisait de nouveau mal depuis l’ajout du scanner de codes QR (fragment 1.0 refusé par lint) : corrigé.
Ajouté Application mobile : écrans des modules
- Les modules s’affichent dans l’application du téléphone comme sur la TV et le site : un onglet de la barre du bas, une rangée de l’accueil, une section et un bouton sur la fiche d’un titre. Un module qui ne parle pas des téléphones y montre ce qu’il montre au site ; dans la fiche du module, « Dans les applications » a maintenant une ligne « Téléphones ». Essayé sur le Pixel 9 Pro avec le module de démonstration : compteur, note écrite par formulaire, confirmation avant d’effacer, images du module.
- Serveur : le client
mobiledes surfaces (ADR 0030). - Le lecteur du téléphone a un bouton par module qui parle du moment joué, comme le panneau de la TV. Vérifié par l’API, pas encore sur un téléphone.
Corrigé Pages d’un module après une action
- Après une action, une autre page du même module pouvait s’afficher telle qu’avant pendant son délai de relecture : une note gardée depuis la page « Nouvelle note » n’apparaissait pas tout de suite sur la page principale qui s’ouvrait ensuite. Une action vide maintenant le cache de toutes les pages de son module, sur le site, la TV et le téléphone.
Ajouté Application mobile : connexion par code QR
- Connecter un téléphone sans taper d’adresse ni de mot de passe : sur le web, compte, « Appareils connectés », « Connecter un téléphone » affiche un code QR ; dans l’application, « Scanner un code QR » le lit, et le téléphone se retrouve connecté à ce serveur avec ce compte. Le code vaut 2 minutes et une seule fois ; le web le renouvelle et dit quel téléphone s’est connecté. Un code expiré ou déjà utilisé est refusé avec un message qui dit d’en afficher un nouveau.
- Serveur :
POST /api/v1/me/sign-in-links,GET /api/v1/me/sign-in-links/{id},POST /api/v1/auth/sign-in-links/redeem; codes d’erreursign_in_link_expiredetsign_in_link_used. - Android : le scanner de Google Play services (
play-services-code-scanner), sans permission caméra.
Ajouté Application mobile : hors ligne
- Garder un film ou un épisode sur le téléphone pour le regarder sans réseau : « Télécharger » sur sa page, au choix de la qualité d’origine (le fichier tel quel si le téléphone le lit) ou d’une conversion 1080p, 720p ou 480p, avec la taille prévue. Le téléchargement passe par le gestionnaire d’Android et reprend après une coupure. Les copies sont dans une rangée « Sur l’appareil » de l’accueil ; sans réseau, l’accueil ne montre qu’elles.
- Ce qui est regardé sans réseau rejoint le serveur au retour du réseau : position, épisode vu, historique.
- Serveur :
/api/v1/me/offline(demander, suivre, télécharger avec Range, retirer une copie ; envoyer la progression) et la tâcheoffline.convert. Nouveau droit « Garder des titres sur son téléphone » dans les comptes (web), désactivé par défaut sauf pour les administrateurs. Migration 42. - La barre d’onglets de l’application défile quand les onglets ne tiennent plus.
Ajouté Modules décrits : les écrans, ADR 0037
- Format 2 du graphe : une mise en page par écran, faite de widgets (les blocs de l’ADR 0030) dont les propriétés sont écrites ou liées aux valeurs que donne la logique, et qui se répètent sur une liste. Carte « Donner les valeurs de l’écran ». Les graphes au format 1 ne changent pas.
- Vérifications et moteur : la mise en page est vérifiée comme le graphe, et remplie par le même code que les cartes de blocs. La fiche du relecteur décrit chaque écran.
- Éditeur : onglets Écrans et Logique, comme l’éditeur de widgets d’Unreal. Concepteur avec palette, hiérarchie, écran rendu pour le site ou la TV, détails ; liaisons, répétition, actions ; un clic mène à la logique d’un écran ou crée le point de départ d’une action.
Changé L’éditeur de modules, ergonomie
- En-tête : une action principale (« Essayer », puis « Installer »), « Publier » pour la soumission et l’export, une pastille d’état qui mène à la carte fautive.
- Canevas : grille, zoom, plan du graphe, une forme de carte par rôle, une couleur par famille, des broches typées aux noms français, un rangement qui fait courir les liens de gauche à droite.
- Câbles tirés à la souris ; lâchés dans le vide, ils ouvrent la recherche des cartes qui les acceptent, et la carte choisie arrive reliée. Recherche au clic droit, au double-clic ou avec « / », avec la fiche de la carte à côté.
- Menus au clic droit sur une carte ou une broche ; Ctrl+D, Ctrl+C, Ctrl+V, F, Maj+F, et la liste des raccourcis (?).
- Info-bulles sur les broches ; la fiche complète d’une carte quand on reste dessus : ce qu’elle fait, quand, comment, ses broches, un exemple, le piège. Les 99 cartes, en français et en anglais.
- Panneau de droite réglable en largeur ; l’inspecteur aux couleurs de la carte ; le module en un coup d’œil quand aucune carte n’est choisie ; les commentaires sur les cartes.
- Page des brouillons : chaque brouillon avec le dessin de son graphe, et « Partir d’un exemple » (
GET /admin/blueprints/examples,POST /admin/blueprints/drafts/{id}/start), rangé à l’ouverture.
Ajouté Modules décrits : soumission, ADR 0038 lot 7 et ADR 0039
- Vérification automatique d'un module décrit pour le catalogue communautaire, la même partout : refus, points à regarder, informations ; rien n'est contacté sauf le DNS sur demande ; chaque écran est essayé hors ligne et sa page passe la vérification du serveur.
- Fiche du relecteur en Markdown : ce que le module contacte et pourquoi, ce qu'il montre et garde, sa logique carte par carte, l'essai de ses écrans.
- Éditeur : « Vérifier pour soumettre », avec l'export du module et de sa fiche.
pfrepo reviewpour le relecteur. - Service de soumission
pfsubmit(ADR 0039), pas déployé. Les auteurs s'inscrivent par un lien envoyé par courriel, envoient leur module, suivent la relecture et échangent avec le relecteur ; un module refusé par la vérification automatique ne va pas plus loin. pfrepo communitypour le relecteur : la file, la fiche, le téléchargement vérifié, les décisions et les messages.- Brouillons des conditions des auteurs et de la politique de confidentialité, dans
docs/legal/, à faire relire avant l'ouverture.
Ajouté Modules décrits : écrans et réglages, ADR 0038 lot 6
- Concepteur de réglages : aide, valeur par défaut, bornes, choix, ordre ; avec « Ce que verra l'administrateur », dessiné par les composants de la fiche d'un module.
- Images d'un brouillon (PNG, JPEG ou WebP vérifiés sur leurs octets, 512 Kio, 32 au plus), proposées à la carte « Image du module » et mises dans le paquet. Routes
/admin/blueprints/drafts/{id}/assets. - Aperçu des écrans, web et TV, dans les deux langues : la réponse d'un essai passe par la vérification du serveur (
surfaces.Preview) puis par les blocs du site ; les actions s'y essaient. - La TV n'a pas de rendu dans le site : son aperçu en donne seulement les proportions et la taille du texte.
Ajouté Modules décrits : l'éditeur, ADR 0038 lot 5
- Modules → Créer un module : un éditeur de modules sans code dans l'administration, en SVG et React, sans dépendance. Brouillons gardés par le serveur ; canevas de cartes reliées, palette avec recherche, liens typés, fonctions et variables, annulation, rangement, clavier et lecteurs d'écran.
- Vérification en direct : les broches de chaque carte, la raison d'un refus et la carte en cause, et ce que le module demandera ; les capacités du manifeste suivent le graphe.
- Essai pas à pas d'un événement : chaque carte avec ses valeurs sur le canevas, le journal, les requêtes, la réponse ; les secrets ne sont jamais montrés.
- Installation sur ce serveur comme un fichier non signé, avec l'avertissement d'un module non officiel ; export
.pfmod. - Routes
/api/v1/admin/blueprints: catalogue des cartes, vérification, essai, brouillons, paquet, préparation de l'installation.
Ajouté Modules décrits : réseau, ADR 0038 lot 4
- Cartes Requête HTTP, Lire du XML et Lire un flux RSS ou Atom. L'hôte d'une requête est écrit dans son adresse (
https, un nom public, port 443) ou lu dans le réglage que l'administrateur saisit ; les valeurs des trous sont échappées. Un secret ne va que dans un en-tête ou le corps. - Module d'exemple
x.rss_accueil: un flux RSS dans une rangée de l'accueil et sur une page, fait sans code.
- Cartes Requête HTTP, Lire du XML et Lire un flux RSS ou Atom. L'hôte d'une requête est écrit dans son adresse (
Ajouté Modules décrits : installation, ADR 0038 lot 3
- Un manifeste peut porter
"engine": { "id": "engine.blueprint", "format": 1 }au lieu d'un programme. Le serveur lit alorsgraph.json, recalcule les capacités du graphe et refuse un manifeste qui en déclare d'autres, au chargement, à l'installation et danspfrepo. - Le moteur
engine.blueprints'installe depuis le dépôt officiel comme un module ("kind": "engine"), sans processus propre ; un module décrit le trouve à chaque démarrage, et ses fichiers sont vérifiés avant le lancement. - Les archives de modules peuvent porter
graph.jsonet les imagesassets/; seulbin/est exécutable. deploy/package/dev-modules.shpose aussi un module décrit et le moteur dans le dossier de développement.
- Un manifeste peut porter
Ajouté Modules décrits : moteur, ADR 0038 lot 2
- Moteur officiel des modules décrits,
engine.blueprint(server/modules/blueprint) : il se présente comme moteur, reçoit du serveur le graphe du module, le vérifie de nouveau et sertmodule.configure,module.check,surface.renderetsurface.action, avec ses minuteries. - Interpréteur à budget (
internal/blueprint/engine) : 10 000 cartes par événement, 1,8 s pour une surface, 32 Mio de valeurs, 20 requêtes, 8 appels imbriqués. Un dépassement arrête le fil sans rien écrire et n'est pas rattrapé par « Essayer ». Les valeurs gardées, par personne ou pour le module, sont écrites à la fin d'une exécution réussie, avec un quota. - Le protocole des modules gagne
enginedansmodule.helloetdescribeddans sa réponse. - Le graphe
exemple-surfacesrefaitexemple.surfaces, réponse pour réponse.
- Moteur officiel des modules décrits,
Ajouté Modules décrits : format, ADR 0038 lot 1
- ADR 0038 : une quatrième famille de modules, faits sans code. Un graphe de cartes (
graph.json, format 1) exécuté par un moteur officiel confiné ; capacités déduites du graphe ; budgets ; canaux de distribution et principe de la soumission. api/blueprints/: schéma du graphe, catalogue des 99 cartes de la version 1 (cards.json), exemples, et 25 graphes hostiles refusés avec leur raison (boucles, récursion, secret dans une adresse ou au journal, hôte caché, adresse IP…).internal/blueprint: lecture, vérification et analyse d'un graphe, partagées par le serveur et le moteur.
- ADR 0038 : une quatrième famille de modules, faits sans code. Un graphe de cartes (
Ajouté Notifications, lot 2 : le relais
relay/: le relais de notifications du projet (ADR 0034), un programme Go sans dépendance. Un téléphone y échange son jeton FCM contre une poignée ; un serveur y envoie des notifications chiffrées pour le téléphone et signées par sa clé d'installation ; le relais les passe à FCM sans pouvoir les lire. La première installation qui écrit à une poignée est la seule qui pourra lui écrire. Unitédeploy/systemd/protoflix-relay.service, exploitation dansdocs/operations/push-relay.md.- Serveur :
PUTetDELETE /api/v1/me/devices/current/push(poignée et clé du téléphone, la clé scellée) ; avecPROTOFLIX_PUSH_RELAY, chaque notification part aussitôt aux téléphones concernés, une par sorte et par téléphone toutes les 10 minutes au plus. - Essayé de bout en bout sur ce PC : serveur, relais et faux FCM ; le téléphone ouvre ce que le relais n'a pu lire.
Ajouté Notifications, lot 1
- Serveur : il garde 30 jours ce qu'un compte doit savoir sans regarder (ADR 0034) : alerte du gardien, tâche abandonnée, nouvelle version pour les administrateurs ; fin ou échec de ses téléchargements pour chacun.
GET /api/v1/me/notifications. Une sorte et ses paramètres, jamais une phrase ; le même événement n'est jamais dit deux fois. Migration 41 (39 et 40 sont à la branche des téléchargements). - Application Android : elle demande au serveur ce qui est nouveau toutes les 15 minutes au mieux, sans Google, et l'affiche en notifications système ; un toucher ouvre la page concernée.
- Serveur : il garde 30 jours ce qu'un compte doit savoir sans regarder (ADR 0034) : alerte du gardien, tâche abandonnée, nouvelle version pour les administrateurs ; fin ou échec de ses téléchargements pour chacun.
Ajouté Application mobile : administration
- Onglet « Serveur » pour les administrateurs : alertes du gardien et disques, lectures en cours avec leur plan, mises à jour, bibliothèques à analyser, tâches à relancer ou annuler, comptes et invitations (envoyées par la feuille de partage), appareils à déconnecter. Les gestes qui ne se rattrapent pas demandent confirmation.
- Téléchargements depuis le téléphone : la file du serveur, l'ajout d'un lien ou d'un magnet, pause, reprise, retrait ; « Partager » un lien vers ProtoFlix depuis une autre application.
- Serveur :
DELETE /api/v1/admin/sessions/{id}arrête la lecture de quelqu'un. Son lecteur reçoitsession_stoppedet s'arrête au lieu d'ouvrir une nouvelle session ; la TV et le mobile le respectent.
Corrigé Son en avance après un saut
- Dans Chrome, après un saut ou une reprise en cours d'épisode, le son pouvait partir jusqu'à 10 s en avance sur l'image quand la vidéo était copiée et le son converti (AC-3 en AAC, par exemple). La vidéo copiée repart de l'image clé précédente, le son du point demandé, et FFmpeg mettait cet écart dans une liste d'édition que Chrome ignore. Les morceaux portent maintenant l'écart dans leurs propres horodatages (
use_editlist=0). Trouvé par la session web sur une vraie lecture de Lost. Ce premier correctif ne suffisait pas : sans liste d'édition, FFmpeg étirait le premier échantillon de son sur tout l'écart, et Chrome, qui compte les échantillons, jouait encore le son en avance. Le son converti repart désormais de la même image clé que la vidéo (-noaccurate_seek), il n'y a donc plus d'écart du tout. Trouvé par la session TV sur Interstellar (6,5 s d'avance). Restait un petit écart, jusqu'à quelques centièmes de seconde selon l'entrelacement du fichier (60 ms d'avance mesurés sur Interstellar) : le son est maintenant coupé ou complété de silence à l'échantillon près pour partir exactement avec l'image (-copyts,aresample), et le décalage annoncé au client est l'instant de décodage de l'image clé.
- Dans Chrome, après un saut ou une reprise en cours d'épisode, le son pouvait partir jusqu'à 10 s en avance sur l'image quand la vidéo était copiée et le son converti (AC-3 en AAC, par exemple). La vidéo copiée repart de l'image clé précédente, le son du point demandé, et FFmpeg mettait cet écart dans une liste d'édition que Chrome ignore. Les morceaux portent maintenant l'écart dans leurs propres horodatages (
Ajouté Disques lents : reconnaissance et lecture anticipée
- Le serveur reconnaît le disque de chaque source : SSD, disque mécanique, USB ou partage réseau. L'API le donne dans
disk(ADR 0029). - Sur un disque lent, ouvrir la fiche d'un film ou d'une série réveille le disque en arrière-plan, pendant qu'on lit le résumé.
- Lecture anticipée sur les disques lents : un seul fil par disque lit par blocs de 16 Mio devant chaque lecture directe et chaque conversion, en priorité disque basse. Le disque fait de longues lectures au lieu de sauter d'un fichier à l'autre. 256 Mio de mémoire au plus en tout, réglable par
PROTOFLIX_READAHEAD_MIB(0l'arrête). - Pas encore mesuré sur un vrai disque mécanique ou USB : c'est l'étape suivante, avant le tampon sur le SSD.
- Le serveur reconnaît le disque de chaque source : SSD, disque mécanique, USB ou partage réseau. L'API le donne dans
Ajouté Application mobile : lecture
- Lecture sur Android : reprise où l'on s'était arrêté ou depuis le début, épisodes, paysage plein écran, commandes au toucher (±10 s, double toucher, barre de lecture), son et sous-titres, « À propos de cette lecture » avec le mode et les raisons du serveur, épisode suivant, image dans l'image en quittant l'application.
- Serveur : profil
android-mobile@1, les règles du lecteur Media3 de la TV sous un nom à lui. apps/core: la logique de lecture commune (Playback) sur une interface de lecteur (MediaPlayer), avecMedia3Playeret la détection des décodeurs (DeviceCaps, venue de la TV) pour Android. La TV garde pour l'instant son propre contrôleur.- Essayé sur un Pixel 9 Pro : HEVC 10 bits en Matroska lu tel quel, MPEG-2 converti avec ses raisons ; APK optimisé de 2,3 Mo, démarrage à froid en 243 ms.
Ajouté Application mobile, Android
apps/mobile(écrans en Compose Multiplatform, pour Android puis iOS) etapps/mobile-android(l'application Android) : choix du serveur, avec les serveurs du réseau trouvés par mDNS ; connexion par mot de passe ou par un code saisi sur la page/appareildu site ; accueil (titre mis en avant, Reprendre, films et séries récents, Ma liste) ; Films et Séries en grilles qui se chargent au défilement ; fiche avec saisons, épisodes et distribution ; recherche au fil de la frappe. Les jetons, la police et les icônes sont ceux du web ; le français fait foi. La lecture n'est pas encore là (étape 4 dedocs/mobile/plan.md).- Essayée sur un Pixel 9 Pro contre un serveur local jetable : APK optimisé de 1,6 Mo, démarrage à froid en 363 ms.
- La recherche des serveurs sur le réseau passe de la TV à
core, pour les deux applications.
Modifié Code partagé des applications
apps/core: module Kotlin Multiplatform (Android, iOS, et Windows natif pour les tests) qui porte les formes de l'API, son client, les surfaces de modules, le choix des pistes et WebVTT. La TV s'en sert ; l'application mobile s'en servira. Le client d'API ne dépend plus d'OkHttp : chaque plateforme lui donne son transport, et il dit au serveur quel client il est (tv, plus tardmobile).- TV : rien ne change à l'écran. Mêmes 53 tests (22 passés dans
core), plus 6 sur le client d'API ; le profil de référence couvre aussicore.
Modifié Applications natives
android-tv/devientapps/, un projet Gradle qui accueillera aussi le code commun et l'application mobile (ADR 0033, ADR 0034 pour les notifications). L'application TV y est le module:tv: même APK à l'octet près en taille, mêmes 53 tests. Le paquet prend désormaistv-release.apk(PROTOFLIX_TV_APK_DIR=apps/tv/build/outputs/apk/release).
Corrigé Surfaces
- Le direct demande de relire la page quand une ligne part après une action (oublier un téléchargement) : la page gardée était effacée avec le cache, et rien ne permettait plus de voir le changement.
- Le contrat dit que la route des actions demande
client(et accepteblocks), comme le serveur l'exige.
Ajouté Surfaces, blocs version 2 servis
- Le serveur sert la version 2 des blocs : en-tête, grande carte, onglets, recherche, champ d'une ligne, courbe, et dans les lignes leurs actions, leurs détails et une affiche. Il retire ce qu'un client ne doit pas voir (un bloc réservé au site, ce qu'une app de version 1 ne sait pas dessiner) et vérifie les nouvelles règles : une action destructive pose sa question, l'id d'un élément en direct est unique.
- Le direct :
GET /surfaces/{module}/{surface}/liverend l'état des éléments en direct, relu au plus toutes les 2 s pour tous les écrans, et demande de relire la page quand une ligne arrive ou part. - Un fichier (un
.torrent) peut accompagner une action : 2 Mio au plus, corps de 3 Mio ; 30 actions par minute et par compte. - Une œuvre nommée par un module s'affiche avec son affiche ou son image de fond, si le compte peut la voir.
- Les surfaces parlent la langue du compte, sinon celle du serveur : la page Téléchargements n'est plus en anglais sur le site.
- La page Téléchargements des surfaces passe en version 2, avec pause, reprise, annulation, relance et « tout mettre en pause » ; elle est désactivée par défaut partout, le site gardant sa propre page.
Modifié - Les images des modules sont servies sous
/api/v1/surface-assets/{module}/{fichier}: l'ancienne adresse se confondait avec le direct d'une surface nomméeassets.
- Les images des modules sont servies sous
Ajouté Gardien de la bibliothèque, ADR 0032
- Le gardien de la bibliothèque, intégré au serveur. Il calcule le SHA-256 de chaque fichier en tâche de fond (
guardian.checksum, chaque heure), à 25 Mio/s au plus (PROTOFLIX_GUARDIAN_RATE_MIB,0l'arrête), en priorité d'entrées-sortiesidleet nice 19 sous Linux, sans chasser du cache ce que l'on regarde. Il se met en pause pendant une lecture, une conversion ou une chaîne TV. Chaque fichier est relu tous les 90 jours (PROTOFLIX_GUARDIAN_VERIFY_DAYS). - Un fichier dont la taille ou la date change est « remplacé » : nouvelle référence, sans alerte. Même taille, même date et un autre contenu, relu deux fois : « corrompu », alerte grave et ligne
WARNau journal. Si Linux montre une écriture (ctime), le fichier est « réécrit », un simple avertissement. Un fichier illisible, ou deux lectures qui diffèrent, déclenchent aussi une alerte. - La santé des disques, toutes les 10 minutes (
guardian.disks), sans droits root. Il relie chaque source et les données du serveur à leur disque par/proc/self/mountinfo,/sys/blocket/dev/disk/by-id(partitions, LVM, RAID logiciel). Il surveille la place libre, l'absence, la lecture seule, les erreurs d'entrée-sortie et SMART. Les rapports SMART sont déposés par un minuteur root optionnel (deploy/smart/,PROTOFLIX_SMART_DIR) : le serveur ne lance jamaissmartctl. - Ce qu'on perdrait si un disque mourait : œuvres perdues, œuvres qui perdraient une version, œuvres qui ont une copie ailleurs (même version ou même SHA-256), fichiers hors catalogue. Un volume RAID 1, 5, 6 ou 10 ne fait rien perdre. Le lien entre source et disque reste en base : un disque absent dit encore ce qu'il portait.
- Routes
GET /admin/guardian,GET /admin/guardian/disks/{id}/loss,GET /admin/guardian/files,POST /admin/guardian/verify,POST /admin/guardian/files/{id}/accept,POST /admin/guardian/alerts/{id}/acknowledge, etGET /admin/guardian/sources/{id}/sha256sumsau format desha256sum -c. Événementguardian.updated(administrateurs). Migration00038_guardian.sql. - Web : page Gestion › Serveur › Gardien de la bibliothèque (
/admin/serveur/gardien), ouverte depuis la page Serveur et la recherche de la console. Elle donne l'état en une phrase, les alertes avec ce qu'il faut faire, les sommes de contrôle et les disques. Pas de route ni d'entrée à elle dans le rail : le premier chargement est à 24 octets de son budget.
- Le gardien de la bibliothèque, intégré au serveur. Il calcule le SHA-256 de chaque fichier en tâche de fond (
Ajouté Migration depuis Jellyfin, ADR 0031
- ADR 0031 : comment ProtoFlix reprend un foyer venu de Jellyfin, Emby ou Plex. Il dit ce qu'on reprend et ce qu'on ne reprend pas, comment on lit chaque source (API ou base hors ligne, formats vérifiés), comment on fait correspondre fichiers et œuvres, comment l'administrateur conduit l'opération, et pourquoi l'outil est intégré au serveur.
- Page
/admin/migration« Venir de Jellyfin », ouverte depuis la page Bibliothèques : un aperçu à blanc, puis l'import.- Ce qu'on reprend : pour chaque utilisateur de Jellyfin rattaché à un compte ProtoFlix, ce qu'il a vu (avec la date, dans l'historique), où il en est et ses favoris, qui vont dans « Ma liste ».
- Ce qu'on ne touche pas : Jellyfin ne reçoit que des requêtes de lecture. Un état plus récent dans ProtoFlix est gardé. Relancer l'import n'écrit rien deux fois.
- Correspondance : par le chemin du fichier, après réécriture des dossiers (proposée d'elle-même quand le nom du dossier est le même), puis par les identifiants TMDB, IMDb ou TVDB, puis par un nom de fichier unique. La page liste ce qui n'a pas trouvé de correspondance.
- API
POST /api/v1/admin/migration/previewetPOST /api/v1/admin/migration/import(administrateurs seulement). La clé d'API de Jellyfin vient avec chaque requête : elle n'est jamais conservée. Nouveaux codes d'erreur :source_unauthorized,source_forbidden,source_unreachable,source_unexpected,source_not_supported,migration_running. L'import est inscrit au journal d'audit. - Pas encore : Emby (lecteur écrit, à essayer sur un vrai serveur), Plex, la création des comptes et des bibliothèques, les listes de lecture, les collections et les métadonnées verrouillées. Essayé seulement contre un faux Jellyfin, pas encore contre celui du Pixel.
Ajouté Blocs des surfaces, version 2, ADR 0030
- Le contrat de la version 2 des blocs, pour des surfaces aussi riches qu'une page faite main : en-tête, grande carte, onglets, recherche, champ d'une ligne (avec envoi de fichier sur le site), courbe ; dans les lignes et les cartes, leurs actions, leurs détails, une affiche ; des blocs réservés à un client ; le direct par
GET /surfaces/{module}/{surface}/live. Exemples partagés :downloads-v2.json,search.json,live.json. Pas encore servi. - App TV : la version 2 des blocs, annoncée par
blocks=2.- En-tête, grande carte, onglets, courbe.
- Recherche : le clavier de la télécommande, les résultats à côté.
- Lignes et cartes : détails, affiche, texte de progression, panneau d'actions.
- Direct : relecture par
/live, changements en place. - Les blocs réservés au site sont écartés.
- Les tests lisent les trois nouveaux exemples. Pas encore essayé sur la TV, faute d'un serveur qui serve la version 2.
- Le contrat de la version 2 des blocs, pour des surfaces aussi riches qu'une page faite main : en-tête, grande carte, onglets, recherche, champ d'une ligne (avec envoi de fichier sur le site), courbe ; dans les lignes et les cartes, leurs actions, leurs détails, une affiche ; des blocs réservés à un client ; le direct par
Ajouté Surfaces : comptes supprimés
- Un compte supprimé est oublié par les modules : son pseudonyme rejoint la liste d'attente de chaque module qui en a, et le module la reçoit par
subject.forget, à son démarrage ou dès son prochain appel de surface. Le module de démonstration efface alors les notes de la personne.
- Un compte supprimé est oublié par les modules : son pseudonyme rejoint la liste d'attente de chaque module qui en a, et le module la reçoit par
Ajouté Surfaces des modules, ADR 0030
- Le cœur des surfaces :
/surfaces, une surface (avecETagetrefresh_s), ses actions, les images des modules, et/admin/surfacespour choisir, surface par surface et client par client, ce qui s'affiche et pour qui. Ce qu'un module rend est vérifié contre le vocabulaire avant d'atteindre un client : texte coupé, listes bornées, aucune adresse extérieure ni champ inconnu ; une réponse lente, fausse ou absente devient sa dernière réponse valide, ou un avertissement. Un module ne reçoit qu'un pseudonyme du compte. Événementsurface.updated. - Première surface : la page Téléchargements (les siens, ou tous les comptes pour un administrateur, en cours et 30 jours d'historique). Affichée sur le site, désactivée sur la TV tant que l'administrateur ne l'active pas.
- Le cœur des surfaces :
Ajouté Surfaces des modules externes, ADR 0030
- Un module externe peut déclarer des
surfacesdans son manifeste : leur emplacement, leurs clients par défaut, leur public, leur fraîcheur, leurs libellésfr/enet leur icône. Le serveur l'interroge parsurface.renderetsurface.action, avec 2 s au plus, 256 Kio pour une page et 64 Kio pour une action. - Le module ne reçoit jamais le compte :
subjectest un pseudonyme propre à lui (HMAC avec une clé par module, scellée, effacée par la purge). - Ses images viennent du dossier
assets/de son paquet, signé avec lui : PNG, JPEG ou WebP vérifiés sur leurs octets, 512 Kio au plus. - Module de démonstration
exemple.surfaces, qui utilise chaque bloc et chaque emplacement, etdeploy/package/dev-modules.shpour le poser dans un dossier de développement.
- Un module externe peut déclarer des
Ajouté Contrat des surfaces, ADR 0030
- Le vocabulaire des blocs que les modules affichent dans la TV et le site :
api/surfaces/schema.json(version 1), avec ses exemples partagés par le serveur, le site et la TV (api/surfaces/examples/). Les routes/surfaces,/surfaces/{module}/{surface}, ses actions, et/admin/surfacessont au contrat, pas encore servies.
- Le vocabulaire des blocs que les modules affichent dans la TV et le site :
Ajouté Sous-titres : épisodes, nettoyage, langues
- Sur la fiche d'une série, chercher et ajouter des sous-titres pour l'épisode choisi.
- Les sous-titres gardés d'un fichier qui a quitté les bibliothèques sont retirés une fois par jour : fichier disparu de la base, ou supprimé depuis 30 jours.
- Module OpenSubtitles 1.1.1 : ses refus portent leur cause.
- Les refus du service de sous-titres ont leur code :
subtitles_quotaetsubtitles_busy(429, avecRetry-After),subtitles_login(422). Le web les écrit dans la langue du compte. Le protocole des modules gagnereasonetretry_aftersur une erreur ; un serveur plus ancien garde le texte du module.
Ajouté Photos HEIC
- « Ma bibliothèque » lit aussi la date, l'appareil et le lieu des photos HEIC, comme ceux des JPEG.
Retiré Contrat
GET/PUT /admin/downloads/settings, jamais servies : ces réglages sont ceux du module Téléchargements et du module BitTorrent.
Modifié Modules : publication et offre gratuite d'OpenSubtitles
- qBittorrent et Transmission sont publiés sur le dépôt officiel
modules.klarvi.fr, signés depuis le code actuel. - Module OpenSubtitles 1.1.0, réglé sur l'offre gratuite. Il envoie au plus 4 requêtes par seconde (le service en permet 5 par adresse IP) et réessaie une fois quand le service répond « trop de demandes ». Il ne se reconnecte pas tant que le compte réglé ne change pas.
- Les téléchargements restants du jour s'affichent après une recherche et après un ajout : 5 sans compte, 20 avec un compte gratuit. Le champ
quotade l'API les donne avec l'heure du renouvellement. Une fois le quota épuisé, le message donne cette heure et conseille un compte. - Un résultat déjà ajouté pour un fichier est marqué
savedet refusé avant d'être téléchargé : chaque téléchargement compte dans le quota. - Mentions légales du dépôt : texte prêt dans
docs/operations/mentions-legales-depot.md, sans l'identité de l'éditeur, à remplir avant publication sur le site vitrine.
- qBittorrent et Transmission sont publiés sur le dépôt officiel
Modifié Fonctions du serveur, ADR 0022
- Les mises à jour, TMDB et MusicBrainz ne sont plus des modules du catalogue, mais des fonctions du serveur, réglées là où on s'en sert :
PATCH /admin/updates(etfeaturedans sa réponse),GET /admin/metadata-sourcesetPATCH /admin/metadata-sources/{id}. Leurs garanties ne changent pas : désactivées jusqu'au oui de l'administrateur, hôtes contactés affichés, clé chiffrée. Les réglages existants sont gardés tels quels, sans migration./admin/moduleset/modulesne les listent plus.
- Les mises à jour, TMDB et MusicBrainz ne sont plus des modules du catalogue, mais des fonctions du serveur, réglées là où on s'en sert :
Sécurité Service média, ADR 0028
- Sans Landlock, FFmpeg peut tourner sous un compte à part :
protoflix media-service, avecPROTOFLIX_MEDIA_SERVICE. Le serveur ne lui passe que des descripteurs (le fichier, le dossier de la tâche, les sorties). Ce compte n'a ni la base, ni la clé, ni la bibliothèque, ni le réseau. Unitédeploy/systemd/protoflix-media.service, à activer à la main.
- Sans Landlock, FFmpeg peut tourner sous un compte à part :
Corrigé - Les essais matériels du démarrage écrivent dans leur propre dossier par noms relatifs.
- Le dossier temporaire des moteurs est propre à chaque processus.
Ajouté Module BitTorrent
- Le module
downloads.bittorrent, à installer et désactivé par défaut, récupère les liens magnet sans service de débridage, dans un processus confiné. Seuls les fichiers audio et vidéo sont pris, puis relus par le serveur. Par défaut, aucun envoi aux autres participants, aucun port entrant, aucune adresse du réseau local et aucun partage une fois le fichier arrivé.
- Le module
Sécurité FFmpeg isolé, ADR 0028
- FFmpeg et ffprobe passent par le lanceur confiné du serveur : ni base, ni clé, ni réseau pour un fichier, et seul le dossier de la tâche en écriture. Sans Landlock, comme sur le Pixel 6, le filtre reste mais les fichiers du compte restent lisibles : le journal le dit au démarrage.
PROTOFLIX_ISOLATE_MEDIA=falsele coupe.
- FFmpeg et ffprobe passent par le lanceur confiné du serveur : ni base, ni clé, ni réseau pour un fichier, et seul le dossier de la tâche en écriture. Sans Landlock, comme sur le Pixel 6, le filtre reste mais les fichiers du compte restent lisibles : le journal le dit au démarrage.
Ajouté Photos de « Ma bibliothèque »
- L'envoi accepte JPEG, PNG, GIF, WebP et HEIC.
/api/v1/me/library/photosles liste par date de prise de vue et sert le fichier et ses vignettes. Date, appareil et lieu sont lus dans le fichier et montrés à son propriétaire seul ; les vignettes ne gardent aucune métadonnée.
- L'envoi accepte JPEG, PNG, GIF, WebP et HEIC.
Ajouté MusicBrainz
- Le module « MusicBrainz », désactivé par défaut, retrouve une pochette et une année pour les albums dont les fichiers n'en disent rien. Ce que disent les fichiers reste prioritaire, un album au nom douteux est laissé tel quel, et la musique de « Ma bibliothèque » n'est jamais envoyée.
Ajouté Listes de lecture
/api/v1/music/playlists: chaque compte crée ses listes, y ajoute des pistes, y compris de son espace privé, les ordonne et les renomme. Nul autre compte n'y a accès, administrateur compris. Une piste dont le droit a été retiré disparaît de la vue sans laisser de trace.
Ajouté Modules, lot 8
- Module OpenSubtitles : chercher des sous-titres pour un film ou un épisode depuis sa fiche, puis les ajouter. Ils sont gardés par le serveur, hors des bibliothèques, et proposés à tous à la lecture. Réservé aux administrateurs et aux comptes qui peuvent télécharger.
Ajouté Modules, lot 7
- Modules qBittorrent et Transmission : un magnet est confié au client de l'administrateur, puis ses fichiers audio et vidéo terminés sont copiés dans la bibliothèque choisie. Le serveur ne rejoint toujours pas le réseau pair-à-pair.
- Module de recherche :
POST /api/v1/downloads/searchet une recherche sur la page des téléchargements, à travers les indexeurs Torznab que l'administrateur ajoute. Aucun n'est fourni. - Capacité
network_configured: un module ne joint que les adresses saisies par l'administrateur, réseau local compris.
Modifié Modules, lot 5
- Mega-Debrid devient un module à installer, signé et confiné, et quitte le binaire du serveur. Un compte déjà relié le reste, mais il faut installer puis activer le module. Sans lui, les liens d'hébergeurs et les torrents sont refusés, et les liens directs fonctionnent.
- Le module « Mises à jour » couvre aussi les modules : recherche quotidienne et, en automatique, installation aux heures réglées des versions officielles qui ne demandent aucun nouveau droit.
- Le serveur connaît le dépôt officiel,
https://modules.klarvi.fr, et sa clé racine. Il ne le contacte que sur demande de l'administrateur, ou si le module « Mises à jour » est activé.
Ajouté Suppression de compte
DELETE /api/v1/accounts/{id}supprime un compte et tout ce qu'il possède, espace privé compris, après confirmation. Désactiver un compte reste le moyen de tout garder.PROTOFLIX_PRIVATE_MAX_GIBplafonne l'ensemble des espaces privés.
Corrigé - Supprimer une bibliothèque efface aussi ses titres de l'index de recherche.
Modifié App Android TV : mise en scène
- Ouverture des films et des chaînes reprise du site : rideau, logo qui fait sa mise au point, ligne de chargement, et une image déjà à sa forme quand le rideau se lève. Le symbole de lecture a disparu. Un épisode montre le logo de sa série, son nom, sa saison et son numéro.
- Écran de pause : titre, résumé, temps restant et heure de fin.
- Page TV refaite : le programme en grand, bande « en ce moment », thèmes, numéro de chaîne tapé à la télécommande, ici et dans le lecteur.
- Nouvel effet « Mise en scène », actif en Cinéma. Le préréglage Léger garde une ouverture sobre, sans animation.
- Un titre ajouté au serveur apparaît seul sur l'accueil et dans les grilles, sans déplacer le curseur.
- Qualité automatique : l'app mesure son débit et applique le conseil du serveur. Une qualité choisie à la main n'est jamais touchée.
- Bande-annonce sur la fiche : un fichier gardé avec le film se lit dans l'app, une vidéo YouTube s'ouvre dans l'app YouTube.
- Fiche : l'épisode sous la télécommande montre son image, sa saison, son numéro et son résumé ; la distribution en photos, la saga et le même genre suivent. Une personne ouvre ce qu'elle a fait.
- Recherche : les ajouts récents avant la première lettre.
- Sous-titres en ligne depuis le lecteur, pour un administrateur ou un compte qui peut télécharger : ceux faits pour ce fichier d'abord, gardés par le serveur et affichés aussitôt.
- Surfaces des modules sur la TV (ADR 0030) : pages dans le rail, étages de l'accueil, sections et boutons de la fiche, lignes du lecteur, dessinées à partir des blocs du contrat ; un module qui s'en tient à eux apparaît sans nouvelle version de l'app.
- L'app TV suit les modules actifs du serveur : TV en direct, enregistrements et sous-titres en ligne n'apparaissent que si leur module tourne, et suivent un changement en moins d'une minute.
- Historique dans Ma liste, et listes de lecture de musique.
- Musique sur la TV : écoutés dernièrement, albums, pistes et lecture en cours, une session par piste comme pour un film. La musique continue pendant qu'on parcourt l'app, derrière l'économiseur d'écran ; pages d'artiste ; artistes, albums et pistes dans la recherche.
- Enregistrements de la box dans la TV en direct, quand l'administrateur les a activés : du plus récent au plus ancien, lus en plein écran avec avance et recul. Les bandes-annonces gardées avec le film passent par le même lecteur, qui gagne une barre de temps.
- Ma bibliothèque sur la TV : les vidéos et les photos de l'espace privé du compte, les photos par mois, en plein écran et en diaporama.
- Fin d'épisode : au générique, une carte propose le suivant avec un anneau de compte à rebours, ou de rester pour le générique. Fin d'un film : « Revoir » ou « Retour à la fiche », au lieu d'un retour sans prévenir.
- Mises à jour de l'app depuis son serveur :
GET /api/v1/clients/android-tvet son fichier, portés par le paquet à côté de l'interface web. La TV propose la version plus récente dans Réglages › À propos, un appui puis la confirmation d'Android. L'app est signée avec sa clé définitive : passer de l'ancienne version demande une désinstallation, une seule fois.
Ajouté Téléchargements vers « Ma bibliothèque »
POST /api/v1/downloadsacceptedestination: "private": le fichier arrive dans l'espace du compte, compte dans son quota et reste invisible des autres, administrateur compris.
Ajouté Mises à jour, ADR 0027
- Le module « Mises à jour », désactivé par défaut, cherche chaque jour une version signée du serveur et de son interface web. Elle s'installe en un clic (
POST /api/v1/admin/updates/apply) ou seule la nuit, attend la fin des lectures, et revient à la version précédente, base comprise, si la nouvelle ne répond pas. protoflix-releasesigne les versions publiées. Sans clé dans le binaire, ou dans une image Docker, le module explique pourquoi il ne peut rien faire.
- Le module « Mises à jour », désactivé par défaut, cherche chaque jour une version signée du serveur et de son interface web. Elle s'installe en un clic (
Ajouté Bandes-annonces
- La fiche d'un film ou d'une série remplit enfin
trailers: les fichiers de la bibliothèque (Dune-trailer.mp4, dossiertrailers/), servis avec les droits de l'œuvre, et les vidéos YouTube connues de TMDB, triées selon les langues du spectateur. - Le module TMDB gagne le réglage « Bandes-annonces YouTube », actif par défaut. Le serveur ne contacte jamais YouTube : c'est le client qui le fait, après l'accord du spectateur.
- La fiche d'un film ou d'une série remplit enfin
Ajouté Ma bibliothèque, ADR 0018
- Chaque compte qui a un quota peut envoyer ses vidéos et sa musique : envoi reprenable après une coupure, quota et place vérifiés avant le premier octet, type réel vérifié à la fin.
GET /api/v1/me/library,/me/library/uploads,DELETE /me/library/items/{id}. Pas de photos pour l'instant. - Nul autre compte n'y a accès, administrateur compris : il voit « Contenu privé » dans les lectures. L'espace reste hors de l'accueil et de la recherche de son propriétaire tant qu'il ne le demande pas.
- Chaque compte qui a un quota peut envoyer ses vidéos et sa musique : envoi reprenable après une coupure, quota et place vérifiés avant le premier octet, type réel vérifié à la fin.
Ajouté Installer des modules, ADR 0024
- L'administration installe, met à jour et retire des modules externes, depuis un dépôt signé ou depuis un fichier :
/api/v1/admin/module-store, écran « Installer des modules », etprotoflix module installserveur arrêté. Aucun dépôt n'est contacté sans demande de l'administrateur. - Chaque installation montre d'abord ce que le module pourra faire, et ce qu'une mise à jour demande de plus. Une mise à jour qui échoue à son contrôle revient seule à la version précédente, données comprises ;
POST /api/v1/admin/modules/{id}/rollbacky revient à la demande. - Les modules hors du dépôt officiel, dépôts tiers ou fichiers sans signature, sont possibles après acceptation du risque. Leur identifiant commence par
x., et ils portent la mention « Non officiel ». cmd/pfreposigne et publie un dépôt (guide :docs/operations/module-repository.md). Le dépôt officiel n'existe pas encore : aucune clé officielle n'est livrée, donc aucun module n'est officiel.- Unité systemd : les appels Landlock sont autorisés et
PrivateIPCactivé. Compose :init: true.
- L'administration installe, met à jour et retire des modules externes, depuis un dépôt signé ou depuis un fichier :
Corrigé Modules
- Couper puis rallumer aussitôt un module externe l'affichait à tort en erreur : le serveur interrogeait encore l'ancien processus.
Ajouté Modules externes, ADR 0024
- Un module peut tourner comme un programme séparé et confiné : il parle au serveur par un protocole décrit dans
docs/api/module-protocol.md, et n'atteint le réseau que par des hôtes déclarés. Pour l'instant, ces modules se chargent seulement depuisPROTOFLIX_MODULES_DEV_DIR, sans signature, pour en développer. Le téléchargement et les mises à jour restent à faire. - Le catalogue donne des avis par module (
notices), affichés sur sa fiche : module de développement, et machine sans Landlock, où le module peut lire et modifier les fichiers du compte du serveur.
- Un module peut tourner comme un programme séparé et confiné : il parle au serveur par un protocole décrit dans
Ajouté Modules
- La TV entre dans le catalogue de modules :
livetv.freeboxetlivetv.iptv, désactivés sur un serveur neuf. Un serveur qui a déjà une Freebox ou une liste les garde activés à la mise à jour. Désactivée, une source n'a plus ni flux ni chaînes, et ne contacte plus rien ; ses données restent. POST /api/v1/admin/modules/{id}/purgeefface les données et les réglages d'un module désactivé, avec confirmation et ligne d'audit. Les bibliothèques ne sont jamais touchées.
- La TV entre dans le catalogue de modules :
Ajouté Qualité automatique pendant la lecture, ADR 0026
- En qualité
auto, le signal de lecture acceptethroughput_bpsetbuffer_mset peut répondreadapt: le client rouvre une session sous la nouvelle limite. Descente immédiate, remontée lente, de plus en plus lente après chaque échec. Une qualité choisie à la main ne change jamais. - Une limite de débit baisse aussi la définition : 720p sous 6,4 Mb/s, 480p sous 3,2, 360p sous 1,6.
- En qualité
Ajouté Musique, ADR 0025
- Une bibliothèque de musique est lue : étiquettes des fichiers, sinon chemin
Artiste/Album (année)/01 - Titre.flac; albums, artistes, pistes, compilations, pochettes du dossier ou du fichier. API/api/v1/music/*. - Lecture directe des formats que lit le client (MP3, FLAC, AAC, Opus, Vorbis, WAV), sinon conversion en AAC. Une piste se lance par la session de lecture habituelle.
- Tous les fichiers sont réanalysés une fois (
ParserVersion5). La migration reconstruitmedia_items: une sauvegarde est prise avant.
- Une bibliothèque de musique est lue : étiquettes des fichiers, sinon chemin
Sécurité Revue complète, `docs/security/review-2026-11-07.md`
- Une requête transférée par un proxy non déclaré, ou par un proxy déclaré qui ne nomme pas son client, compte comme distante : un inconnu ne peut plus créer le premier administrateur par ce biais. Toutes les lignes de
X-Forwarded-Forcomptent. - Code rapide et connexion : les tentatives d'une rafale sont comptées avant la vérification. Un inconnu ne bloque plus le propriétaire d'un compte (limite par adresse et compte, plafond de 50 par compte seul). Changer de mot de passe supprime les codes rapides.
- Les jetons de lecture cessent avec le compte, l'appareil ou les droits. Un compte tient 2 conversions au plus : la plus ancienne du même appareil cède sa place.
- TV : 8 flux en tout, 30 démarrages par minute et par compte ; logos jugés sur leurs octets ; un guide nommé par une liste ne vise plus le réseau local.
PROTOFLIX_TRANSCODE_DIRn'efface plus que les dossiers de session, et ne peut plus contenir les données.- Créer le premier administrateur demande un code écrit dans les journaux du serveur (
setup_token,PROTOFLIX_SETUP_TOKENpour le fixer). - Une session ouverte par code rapide n'administre pas avant d'avoir redonné le mot de passe (
POST /api/v1/auth/confirm-password,admin_password_required). - Droit
live_tv_allowedpar compte, désactivé pour les enfants, y compris les comptes existants. - Effacer son historique efface aussi les lectures terminées que voit l'administrateur.
- CSP sur l'interface web et les images TV. Base en mode 0600. Aperçus, étiquettes de fichiers, cache de logos et guide bornés. Flux d'événements : droits relus toutes les 25 s. Un compte enfant a toujours une limite d'âge.
- Une requête transférée par un proxy non déclaré, ou par un proxy déclaré qui ne nomme pas son client, compte comme distante : un inconnu ne peut plus créer le premier administrateur par ce biais. Toutes les lignes de
Ajouté Client Android TV
android-tv/: client natif pour la télécommande (Kotlin, Compose, Media3). Accueil « Les étages », fiche, grilles, recherche, TV en direct, lecteur, plan de lecture expliqué, réglages d'effets, français et anglais. Plans et mesures dansdocs/tv/, décision dans l'ADR 0023.- Lecteur de la TV en direct : programme, horaires, zapping, liste des chaînes, pause et retour au direct, comme sur le web.
- Récap d'un épisode (
recap, migration 30) : un marqueur de plus, trouvé dans les sous-titres complets du fichier quand ils annoncent « Précédemment dans… ». Bouton sur la TV ; l'API le donne déjà au web, qui ne l'affiche pas encore. - Client TV, V1.1 : connexion par code ou QR sans mot de passe, serveur trouvé tout seul sur le réseau, guide des programmes, langues modifiables, rangée « Reprendre » sur l'accueil Android.
- Serveur : connexion d'un appareil par un code affiché dessus (
/api/v1/auth/pairings,/api/v1/me/pairings, page/appareil). Annonce mDNS sur les réseaux privés (PROTOFLIX_DISCOVERY=offpour la couper). - Accueil TV plus régulier : plus d'image 4K décodée et envoyée d'un bloc au GPU à chaque titre, une seule bande réutilisée d'un étage à l'autre et défilée par calque, préchargement sans décodage. Pire blocage du fil principal de 99 à 33-49 ms, fils de fond de 9,6 à 1,4 s sur 16 s de parcours. Le compteur
gfxinforeste à environ 20 %, comme Jellyfin sur la même TV : la cible de 5 % n'est pas atteinte. - Serveur : profil de lecture
androidtv@1. Le lecteur natif ouvre le Matroska et l'audio d'origine : l'application le restreint à ce que la TV déclare. Un lecteur natif choisit lui-même sa piste audio dans le fichier : changer de langue ne demande aucune conversion (SelectsAudio). - TV en direct : le flux est demandé à la Freebox à son adresse locale quand la passerelle de la machine est bien la box. Par son nom, la box envoie l'image depuis une adresse publique, qu'un pare-feu limité au réseau local refuse : aucune image n'arrivait (
tv_stream_no_data).
Corrigé Recherche
- Une recherche de deux lettres renvoyait une erreur 500 (
bm25dans une requête aplatie par SQLite), web compris.
- Une recherche de deux lettres renvoyait une erreur 500 (
Corrigé Nvidia
- Les segments sortis de NVENC duraient 10,4 s au lieu de 2 (
-forced-idr). - La doc Nvidia présentait une mire comme un film : mesures refaites sur de vrais films, l'avantage annoncé de NVENC à 12 Mb/s sur x264 medium à 8 Mb/s n'existe pas (égalité).
- Les segments sortis de NVENC duraient 10,4 s au lieu de 2 (
Ajouté Pour le plan de design
- Conversion HDR près de deux fois plus rapide : les tons viennent d'une table faite pour le pic du film, lu à l'analyse (
hdr_peak_nits; tous les fichiers sont réanalysés une fois). Sur une carte Nvidia, l'image est réduite sur la carte avant. - Guide TV : les images de programme passent par le serveur (
image,GET /tv/programmes/{id}/image), l'adresse du spectateur ne part plus chez l'hébergeur du guide. - Historique des lectures : conservé sans limite par défaut, durée réglable par l'administrateur (
/admin/sessions/history/settings), et bouton pour le vider (DELETE /admin/sessions/history). La reprise et les œuvres vues de chaque compte n'en dépendent pas. - Les images donnent leur couleur dominante et un point d'intérêt (
dominant_color,focus_x), calculés une fois à leur téléchargement. GET /admin/sessions/history: les lectures terminées, avec leur mode et leurs raisons.GET /admin/sessions/{id}/events: la frise d'une lecture.- Les images disent si elles portent du texte (
has_text,language). - Genres et rôles que TMDB laisse en anglais, traduits en français (« Action & Aventure », « (voix) »). Les œuvres identifiées sont redemandées une fois.
- Conversion HDR près de deux fois plus rapide : les tons viennent d'une table faite pour le pic du film, lu à l'analyse (
Ajouté Nvidia
- Chaîne Nvidia : décodage NVDEC, mise à l'échelle sur la carte, encodage NVENC, repérés au démarrage en les utilisant, jusqu'à quatre conversions ensemble. Mesurée sur une GTX 1080 par le pilote Windows dans Docker, pas encore sur un vrai Linux. Le mappage de tons HDR reste sur le processeur.
- Le service systemd et le compose donnent accès aux cartes graphiques, et à rien d'autre de
/dev.
Ajouté Installation Linux
- Paquet
.debet archive avecinstall.sh, construits pardeploy/package/build.shet essayés sur des systèmes vierges pardeploy/package/test/run.sh: installation, premier compte, bibliothèque, lecture, mise à jour, retrait. - L'image Docker contient maintenant l'interface web et FFmpeg. Le port par défaut du paquet et de l'image est 8097, pour tourner à côté de Jellyfin.
- FFmpeg 6.1 est le minimum. Avec une version plus ancienne, le serveur le signale et n'analyse plus rien, au lieu de déclarer tous les fichiers illisibles.
- Paquet
Corrigé Plan de lecture
- Une piste HDR convertie en SDR ne donne plus deux raisons pour la même chose :
hdr_tone_mappedseule reste.
- Une piste HDR convertie en SDR ne donne plus deux raisons pour la même chose :
Corrigé Noms de fichiers
- Noms français reconnus : FRENCH, VFF, HDLight et autres balises, filigranes de sites en tête ou en fin, noms encodés comme une adresse, dossiers « Partie N », « Épisodes spéciaux », « Hors saison », « Épisode 7 » sans saison, dossier de saison complète.
- Les mots de vrais titres ne coupent plus le nom : The French Connection ne devient plus « The », ni Charlottes Web « Charlottes ».
- TMDB : second essai en anglais si le nom n'est pas trouvé, fiches vides écartées, préfixes de marque ignorés (« Marvel's »).
- Devant deux œuvres de même nom, celle qui est au moins deux fois plus connue passe sans arbitrage. Si elles sont proches, l'administrateur tranche toujours.
Ajouté Génériques, lectures simultanées
- Les génériques de début et de fin des séries sont repérés en comparant l'audio des épisodes d'une saison, et donnés sur la fiche de chaque version (
markers). - Sur le Pixel, trois conversions peuvent tourner ensemble au lieu d'une.
- Les génériques de début et de fin des séries sont repérés en comparant l'audio des épisodes d'une saison, et donnés sur la fiche de chaque version (
Corrigé Repli logiciel
- Si la chaîne matérielle échoue au démarrage d'une conversion, le processeur prend le relais au lieu de refuser la lecture. Le film se lit, plus lentement, et la session l'indique (
software_fallback).
- Si la chaîne matérielle échoue au démarrage d'une conversion, le processeur prend le relais au lieu de refuser la lecture. Le film se lit, plus lentement, et la session l'indique (
Ajouté Taille et débit tenables
- Sans matériel adapté, le serveur chronomètre son encodeur au démarrage et n'accepte pas une taille qu'il ne tiendrait pas en temps réel. Le plan de lecture le dit (
output_limited_by_server). - Un encodeur matériel reçoit une fois et demie plus de débit (1080p à 12 Mb/s), à qualité mesurée équivalente à x264 à 8 Mb/s.
GET /playback/bandwidth-test: le client mesure sa liaison, et son résultat borne le plan de lecture en qualité automatique.
- Sans matériel adapté, le serveur chronomètre son encodeur au démarrage et n'accepte pas une taille qu'il ne tiendrait pas en temps réel. Le plan de lecture le dit (
Ajouté HDR
- Un serveur sans matériel adapté lit désormais les films HDR10, HLG et Dolby Vision à couche de base, convertis en SDR par le processeur, au lieu de les refuser. Dolby Vision profil 5 reste refusé.
- Un client qui prouve que son décodeur lit le HEVC reçoit l'image d'origine, 4K et HDR compris, sans conversion.
Modifié Démarrage et sauts
- Segments de 2 s au lieu de 6, AAC rapide, et un saut n'attend plus la fin de l'ancienne conversion. Le démarrage et les sauts d'un transcodage sont plus courts. L'audio stéréo converti passe de 128 à 192 kb/s.
- Une conversion s'arrête de travailler à 60 s d'avance sur le lecteur et reprend à 30 s, y compris quand la lecture est en pause : moins de calcul et de chaleur pour une partie du film qu'on n'atteindra peut-être pas.
Ajouté Aperçus
- Images de la barre de lecture, une toutes les 10 s, sur la fiche de chaque version. À activer par bibliothèque (
previews_enabled, désactivé par défaut) : chaque fichier est lu une fois, à basse priorité et un à la fois, dans la limite de 2 Gio.
- Images de la barre de lecture, une toutes les 10 s, sur la fiche de chaque version. À activer par bibliothèque (
Ajouté Acteurs, réalisateurs, sagas
- La fiche d'une œuvre donne ses créateurs, réalisateurs, scénaristes et acteurs, et sa saga. Les œuvres déjà identifiées sont redemandées une fois à TMDB ; les valeurs corrigées restent verrouillées.
GET /itemsfiltre par personne (person_id) et par saga (collection_id). Nouvelles routes/people/{id}et/collections, dans les droits du compte.- La recherche trouve une œuvre par le nom d'une personne ou de sa saga.
Ajouté Chapitres
- La fiche d'une œuvre donne les chapitres de chaque version : début, fin et titre.
Ajouté Libellés des tâches
- Les tâches portent
label_keyetlabel_params: l'interface peut les dire dans sa langue.labelreste en français pour les autres clients et les tâches plus anciennes.
- Les tâches portent
Ajouté Temps réel
sessions.updatedetsessions.ended: les administrateurs suivent les lectures en cours sans sonder le serveur.catalog.changed: tout compte qui voit une bibliothèque apprend que ce qu'elle liste a changé, sans détail sur les œuvres. Au plus un événement toutes les 5 s par bibliothèque.libraries.updatedpart aussi quand un scan ou une identification change les compteurs.
Ajouté Filtres du catalogue
GET /itemsfiltre aussi par années (year_min,year_max) et par qualité (quality=2160pouhdr, sur n'importe quel fichier présent de l'œuvre). Sa première page donne le nombre total d'œuvres (total).GET /items/facetsdonne les genres, années et qualités qui mènent à au moins une œuvre, avec leur nombre, dans les droits du compte.
Ajouté Langues
GETetPUT /me/preferences: langues audio et sous-titres, mode de sous-titres et qualité maximale suivent le compte d'un appareil à l'autre.- Langue par défaut du serveur :
default_localedans/server/info, lisible avant la connexion, réglable parPUT /admin/server/default-locale. Les nouveaux comptes la prennent ; les comptes existants gardent la leur.
Ajouté Détection automatique
- Sous Linux, un film ajouté, déplacé ou supprimé sur un disque local est vu tout seul, une vingtaine de secondes après le changement, sans lancer de scan. Les partages réseau et les autres systèmes restent au scan quotidien ou manuel.
Corrigé Scan
- Un film supprimé du disque restait dans les listes, la recherche et les compteurs tant que la suppression n'était pas confirmée, soit 72 h au moins. Il en sort dès le scan. Rien n'est effacé : s'il revient, il retrouve sa fiche et son historique.
- La date du dernier scan ne suivait que les scans complets : elle semblait figée après un scan rapide. Elle suit maintenant tout scan abouti.
Ajouté Images et recherche chez le fournisseur
/api/v1/artwork/{id}?w=: 360, 720, 1440 ou 2880 ; cache des images borné à 2 Gio.- Administration :
GET /admin/metadata/searchpour chercher une œuvre sous un autre nom, affiche et résumé des candidats dans la file de validation,DELETE /admin/catalog/review/{id}pour laisser une œuvre telle quelle. - Administration :
GET /admin/items/{id}/imagesetPUT,DELETE /admin/items/{id}/artwork/{kind}pour choisir une image. Une image choisie reste, même après un nouveau rapprochement. - La fiche porte
admin(état du rapprochement, champs corrigés à la main, identifiants externes) pour les administrateurs.
Corrigé Images
- Une image remplacée chez le fournisseur gardait son URL, déclarée immuable : le client et le cache pouvaient garder l'ancienne. Elle reçoit maintenant une nouvelle URL.
Ajouté Interface servie par le serveur
PROTOFLIX_WEB_DIR: le serveur sert lui-même l'interface web construite, sans second programme./api/,/livezet/readyzgardent leurs réponses.
Ajouté Chaîne matérielle du Pixel 6
- Avec le ffmpeg de Pixel Server : décodage et encodage sur le bloc vidéo, mise à l'échelle et mappage de tons sur le G2D. Les films HDR10 et Dolby Vision sur base HDR10 se lisent en SDR, y compris avec des sous-titres PGS incrustés. Essayée au démarrage ; sans elle, rien ne change.
- Détection HDR plus sûre : la première image est lue quand le flux ne dit rien de ses couleurs. Les fichiers sont réanalysés une fois.
Corrigé Disque pendant une conversion
- L'espace libre n'était contrôlé qu'au démarrage d'une conversion, qui pouvait ensuite occuper 40 Gio. Elle s'arrête maintenant sous 2 Gio libres, avec
seek_to_continue; ce qui est produit reste lisible.
- L'espace libre n'était contrôlé qu'au démarrage d'une conversion, qui pouvait ensuite occuper 40 Gio. Elle s'arrête maintenant sous 2 Gio libres, avec
Corrigé Scan différé
- Un fichier modifié depuis moins de 2 minutes est considéré en cours de copie : le scan le laisse de côté et un second scan suit 2 min 30 plus tard. Le libellé de ce second scan le dit désormais, au lieu de ressembler à un scan bloqué.
Corrigé Fin des lots en cours
- Téléchargements : le type réel du fichier est lu par ffprobe avant l'import (
not_media). Deux imports du même nom ne peuvent plus s'écraser là où le système de fichiers a des liens physiques. - Fiche d'une série ou d'une saison :
next_episode_idest rempli, selon la même règle que « Reprendre ». - Contrat : les routes pas encore servies sont marquées « planifié » (
/me/preferences,/admin/downloads/settings,/me/library/uploads).
- Téléchargements : le type réel du fichier est lu par ffprobe avant l'import (
Ajouté Sous-titres image
- Les sous-titres PGS, VobSub et DVB s'incrustent dans l'image quand on les choisit (
subtitle_track_id,subtitle_delivery: burn_in). La vidéo est réencodée : c'est plus coûteux, et en changer demande une nouvelle session. Sans encodeur, ou sur une vidéo HDR sans chaîne matérielle, la lecture continue sans eux (subtitle_burn_in_unavailable).
- Les sous-titres PGS, VobSub et DVB s'incrustent dans l'image quand on les choisit (
Corrigé Événement des bibliothèques
- L'événement temps réel
libraries.updatedenvoyait tous ses compteurs à 0 (item_count,file_count,size_bytes,pending_matches). Il porte maintenant les mêmes valeurs queGET /api/v1/libraries. Il part quand une bibliothèque change, pas à chaque fichier scanné.
- L'événement temps réel
Ajouté Ma liste, Reprendre, Historique
GET,PUTetDELETE /api/v1/me/list,GET /api/v1/me/continue,GETetDELETE /api/v1/me/history.- Privés au compte, administrateurs compris. Les droits sont appliqués à la lecture : une œuvre devenue invisible est masquée, pas effacée.
- « Reprendre » donne une entrée par œuvre. Pour une série : le dernier épisode lu s'il n'est pas terminé, sinon le suivant non terminé et présent sur le disque (
up_next), y compris à la saison suivante. Une série entièrement vue sort de la liste. - Effacer l'historique garde la position dans chaque œuvre et la marque « vu ».
Sécurité Destinations des téléchargements
- Un compte non admin ne peut télécharger que vers les bibliothèques que l'administrateur a ouvertes (
accepts_downloads,PATCH /api/v1/libraries/{id}), sinon403 destination_not_allowed. Fermé par défaut, y compris pour les bibliothèques existantes : les téléchargements non admin en file vers une bibliothèque fermée s'arrêtent à leur prochain démarrage.
- Un compte non admin ne peut télécharger que vers les bibliothèques que l'administrateur a ouvertes (
Sécurité Relecture des téléchargements
- Disque : une taille maximale par fichier et un espace à garder libre, réglables dans le module (200 Gio et 10 Gio par défaut). Rien ne les limitait, et une réponse compressée de 411 Ko pouvait devenir 200 Mio : les réponses compressées sont maintenant refusées. 100 téléchargements non terminés au plus par compte non admin.
- Droits : un droit retiré empêche la reprise et arrête ce qui était en file. Une route de débridage coupée par l'admin ne peut plus être demandée par le client.
- Chemins : les erreurs lues par le propriétaire d'un téléchargement ou de son job ne contiennent plus de chemin du serveur.
- Sorties réseau (tous les modules) : plages spéciales refusées en plus (dont
192.0.0.0/24,198.18.0.0/15,240.0.0.0/4,fec0::/10,168.63.129.16). NAT64 et 6to4 sont jugés sur l'adresse IPv4 qu'ils portent. Le lien n'est plus envoyé enRefererlors d'une redirection.
Corrigé Téléchargements
- Après une redirection, le fichier prend le nom de la dernière adresse si celui de la première n'est pas un média.
Corrigé Compteurs des bibliothèques
item_countetadmin.pending_matchesvalaient toujours 0 dansGET /api/v1/libraries.item_countdonne maintenant le nombre d'œuvres que le compte peut ouvrir, avec les règles de la liste : limite d'âge du compte comprise, une série compte pour une.
Ajouté Lectures en cours
GET /api/v1/admin/sessions(admin) : qui lit quoi, sur quel appareil, avec le plan piste par piste, les raisons, l'encodeur et la vitesse de conversion.- Aucune URL de média, aucun jeton, aucun chemin : la liste sert à comprendre, pas à regarder.
- Le titre des bibliothèques privées devra y être masqué quand elles existeront (
authn-authz.md) : elles n'existent pas encore.
Ajouté Fichiers de sous-titres
- Fichiers
.srt,.ass,.ssaet.vttposés à côté d'un film (Film.fr.srt,Film.en.forced.srt, dossierSubs) : listés dans la fiche (external) et dansdelivery.subtitles.- Vus dès qu'ils sont posés, sans nouveau scan. Une session déjà ouverte ne voit que ceux présents à son démarrage.
- Convertis en WebVTT par le serveur lui-même : aucun processus lancé sur ces fichiers, et ils marchent sans FFmpeg.
- UTF-8, UTF-16 et Windows-1252 (anciens sous-titres français) sont reconnus. Le balisage autre que gras, italique et souligné est retiré.
- Fichiers
Ajouté Sous-titres texte
- Sous-titres intégrés au fichier (SRT, ASS, mov_text, WebVTT…) servis en WebVTT :
delivery.subtitlesetGET /api/v1/media/s/{jeton}/subtitles/s3.vtt.- L'image et le son ne changent pas : la lecture directe reste directe. Changer de sous-titres ne demande ni nouvelle session ni relance.
- Première extraction : lecture de tout le fichier, 2 à la fois, avec les répliques déjà connues servies pendant ce temps (
X-Subtitles-Complete). Résultat gardé entre deux démarrages, 1 Gio au plus. - Raisons du plan :
subtitle_converted,subtitle_style_lost(ASS). - Les sous-titres bitmap (PGS, VobSub) restent non livrés :
subtitle_not_yet_supported.
- Sous-titres intégrés au fichier (SRT, ASS, mov_text, WebVTT…) servis en WebVTT :
Corrigé timeline_offset_msaprès un saut en copie vidéo : il valait la cible du saut alors que la vidéo repart de l'image clé précédente, soit jusqu'à la longueur d'un GOP d'écart (position fausse, et sous-titres décalés d'autant). Il vaut maintenant le début réel.
Ajouté Sélecteur de dossiers
GET /api/v1/libraries/browse(admin) : parcourt les dossiers du serveur pour choisir une source au lieu de taper un chemin.- Sans chemin : les lecteurs sous Windows ; sous Linux,
/et les emplacements habituels qui existent ici. - Dossiers seulement, jamais de fichier ; dossiers cachés et techniques des NAS masqués.
- Zones système et données du serveur jamais listées, y compris par un lien symbolique.
- Mêmes refus que
test-path, avec la raison et son code stable (reason_code,problem_codepourtest-path) ;media_hintdonne le nombre de médias du premier niveau, avec des limites pour qu'un dossier énorme ou un partage lent ne bloque pas.
- Sans chemin : les lecteurs sous Windows ; sous Linux,
Ajouté Lot 4b, encodage vidéo logiciel
- Les fichiers que le navigateur ne peut pas décoder sont lus : HEVC hors Safari, MPEG-2, vidéos trop grandes pour le client, qualité réduite à la demande ou par la politique à distance. Sortie H.264 High 8 bits en HLS fMP4, à la définition d'origine dans la limite du client, avec l'audio copié ou converti.
- Enregistrements TV entrelacés : désentrelacés (
yadif), puis encodés. - Couleurs : la signalisation SDR d'origine est conservée (testé). Un film HDR que le client ne peut pas afficher reste refusé (
hdr_tonemap_unavailable) : pas de couleurs fausses tant que le mappage de tons n'est pas validé (phase 5). - Test de démarrage de l'encodeur (quelques images réellement encodées) ; en cas d'échec, seuls les fichiers qui en ont besoin sont refusés.
- Ressources : au plus un encodage par tranche de 4 cœurs (au moins 1), refus immédiat au-delà (
resources_exhausted), jamais de file d'attente.conversion_speeddans la session : sous 1, le lecteur attendra. - Vérifié en conditions réelles dans le conteneur (16 cœurs), sur des fichiers synthétiques : HEVC 1080p prêt en 1,6 s, décodé depuis l'URL, produit à 4,9 fois le temps réel ; enregistrement entrelacé lu ; HDR10 refusé avec sa raison. Pas encore dans un vrai navigateur. Les vitesses sur de vrais films et sur une petite machine restent à mesurer.
Ajouté Lot 4a, remux et conversion audio
- Les MKV et les fichiers au son non décodé par le navigateur (AC-3, DTS, TrueHD…) sont lus, sans réencoder l'image : HLS fMP4 (
GET /api/v1/media/s/{jeton}/hls/{nom}), vidéo copiée, audio copié ou converti en AAC (canaux conservés dans la limite du client).internal/transcodingsupervise,internal/transcoding/ffmpegest seul à connaître la syntaxe. - Choix de la piste audio : une autre piste que celle par défaut passe par le remux (raison
audio_track_selection), car un lecteur à qui l'on donne le fichier joue la piste par défaut. Avant, le plan promettait à tort cette piste en lecture directe. - Saut
PATCH /api/v1/playback/sessions/{id}: relance la conversion à la position demandée ;timeline_offset_msdonne le temps du film au début de la playlist. - Sécurité : ffmpeg reçoit le fichier par descripteur et ne voit aucun chemin ; les noms servis sont une liste fixe ; environnement minimal ; aucun détail du moteur dans les réponses.
- Ressources : 4 conversions au plus, jamais de file d'attente (
resources_exhausted) ; espace libre vérifié ; budget disque par conversion ; arrêt si plus aucune progression. - Pannes : à l'arrêt, à l'expiration ou à l'abandon d'une session, le processus et ses fichiers disparaissent. Après un
kill -9du serveur, ffmpeg meurt avec lui (Linux) ; au redémarrage, les répertoires sont vidés et les sessions passentfailed: le client en recrée une à la position enregistrée. - Vidéo entrelacée : l'analyse relève maintenant
field_order(migration 00014, normaliseur en version 2, réanalyse automatique au prochain scan). Le plan refuse de copier ces fichiers (raisonvideo_interlaced), car Chromium produit alors des erreurs de décodage aléatoires. Ils seront lisibles avec l'encodage vidéo (lot 4b). PROTOFLIX_TRANSCODE_DIR(par défautCACHE_DIR/transcode, vidé à chaque démarrage).- Vérifié en conditions réelles dans le conteneur, sur un MKV de 10 minutes H.264 + AC-3 :
- session prête en 378 ms, sortie H.264 + AAC 5.1 décodée par FFmpeg depuis l'URL ;
- saut à 300 s en 475 ms ;
- ffmpeg sans chemin sur sa ligne de commande ;
- noms hors liste refusés (404) ;
- plus aucun processus ni fichier après l'arrêt ou un
kill -9.
Pas encore essayé dans un vrai navigateur : le lecteur web n'est pas branché. Ces temps viennent d'un fichier synthétique sur disque local : à mesurer sur de vrais films et sur un NAS.
- Les MKV et les fichiers au son non décodé par le navigateur (AC-3, DTS, TrueHD…) sont lus, sans réencoder l'image : HLS fMP4 (
Ajouté Lot 3a, lecture directe
- Moteur de décision
internal/playback.Decide(docs/media/playback-decision.md) : une fonction pure qui produit un plan déterministe (lecture directe, remux ou transcodage) avec toutes les raisons.- Profils
web-chromium@1(alias chrome, edge),web-firefox@1,web-safari@1etconservative@1; un profil inconnu retombe sur le profil prudent. La déclaration du client ne peut que restreindre. - Les limites de qualité demandée et de politique à distance s'appliquent.
- Testé par une table de cas et par des propriétés vérifiées sur 3 000 entrées aléatoires : déterminisme, une raison pour tout ce qui n'est pas direct, aucune déclaration ne peut élargir le profil.
- Profils
- Sessions de lecture (migration 00013) :
POST /api/v1/playback/plan-preview,POST /api/v1/playback/sessions,GET(qui renouvelle le jeton) etDELETE.- Seule la lecture directe est exécutée. Un plan qui demanderait un remux ou un transcodage répond
503 transcoder_unavailablejusqu'à la phase 4.
- Seule la lecture directe est exécutée. Un plan qui demanderait un remux ou un transcodage répond
- Fichier
GET /api/v1/media/s/{jeton}/file:- jeton HMAC lié à la session, valable 4 h, qui ne sert plus dès l'arrêt ou l'expiration de la session ;
- Range,
ETag,If-Range; - fichier ouvert par la racine confinée de la source ;
- jamais de jeton dans les journaux.
- Progression
PUT …/progress: idempotente (les événements anciens sont ignorés) ; reprise par compte (ItemSummary.progress, la dernière écriture gagne entre appareils) ; vue à 90 % (historique). Une session sans heartbeat passestalledaprès 30 s, puisexpiredaprès 5 min. PROTOFLIX_PLAYBACK_EXPERIMENTAL(par défauttrue) : les règles de compatibilité pas encore mesurées décident, faute de banc. Le plan l'indique (support: experimental).
- Moteur de décision
Corrigé - Essai réel de TMDB avec une vraie clé (
docs/adr/0016-fournisseur-metadonnees.md). Il a révélé trois défauts, corrigés :- un titre écrit sans apostrophe dans le nom de fichier (« d Amelie ») partait en validation au lieu d'être reconnu ;
- des logos SVG, que le serveur refuse de servir, étaient retenus : seules les images servables le sont désormais ;
- file de jobs : un job ponctuel d'un type récurrent (
metadata.match_alllancé à l'activation du module) replanifiait le type en heurtant l'occurrence déjà prévue, son résultat n'était pas enregistré et il repartait après expiration de son lease. Seule l'occurrence récurrente se replanifie désormais.
- Tri par titre : « Alien », « Annie Hall » ou « Amélie » étaient rangés sans leur première lettre, comme si « A » était un article. Les clés de tri existantes sont recalculées une fois au démarrage.
- Essai réel de TMDB avec une vraie clé (
Ajouté Lot 2f, recherche et corrections
- Recherche
GET /api/v1/search(ADR 0015, accepté), avec SQLite FTS5 (migration 00011) :- par titre, titre original et genre ; accents et casse ignorés ;
- tous les mots requis, le dernier en préfixe (« dun par » trouve « Dune: Part Two ») ;
- fragments d'au moins 3 caractères à l'intérieur des titres (« xpans » trouve « The Expanse ») ;
- droits (bibliothèques, limite d'âge) appliqués dans la requête ; les opérateurs saisis sont du texte ordinaire ;
- ordre stable et pagination par curseur.
- Mesure sur 50 000 œuvres, sur le poste de développement : P50 14 ms, P95 103 ms (
docs/testing/benchmarks/search/). - Corrections manuelles
PATCH /api/v1/admin/items/{id}: titre, titre original, titre de tri, année, synopsis, classification et genres.- Chaque correction devient une valeur verrouillée, prioritaire sur les NFO, TMDB et le nom de fichier.
- Un champ envoyé à
nullrend la main aux autres sources. - Elle s'applique aussi aux saisons et aux épisodes.
- Une œuvre en attente de validation le reste jusqu'à un choix ou une correction, même si de nouveaux fichiers arrivent.
- Recherche
Modifié Demande du porteur du projet
- Mot de passe : la longueur minimale passe de 12 à 8 caractères, sans règle de composition. Sont désormais refusés les mots de passe très courants (liste locale), les caractères répétés, les suites (
12345678), les rangées de clavier (azertyuiop) et la partie locale de l'e-mail. Contrat mis à jour (minLength: 8).
- Mot de passe : la longueur minimale passe de 12 à 8 caractères, sans règle de composition. Sont désormais refusés les mots de passe très courants (liste locale), les caractères répétés, les suites (
Ajouté Lot 2e, modules et TMDB
- Modules activables (ADR 0022, accepté) :
- catalogue, états (désactivé, à configurer, erreur, indisponible, actif) et dépendances ;
- réglages typés et validés, secrets chiffrés au repos et jamais relus ;
nullefface ; - vérification immédiate après un changement, événement
modules.updated; - API
/api/v1/moduleset/api/v1/admin/modules.
- Client sortant commun (
internal/platform/outbound) : hôtes déclarés uniquement, adresses privées refusées après DNS (SSRF), pas de proxy d'environnement, redirections contrôlées, HTTPS seul, réponses limitées, requêtes espacées, clé jamais écrite dans les erreurs. - Module
metadata.tmdb(ADR 0016), avec la clé de l'administrateur :- recherche et score titre et année ; identifiants des NFO utilisés directement, IMDb et TVDB résolus ;
- les cas ambigus vont dans une file de validation (
GET /api/v1/admin/catalog/review, choix parPOST /api/v1/admin/items/{id}/match) ; - titres, résumés, genres et classification (pays de la langue choisie), pour les saisons et les épisodes aussi ;
- un nouvel épisode fait redemander la série ;
- les NFO et les corrections manuelles restent prioritaires.
- Images : affiches, fonds, logos et vignettes d'épisodes, servis par
GET /api/v1/artwork/{id}après contrôle des droits. Téléchargés au premier usage et mis en cache dansPROTOFLIX_CACHE_DIR(par défautDATA_DIR/cache). Le SVG est refusé. - Les classifications d'âge passent dans un paquet commun (
internal/catalog/rating). - Vérifié en conditions réelles depuis le conteneur : une fausse clé est refusée par le vrai TMDB (« Clé API refusée par TMDB »), et la clé n'apparaît pas en clair dans la base. Le reste du parcours TMDB est testé contre un faux serveur TMDB. Pas encore validé avec une vraie clé.
- Modules activables (ADR 0022, accepté) :
Ajouté Lot 2d, catalogue
- Catalogue en couches (ADR 0014, accepté), migration 00009 :
- une œuvre (film, série › saison › épisode, vidéo perso) a des éditions, chaque édition des versions, chaque version des fichiers ;
- les métadonnées sont gardées par champ, avec leur source (
metadata_values) ; - les identifiants TMDB, IMDb et TVDB sont conservés.
- Identification locale (
docs/media/naming.md), par le jobcatalog.identifymis en file après chaque scan :- films : titre, année et édition tirés des noms de release et des dossiers « Titre (Année) » ;
- séries :
S01E02et1x02, dossiers de saison ; - bonus (bandes-annonces, échantillons) écartés du catalogue ;
- NFO Kodi, Jellyfin, Radarr et Sonarr, traités comme des entrées hostiles ;
- copies identiques regroupées dans une même version.
- Arbitrage des métadonnées : une valeur verrouillée l'emporte, puis manuel, puis NFO, puis fournisseur, puis nom de fichier.
- Classifications d'âge (FR, MPA, TV, FSK) ramenées aux paliers 0, 10, 12, 16 et 18. Une œuvre sans classification est masquée sous une limite d'âge.
- API
GET /api/v1/items,/items/{id}et/items/{id}/children:- filtrées par les bibliothèques visibles et la limite d'âge du compte ; une œuvre invisible répond 404 ;
- tris
added_desc,title_asc(sans l'article) etyear_desc, avec un curseur lié au tri ; - disponibilité
available,source_offlineoumissing; - versions triées de la meilleure à la moins bonne ; libellés et badges (2160p, HDR10, Dolby Vision, Atmos, 5.1, 7.1) tirés de l'analyse uniquement ;
- pistes détaillées, sans aucun chemin.
- Vérifié en conditions réelles dans le conteneur, avec 2 bibliothèques :
- Dune : 2 versions et la classification « 12 » tirée du NFO ;
- la bande-annonce est écartée ;
- la série est rangée en saisons ;
- un identifiant inconnu répond 404.
- Catalogue en couches (ADR 0014, accepté), migration 00009 :
Modifié Demandes du front
- Les jobs exposent
subject: ce sur quoi ils portent, en identifiants publics uniquement. Pour un scan ou une analyse, c'est{kind: "source", id, library_id}; pour un job global,null. Le front n'a plus à deviner la bibliothèque à partir du libellé. Migration 00008. forcelève aussi la protectionempty_root, pour le cas d'un dossier vraiment vidé. Même forcé, rien n'est supprimé tout de suite : les fichiers passent absents et retrouvent leur identité si le dossier revient (testé).
- Les jobs exposent
Ajouté Lot 2c, analyse des médias
internal/mediaanalysis: description technique d'un fichier indépendante de ffprobe. Elle comprend :- le conteneur, la durée et le débit ;
- les pistes vidéo : codec, profil, définition, cadence exacte (
24000/1001), profondeur, couleurs, HDR (hdr10,hlg,dolby_visionavec profil) ; - les pistes audio : canaux, disposition, fréquence ;
- les sous-titres : texte ou image, forcés, pour malentendants ;
- la langue et le titre des pistes, les chapitres.
Ce qui n'est pas trouvé reste vide, jamais deviné. Une pochette intégrée n'est pas comptée comme piste vidéo.
- Adaptateur ffprobe confiné : le fichier est transmis comme descripteur, ffprobe ne voit aucun chemin et ne peut rien ouvrir d'autre. Délai et sorties bornés.
- Job
media.analyzepar source, mis en file après chaque scan terminé :- les résultats vont dans
media_analyses,media_streamsetmedia_chapters(migration 00007) ; - un fichier illisible est marqué
unreadableet n'est plus retenté tant qu'il ne change pas ; - un résultat est ignoré si le fichier a changé pendant l'analyse ;
- une nouvelle version du normaliseur relance l'analyse.
- les résultats vont dans
PROTOFLIX_FFPROBE_PATH(par défaut le ffprobe à côté de ffmpeg, sinon celui duPATH). Sans ffprobe, les fichiers sont indexés sans analyse.- Image de test
deploy/docker/test.Dockerfile(Go 1.27 et FFmpeg 7.1.5 épinglé). Elle sert àcheck.sh --fullpour des tests sur un corpus généré : h264/aac, HEVC 10 bits HDR10 et HLG, MKV multipiste avec sous-titres forcés et chapitres, fichiers corrompu et tronqué, lien hors source. Le profil Dolby Vision est vérifié sur une sortie ffprobe écrite à la main (pas d'encodeur libre). - Vérifié en conditions réelles dans le conteneur : la création d'une bibliothèque lance le scan puis l'analyse. Deux fichiers sont analysés en 191 ms ; le fichier corrompu est marqué illisible.
Ajouté Lot 2b, scanner
- Scanner des sources (
internal/scanner) :- parcours confiné ; seuls les fichiers vidéo et audio sont indexés ;
- ignorés : fichiers temporaires (
.part,.!qB,.crdownload…), fichiers cachés, dossiers techniques des NAS (@eaDir,#recycle,$RECYCLE.BIN…).
- Fichiers en cours de copie mis en attente (« settling »), puis repris par un scan de suivi.
- Renommages et déplacements reconnus par taille et empreinte rapide : le fichier garde son identité. Les copies identiques ne sont jamais devinées.
- Un fichier absent passe en « missing » et n'est supprimé qu'après deux scans complets et 72 h d'absence. Une source hors ligne n'est jamais scannée. Une racine soudain vide ou une disparition massive interrompt le scan sans rien modifier, sauf scan forcé.
- Jobs
library.scan(automatique à la création d'une bibliothèque et à l'ajout d'un dossier) etlibrary.scan_all(réconciliation complète quotidienne) ;POST /api/v1/libraries/{id}/scanaveckindetforce. - Compteurs réels de fichiers et d'octets dans la vue admin des bibliothèques. Historique des exécutions dans
scan_runs.
- Scanner des sources (
Ajouté Lot 2a, bibliothèques
internal/storage: accès en lecture seule confiné à la racine de chaque source paros.Root. Les chemins.., les chemins absolus et les liens symboliques sortants sont refusés. Les racines sont validées : chemin absolu, hors zones système, sans chevauchement avecDATA_DIRni avec une autre source.- Bibliothèques partagées (films, séries, musique, vidéos personnelles) et leurs sources. API
/api/v1/libraries: liste, détail, création, renommage, suppression confirmée (X-Confirm-Delete), ajout et retrait de dossiers, test d'un dossier. Un compte ne voit que les bibliothèques de sa politique, sans aucun chemin. - Sonde des sources toutes les 2 minutes (job
library.probe_sources) :online,unavailable,permission_deniedouio_error, avec horodatage, détail et type de système de fichiers. Une source qui tombe ne fait rien supprimer (vérifié en conditions réelles). - Droits par bibliothèque désormais enregistrés (
policy_libraries) et validés. internal/platform/fsinfo: détection du système de fichiers, partagée par la base et les bibliothèques.
Ajouté Lot 1f, contrôles
server/scripts/check.sh: gofmt, go vet, staticcheck v0.8.2, tests, govulncheck v1.9.0 ; avec--full, en plus, tests-race, détection d'écart sqlc et validation du contrat OpenAPI.- Test d'architecture (
internal/archtest) : les règles dedomains.mdvérifiées sur le graphe d'imports réel. - Test de couverture du contrat : toute route servie doit figurer dans
api/openapi.yaml. - Workflow GitHub Actions (
.github/workflows/server.yml), écrit mais pas encore exécuté (pas de dépôt distant).
Sécurité - Chaîne d'outils Go épinglée en go1.27.3 : govulncheck signalait 13 vulnérabilités de la bibliothèque standard (net/http, HTTP/2, crypto/tls, crypto/x509, html/template, mime/multipart) dans go1.27.0, dont certaines atteignables par le serveur.
golang.org/x/netv0.62.0. Reste une vulnérabilité signalée dansgolang.org/x/cryptov0.58.0, non atteignable par notre code, corrigée seulement dans une version non publiée : à mettre à jour à la prochaine version.
Ajouté Lot 1e, jobs
- File de jobs durable (ADR 0006, accepté) : mise en file idempotente, priorités, acquisition atomique, leases avec heartbeat, nouveaux essais avec backoff et jitter,
failed/dead_letter, annulation (y compris en cours d'exécution), libération propre à l'arrêt, récupération des leases expirés, purge. - Runner de workers via l'interface
jobs.Source(ADR 0020) : concurrence par type, timeouts, progression, paniques rattrapées. - Maintenance récurrente
maintenance.purge_jobs(quotidienne). - API
/api/v1/jobs(liste paginée, détail, tentatives, relance, annulation) : l'admin voit tout, un compte seulement ses propres jobs. - Flux SSE
/api/v1/eventsfiltré par compte, avec reprise parLast-Event-ID,resyncet durée limitée à 15 min. - Mesures : 1 625 jobs/s ;
kill -9d'un worker sans perte de job (testé avec un vrai processus). Retry-Afteroptionnel pour les erreurs de domaine des autres paquets.
- File de jobs durable (ADR 0006, accepté) : mise en file idempotente, priorités, acquisition atomique, leases avec heartbeat, nouveaux essais avec backoff et jitter,
Ajouté Lot 1d, identité
- Comptes individuels (ADR 0009) : création du premier administrateur depuis le réseau local, invitations à usage unique (7 jours), rôles admin/adulte/enfant, droits par compte (limite d'âge, accès distant et qualité maximale à distance, code rapide, quota privé, téléchargements).
- Appareils et comptes mémorisés : une session par compte et appareil, verrouillage des autres comptes sur un appareil partagé, déverrouillage par mot de passe ou code rapide à 4 chiffres. Le code rapide est lié à l'appareil, supprimé après 5 échecs et refusé à distance par défaut.
- Jetons de session opaques avec rotation à chaque connexion ou déverrouillage ; seule leur empreinte SHA-256 est stockée. Mode
cookiepour les navigateurs (préfixe__Host-en HTTPS) et modetokenpour les clients natifs. - Protection CSRF (origine autorisée et double soumission), limitation des tentatives en mémoire avec
Retry-After, Argon2id aux paramètres OWASP avec au plus 4 hachages simultanés. - Journal d'audit des actions d'administration.
- Endpoints :
/api/v1/setup,/auth/login,/auth/logout,/devices/current/accounts…,/me(profil, mot de passe, code rapide, appareils),/accounts(admin),/invitations(admin) et/invitations/by-code/{code}(public). - Configuration :
PROTOFLIX_LOCAL_NETWORKS,PROTOFLIX_ALLOWED_ORIGINS. - Erreurs de domaine génériques (
httpapi.CodedError) pour les futurs paquets.
Modifié Contrat
- Invitations publiques sous
/api/v1/invitations/by-code/{code}; révocation par identifiantinv_…. Ajout desession_mode, dePUT /me/passwordet de nouveaux codes d'erreur (invalid_credentials,session_locked,setup_done,email_taken,device_unknown,csrf_rejected).
- Invitations publiques sous
Décidé - ADR 0017 accepté : BitTorrent et débridage inclus. Les torrents (
torrents_enabled, activé par défaut une fois le module ouvert), le partage (seeding_enabled, désactivé par défaut, avec limites de ratio et de durée) et le port entrant (incoming_port_enabled, désactivé par défaut) sont des réglages d'administration. Nouveau code d'erreurtorrents_disabled.
- ADR 0017 accepté : BitTorrent et débridage inclus. Les torrents (
Ajouté Lot 1c, observabilité
- OpenTelemetry v1.47.0 : métriques au format Prometheus et traces exportables en OTLP/HTTP (
PROTOFLIX_OTLP_ENDPOINT, désactivé par défaut ; sans destination, aucun span n'est enregistré). - Écoute d'administration
PROTOFLIX_ADMIN_ADDR(désactivée par défaut) :/metricset/debug/pprof/. Avertissement si elle n'est pas sur loopback. - Métriques : durée des requêtes HTTP par motif de route (labels bornés, testé), requêtes en cours, attente et durée de l'écrivain SQLite, issues des transactions, connexions par pool,
protoflix_build_info, métriques Go et processus. - Span serveur par requête API, nommé par motif de route ;
traceparentaccepté seulement depuis un proxy de confiance. - Journaux :
trace_idetspan_idajoutés automatiquement ; le journal d'accès écrit la route et non plus le chemin brut (les futurs jetons de lecture n'y apparaîtront pas) ; durée enduration_ms.
- OpenTelemetry v1.47.0 : métriques au format Prometheus et traces exportables en OTLP/HTTP (
Ajouté Lot 1b, persistance
- Base SQLite embarquée (
modernc.org/sqlitev1.61.1, SQLite 3.54.1) : WAL, un seul écrivain (BEGIN IMMEDIATE), un pool de lecture enquery_only, tablesSTRICT. - Verrou d'instance
DATA_DIR/protoflix.lock: un seul coordinateur par répertoire de données, libéré par le système même après un arrêt brutal. - Refus de démarrer si
DATA_DIRest sur un système de fichiers réseau (Linux : NFS, SMB, CIFS, Ceph… ; Windows : lecteurs réseau et chemins UNC). - Migrations
goosev3.29.0 embarquées. Première migration :server_instance,settings. Une base neuve est initialisée automatiquement ; une base existante n'est migrée que parprotoflix migrate upou avecPROTOFLIX_AUTO_MIGRATE=true, après une sauvegarde vérifiée. Une base plus récente que le binaire est refusée. - Commandes
migrate up|statusetbackup create|verify|restore(la restauration conserve l'ancienne base). /readyzvérifie la base.- Identifiants UUIDv7 et forme publique préfixée (ADR 0008).
- Requêtes typées générées par
sqlc1.31.1 (server/scripts/sqlc.sh). - Banc pilote pur Go contre cgo (
docs/testing/benchmarks/sqlite-drivers/).
- Base SQLite embarquée (
Modifié - Image Docker :
PROTOFLIX_AUTO_MIGRATE=true; le répertoire de données est créé dans l'image avec le propriétairenonroot(sans cela, un volume nommé n'était pas inscriptible). - Le serveur vérifie au démarrage qu'il peut écrire dans
DATA_DIR, avec un message explicite. - Contrat : route de débridage pour les téléchargements (
route, étatcaching, compte Mega-Debrid côté admin, réglages globaux, pause/reprise de toute une file) et bandes-annonces (trailersdans le détail d'une œuvre). ADR 0017 complété : le connecteur de débridage est soumis à validation humaine. - Base de données : SQLite embarqué au lieu de PostgreSQL (ADR 0019, remplace 0004), pour une installation et des mises à jour sans base à administrer. ADR 0002, 0005, 0006, 0008, 0013 et 0015 révisés.
- Architecture coordinateur + workers distants optionnels via une API interne (ADR 0020).
- Contrat :
has_quick_code,last_device_name, fiche technique par version,next_episode_id,POST /api/v1/playback/plan-preview.
- Image Docker :
Ajouté - Dossier d'architecture (phase 0) : vue d'ensemble, domaines, modèle de données, flux, feuille de route, risques (
docs/architecture/). - ADR 0001 à 0018 (
docs/adr/), dont le modèle de comptes individuels (0009), le module Téléchargements (0017, validation humaine requise) et la bibliothèque privée (0018). - Contrat OpenAPI 3.1 préliminaire (
api/openapi.yaml) et conventions d'API (docs/api/). - Documentation média, sécurité, exploitation et tests (
docs/media/,docs/security/,docs/operations/,docs/testing/). - Squelette du serveur Go (
server/) : sous-commandesserve,migrate(non implémentée),config checketversion; configurationPROTOFLIX_*validée ; logs JSON ; erreursproblem+json;/livez,/readyz,/api/v1/server/info; arrêt gracieux. - Déploiement : unité systemd durcie et Dockerfile distroless avec
compose.yaml(deploy/), non testés en conditions réelles.
- Dossier d'architecture (phase 0) : vue d'ensemble, domaines, modèle de données, flux, feuille de route, risques (
Vérifié Lot 3a
Dans le conteneur, avec un vrai fichier MP4 H.264/AAC :
- fichier servi identique octet pour octet ;
206 Partial ContentavecContent-Range;- ffprobe lit le film par l'URL de lecture (20 s) ;
- jeton falsifié refusé (403) ;
- reprise enregistrée à 7 s ;
- URL refusée après l'arrêt (409) ;
- jeton absent des journaux ;
- un MKV est refusé avec la raison
container_unsupported.