> La révision linguistique de cette traduction est en cours. En cas d’ambiguïté, consultez l’[original anglais](https://www.sm.ch-j.eu/docs/i18n/en/remote-editor-latency.md). # Enregistrement et surveillance de la latence par l'éditeur distant ## Causes profondes L'éditeur précédent a téléchargé son fichier de travail dans le répertoire parent de la cible, qui ne peut souvent pas être écrit par le compte SSH sous `/etc` ou `/var`. SFTP rename n'a fourni aucun chemin de sudo autorisé, vérification des conflits de base, vérification des métadonnées de sécurité ou sémantique d'écrasement fiable. Son gestionnaire d'erreur a supprimé la copie temporaire, en supprimant le matériel de récupération même lorsque l'achèvement était incertain. État de session précédemment exposé seulement l'état de connexion. Il n'y a pas eu de mesure de la réponse ICMP ou SSH authentifiée alimentant l'indicateur terminal. ## Enregistrer le protocole 1. Un helper SSH fixe ouvre un fichier régulier à lien unique en utilisant descripteur-relative opérations et `O_NOFOLLOW` pour chaque composant de chemin. Il capture le contenu, le hachage SHA-256, périphérique/inode, UID, GID, les bits d'autorisation complets, les temps de modification/changement nanoseconde et tous les attributs étendus lisibles. Core vérifie le hachage et décode la stricte UTF-8, en préservant un BOM. Chaque document obtient un `editId` opaque, englobé dans son plugin, session de terminal et identité du serveur. 2. Une opération de préparation non privilégiée résout le compte authentifié Accueil via `pwd.getpwuid(os.getuid())`, crée `$HOME/ch-j-sm/` avec le mode `0700` et crée un journal privé de récupération exclusive. Un logement non sécuritaire, un espace de travail symlink ou un lieu de travail appartenant à un autre compte est rejeté. 3. Core télécharge un fichier de travail au hasard de 128-bit `.tmp` dans SFTP avec création exclusive (`wx`), mode `0600` et un délai d'exécution de soixante secondes. Le journal contient la cible, le point de départ initial et le hash de travail attendu; il ne contient aucune identificatif. 4. **One SSH exec effectue l'ensemble de la finalisation **, en option à travers le Exécuteur de sudo existant. L'aide ouvre et hache la copie de travail privée en toute sécurité et la chasse. Il verrouille l'inode d'origine, vérifie sa base de référence, crée un fichier de destination exclusif à côté de la cible, écrit tout le contenu, applique et vérifie les métadonnées, vérifie l'original à nouveau et chasse le remplacement. 5. Un même répertoire `os.replace` remplace atomiquement la cible. Le parent le répertoire est rincé et le chemin final, le hachage, l'inode et les métadonnées sont vérifiés. Le chemin d'origine reste disponible jusqu'au remplacement. Le fichier de travail n'est jamais déplacé à travers les systèmes de fichiers et ne sera jamais supprimé par finalisation. 6. Après que Core ait reçu un succès vérifié, un nettoyage séparé revérifie la finale contenu et métadonnées de sécurité avant de supprimer le fichier de travail et la revue. L'échec de nettoyage signale toujours une sauvegarde confirmée avec `recoveryAvailable: true`. Un téléchargement, un sudo, un conflit, une erreur de métadonnées ou un remplacement raté conserve l'original et tout matériel mis en scène. Les téléchargements incomplets sont identifiés comme tels et ne peuvent pas être récupérés en tant que document complet édité. La communication SSH perdue, l'état de sortie manquant, les chronométrages et les résultats de finalisation inattendus sont signalés comme **unknown**, jamais aussi sauvegardés. Core bloque une autre sauvegarde sur un document incertain; il n'y a pas de réessayer de remplacement automatique. ## Métadonnées, privilèges et limites de sécurité L'assistant conserve et vérifie les UID, GID et tous les bits d'autorisation POSIX, y compris les bits exécutables, setuid, setgid et collants. Il reproduit les attributs étendus par octet Linux pour octet, y compris les ACL POSIX, les capacités et les étiquettes SELinux. La propriété et le contenu du fichier sont définis avant les attributs de sécurité, parce que les écritures/chown peuvent effacer des capacités ou des bits de permission spéciaux. Les attributs de destination hérités qui sont absents sur l'original sont supprimés. Le temps de modification reflète la nouvelle écriture et n'est pas copié à partir de l'original. Un attribut illisible ou non représentatif avorte l'opération; les métadonnées ne sont pas supprimées silencieusement. Les signatures IMA/EVM sont explicitement rejetées parce que la copie des signatures d'intégrité de contenu/liées à l'inode les invaliderait. Les liens dans la cible ou le chemin d'accès, les fichiers liés en dur et les fichiers non réguliers sont rejetés. Aucun retour en arrière en place ou plus faible SFTP n'est utilisé. Les sauvegardes en écriture ordinaires s'exécutent sous la forme du compte SSH. Les sauvegardes protégées nécessitent explicitement `{ sudo: true }`; un mot de passe sudo est optionnel pour le sudo sans mot de passe. Les mots de passe sont validés et transmis uniquement sur le canal stdin, jamais dans la commande, journal, fichier de travail, enregistreur ou erreur distante. Les sessions Root SSH utilisent l'exécuteur root direct existant. L'autorisation refusée laisse intact l'original et la copie de travail. Toutes les sauvegardes exécutées sous forme de root (direct root SSH ou sudo) rejettent également les répertoires/avertisseurs cibles appartenant à d'autres comptes, ou portant un accès ACL, plutôt que de faire confiance à un chemin privilégié contrôlé par un autre compte. L'assistant fixe fonctionne avec `python3 -I -B` : il ignore les chemins Python de l'utilisateur, le répertoire de travail et les paquets du site utilisateur, et n'écrit aucun octecode. Les paramètres Paths et JSON sont shell-quoted dans Core. Les greffons ne reçoivent jamais les poignées arbitraires SSH exec ou SFTP. La boîte à sable, CSP, les autorisations de manifeste, la vérification de la clé hôte et la vérification de mise à jour demeurent en usage. ## Plugin API et intégration Monaco restante **L'interface utilisateur Monaco/File Manager distribuée séparément est absente de cette commande. L'intégration de l'interface utilisateur, l'invite de sudo, la gestion dirty-buffer et les traductions n'ont pas pu être mises en œuvre ni testées ici.** La source du plugin est le plugin Hash & Sommes de contrôle. Aucune source de remplacement du gestionnaire de fichiers n'a été inventée. Les méthodes existantes demeurent disponibles. Les méthodes/options additives sont exposées par le préchargement en boîte de sable et l'exécution contrôlée par autorisation: ```js const opened = await chjPlugin.files.readText(sessionId, path); // For a protected read, explicitly pass { sudo: true, sudoPassword }. const result = await chjPlugin.files.saveText(sessionId, path, editor.getValue(), { editId: opened.editId, sudo: true, // Include only after the user authorizes elevation. sudoPassword // Omit for passwordless sudo; never persist this value. }); if (result.ok && result.value.status === "saved") { // Mark this exact submitted editor version as saved. Later edits stay dirty. } else { // Keep the Monaco model dirty. Translate result.error.code/status. // result.error.recoveryId/recoveryPath identify retained working material. } await chjPlugin.files.closeText(opened.editId); const recovery = await chjPlugin.files.listRecovery(sessionId); const copy = await chjPlugin.files.readRecovery(sessionId, recoveryId); // Review copy.status and copy.text; open a fresh document before another save. await chjPlugin.files.cleanupRecovery(sessionId, recoveryId); // Cleanup rejects anything whose target is not currently confirmed. ``` Les méthodes de récupération acceptent un paramètre final optionnel `{ sudo: true, sudoPassword }` lors de l'inspection d'une cible nécessite une élévation. Ils conservent l'espace de travail de l'utilisateur authentifié même lorsqu'il est exécuté par sudo. Les journaux survivent au redémarrage de l'application et à la reconnexion de SSH; la récupération ne répète jamais automatiquement la finalisation. Examiner un tampon récupéré contre une cible nouvellement ouverte avant de l'enregistrer explicitement. `files.read` garde lit, contrôle et la mainlevée. Les gardes `files.write` sauvent et récupèrent le nettoyage. `writeText` rejette toujours en cas d'échec pour les plugins existants; `saveText` retourne une enveloppe structurée `{ ok, value/error }` parce que Electron dépose des propriétés personnalisées sur les objets rejetés. Un ancien trois arguments `writeText` peut utiliser la ligne de base d'un seul document ouvert. Plusieurs documents en direct pour le même chemin nécessitent `editId`; les appels ambigus échouent en toute sécurité au lieu de choisir la base de référence d'un autre document. Les greffons devraient libérer les poignées inutilisées. L'interface utilisateur externe doit afficher la sauvegarde immédiatement, garder les tampons sales en cas d'échec, n'offrir de sudo qu'après des échecs de permission/authentification, afficher les conflits sans écrasement, et offrir la récupération après perte de connexion ou un résultat inconnu. Il doit traduire ces états en tchèque, en allemand et en anglais. Copie de l'état suggérée : | State | Czech | German | English | | --- | --- | --- | --- | | Saving | Ukládání… | Wird gespeichert… | Saving… | | Confirmed | Uloženo | Gespeichert | Saved | | Failure | Uložení selhalo | Speichern fehlgeschlagen | Save failed | | Sudo required | Vyžadováno oprávnění sudo | sudo-Autorisierung erforderlich | Sudo authorization required | | Conflict | Původní soubor byl změněn | Originaldatei wurde geändert | Original file changed | | Disconnected | Spojení bylo přerušeno | Verbindung unterbrochen | Connection lost | | Unknown | Výsledek uložení není znám | Speicherergebnis unbekannt | Save result unknown | | Recovery | Obnova je dostupná | Wiederherstellung verfügbar | Recovery available | Récupération | | Obnova je dostupná | Wiederherstellung verfügbar | Récupération disponible | ## Définitions des latences et cycle de vie **Ping** est la latence rapportée par une réponse d'écho ICMP côté client à l'IP résolu utilisé par SSH. Core invoque la plate-forme ping exécutable asynchrone avec un tableau d'arguments fixe, sans exigence de démarrage shell ou administrateur. Les arguments Linux, macOS (y compris `ping6`) et Windows sont sélectionnés séparément. Un ICMP bloqué, un exécutable manquant, une sortie timeout, une sortie invalide ou une réponse Windows liée uniquement à la ligne supérieure, telle que `<1ms`, produisent une valeur indisponible, et non un nombre inventé. **SSH RTT** est la durée monotonique `performance.now()` d'une demande d'exec `true` fixe par rapport au client SSH déjà authentifié. Il comprend la configuration du canal, le traitement du serveur et la livraison des réponses; il ne s'agit pas d'une durée de connexion RTT ou SSH. L'outil d'indicateur traduit explique cette distinction. La surveillance commence dès que le terminal se connecte. Les sondes fonctionnent simultanément et asynchronement, avec un délai de requête/processus de cinq secondes. L'échantillon suivant est programmé douze secondes après la fin de l'échantillon précédent, ce qui empêche le chevauchement. Déconnecter avorter ICMP, effacer les minuteurs, annuler en attente de travail SSH et effacer les valeurs. Les contrôles d'identité des enregistrements empêchent une connexion antérieure de publier après la reconnexion. L'échec ICMP ne change jamais l'état de connexion SSH. Latence voyage à l'intérieur de l'événement `state` existant / `ssh:state` Charge utile IPC: ```js latency: { pingMs: 24.1, sshRttMs: 31.25, measuredAt: "…" } ``` Les numéros non disponibles sont `null`. L'indicateur terminal compact utilise des millisecondes, du texte non disponible localisé et des étiquettes Czech/German/English. Il se cache en déconnexion. Aucune autre capacité d'exécution du rendu ou demande de la CIB n'était nécessaire. ## Validation et limites opérationnelles - Exécuter à partir de `app/`: `npm ci`, puis `npm test`. - Résultat final local: **179 essais; 163 passé, 0 échoué, 16 Évacuation**. Tous les skips sont les cas du système de fichiers Linux sur cet hôte macOS. `npm ci`, compilation syntaxique Python et `git diff --check` ont été complétés avec succès. - Les tests couvrent Core sauvegarde/récupération, protocole sudo et réécriture de mot de passe, réel shell POSIX citant des chemins hostiles, des conflits, des téléchargements, un nettoyage échoué, des résultats incertains, des documents concurrents, des permissions de CIB et le cycle de vie de latence. - Linux tests de système de fichiers exercice le point d'entrée Python expédié, en utilisant un privé test account-home searchup: ownering/mode/xattrs, POSIX ACLs, symlinks/hardlinks, FIFOs, pannes de téléchargement et de métadonnées, défaillances de remplacement, courses cibles, résultats de post-replacement inconnus et récupération. La mise en place d'un système de fichiers croisé utilise `/dev/shm` et un autre système de fichiers lorsque disponible. Ces tests sautent sur des hôtes non Linux ; les installations manquantes de ACL/segate-filesystem sont explicitement ignorées. - La fonction d'actions Linux GitHub supplémentaire exécute la suite complète et répète le système de fichiers les cas comme racine. Ce workflow n'a pas été envoyé depuis cet arbre de travail. - La validation locale était sur macOS. La syntaxe source de Python a été cochée avec le Outils de ligne de commande Python exécutable. Un vrai contrôle de la fumée ICMP en boucle macOS retourné `0.071 ms`. Pas de télécommande en direct SSH serveur, Windows durée d'exécution, Linux l'exécution, le déploiement de SELinux ou l'interface utilisateur Monaco externe ont été testés localement. - L'édition de texte à distance nécessite désormais Linux et Python 3 avec descripteur-relative prise en charge du système de fichiers/xattr. Un interprète manquant échoue explicitement. Ce noyau refuse intentionnellement les métadonnées, les liens et les configurations de répertoires non sécuritaires. - Verrouillage est un conseil: les processus non coopératifs peuvent encore courir dans l'étroit intervalle entre la dernière vérification de base et le renomm atomique. Linux ne fournit aucune opération générale de comparaison et de remplacement du contenu atomique. Les vérifications détectent les changements avant cet intervalle; les copies de travail conservées supportent la récupération après. - Les données de récupération restent sur le compte distant jusqu'à un nettoyage confirmé. Incomplète, Les revues conflictuelles et inspectables ne sont jamais écartées silencieusement. Il n'y a pas d'expiration automatique du fichier de récupération et aucune option d'écrasement forcé. - `npm ci` a fait état des résultats de l'audit de dépendance 17 (9 modéré, 8 élevé). Ce changement ne change pas les dépendances ou le modèle de confiance mis à jour de l'application. L'utilisateur a demandé à conserver des modifications dans l'arborescence de travail existante, actuellement `feature/hash-checksum-plugin`; aucun commutateur de branchement ou nettoyage non lié n'a été effectué. ## Fichiers modifiés pour cette tâche - `src/main/files/remoteFileService.js` - `src/main/files/remoteEditor.py` (nouveau) - `src/main/sessions/sessionManager.js` - `src/main/sessions/latencyMonitor.js` (nouveau) - `src/main/plugins/pluginRuntime.js` - `src/preload/pluginPreload.js` - `src/renderer/app.js` - `src/renderer/index.html` - `src/renderer/styles.css` - `src/renderer/i18n.js` - `test/remoteFileService.test.js` - `test/sessionManager.test.js` - `test/pluginRuntime.test.js` - `test/remoteEditor.test.js` (nouveau) - `test/remoteEditorProtocol.test.js` (nouveau) - `test/remoteEditorLinux.test.js` (nouveau) - `test/fixtures/remoteEditorLinux.py` (nouveau) - `test/latencyMonitor.test.js` (nouveau) - `README.md` - `docs/remote-editor-latency.md` (ce fichier) - `../.github/workflows/remote-editor-tests.yml` (nouveau)