> Revizuirea lingvistică a acestei traduceri este în curs. Pentru pasaje neclare, consultați [originalul în engleză](https://www.sm.ch-j.eu/docs/i18n/en/remote-editor-latency.md). # Salvare editor la distanță și monitorizare latență ## Cauze profunde Editorul anterior a încărcat fișierul său de lucru în directorul mamă al țintei, care adesea nu poate fi scris de contul SSH sub `/etc` sau `/var`. Renumele SFTP nu a furnizat cale sudo autorizată, verificarea de bază a conflictelor, verificarea metadatelor de securitate sau suprascrierea semantică fiabilă. Manipulatorul său de erori a şters copia temporară, eliminând materialul de recuperare chiar şi atunci când finalizarea era incertă. Starea sesiunii a fost expusă anterior numai stării conexiunii. Nu a existat nici o măsurătoare de răspuns ICMP sau SSH autentificată care să alimenteze indicatorul terminal. ## Salvează protocolul 1. Un helper fix SSH deschide un fişier obişnuit, cu un singur link folosind descriptor-relativ operațiuni și `O_NOFOLLOW` pentru fiecare componentă de cale. Acesta surprinde conținutul, SHA-256 hash, dispozitiv/inode, UID, GID, biți de permisiune completă, nanosecunde de modificare / timpi de schimbare și toate atributele extinse lizibile. Core verifică hash și decodează strict UTF-8, păstrând o BOM. Fiecare document devine un `editId` opac, amplificat la modulul său, sesiune terminală și identitatea serverului. 2. O operaţiune de pregătire neprivilegiată rezolvă situaţia contului autentificat acasă prin `pwd.getpwuid(os.getuid())`, creează `$HOME/ch-j-sm/` cu modul `0700` și creează un jurnal de recuperare privat, exclusiv. O casă nesigură, un spațiu de lucru simlink sau un spațiu de muncă deținut de un alt cont este respinsă. 3. Core uploads a hidden, aleatoare 128-bit `.tmp` file working through SFTP with creație exclusivă (`wx`), modul `0600` și un canal de 60 secunde/timeout de încărcare. Revista conţine ţinta, baza iniţială şi haşişul de lucru aşteptat; nu conţine nici o acreditare. 4. **one SSH exec efectuează întreaga finalizare**, opțional prin intermediul executor sudo existent. Ajutorul se deschide în condiții de siguranță și hashes copia privată de lucru și o spală. Încuie inodul original, îşi verifică baza de referinţă, creează un fişier exclusiv de destinaţie lângă ţintă, scrie tot conţinutul, aplică şi verifică metadatele, verifică originalul din nou şi spală înlocuitorul. 5. Același document `os.replace` înlocuiește ţinta în mod atomic. Parintele directorul este spălat și calea finală, hash, inod și metadate sunt verificate. Calea originală rămâne disponibilă până la înlocuire. Fișierul de lucru nu este niciodată mutat prin sisteme de fișiere și nu este niciodată eliminat prin finalizare. 6. După ce Core primeşte un succes verificat, o curăţare separată reverifică finala conținutul și metadatele de securitate înainte de a elimina fișierul de lucru și jurnalul. Eşecul de curăţare raportează încă o salvare confirmată cu `recoveryAvailable: true`. O încărcare eșuată, sudo eșuat, conflict, eroare de metadate sau înlocuire eșuată păstrează materialul original și orice material înscenat. Încărcăturile incomplete sunt identificate ca atare și nu pot fi recuperate ca un document complet editat. Lost SSH comunicare, lipsa statutului de ieșire, timeouts și rezultatele neașteptate de finalizare sunt raportate ca **unnown**, niciodată ca salvat. Nucleul blochează o altă salvare pe un document nesigur; nu există nici o rejudecare automată. ## Metadate, privilegii și limite de siguranță Ajutorul păstrează și verifică UID, GID și toate biții de permisiune POSIX, inclusiv executabile, setuid, setgid și biți lipicioase. Se reproduce Linux atribute extinse octet pentru byte, inclusiv ACL-uri POSIX, capacități și etichete SELinux. Proprietatea și conținutul de fișiere sunt stabilite înaintea atributelor de securitate, deoarece scrie / Crown poate șterge capacitățile sau biți de permisiune speciale. Se elimină atributele de destinație moștenite care lipsesc pe original. Timpul de modificare reflectă noua scriere și nu este copiat din original. Un atribut necitit sau nereprezentabil anulează operațiunea; metadatele nu sunt retrase în tăcere. Semnăturile IMA/EVM sunt respinse în mod explicit, deoarece copiile de conținut/semnături de integritate legate de inoziuni le-ar invalida. Symlink-uri în calea țintă sau acasă, fișiere hard-legate și fișiere neregulate sunt respinse. Nu se utilizează nicio suprascriere a redundanței SFTP în loc sau mai slabă. Obisnuita salveaza ca SSH. Salvările protejate necesită `{ sudo: true }` explicit; o parolă sudo este opțională pentru sudo fără parole. Parolele sunt validate și transmise doar pe canalul stdin, niciodată în interiorul comenzii, jurnal, fișier de lucru, logger sau eroare la distanță. Sesiunile Root SSH folosesc executorul direct existent. Autorizaţia eşuată lasă copia originală şi funcţională intactă. Toate salvările executate ca rădăcină (rădăcină directă SSH sau sudo) resping, de asemenea, directoarele-țintă/cancerul deținut sau scris de alte conturi, sau care transportă un ACL acces, în loc să aibă încredere într-un nume de cale privilegiat controlat de un alt cont. Ajutorul fix ruleaza cu `python3 -I -B`: ignora traseele Python utilizator, directorul de lucru și pachetele site-ului de utilizator, și scrie nici un cod bytecode. Căile și argumentele JSON sunt citate în Core. Modulele nu primesc niciodată mânere arbitrare SSH exec sau SFTP. Sandbox existent, CSP, permisiuni manifeste, verificarea cheii-gazdă și verificarea actualizărilor rămân în uz. ## Modul API și integrarea Monaco rămasă ** Distribuit separat Monaco / File Manager UI este absent de la acest checkout. Integrarea UI, sudo promptă, manipularea și traducerile murdare-buffer nu au putut fi implementate sau testate aici.** Sursa de plugin pachet este modulul Hash & Checksum. Nu a fost inventată nici o sursă înlocuitoare de director de fișiere. Metodele existente rămân disponibile. Metodele/opțiunile aditive sunt expuse la sarcina preîncărcată cu nisip și timpul de funcționare controlat prin permisiune: ```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. ``` Metodele de recuperare acceptă un argument final opțional `{ sudo: true, sudoPassword }` atunci când se inspectează o țintă necesită elevație. Ei păstrează spațiul de lucru autentificat al utilizatorului chiar și atunci când este executat prin sudo. Jurnalele supravieţuiesc repornirii aplicaţiei şi reconectării SSH; recuperarea nu repetă automat finalizarea. Revizuirea unui tampon recuperat în raport cu o țintă recent deschisă înainte de a-l salva explicit. Gărzile `files.read` citesc, inspectează şi eliberează mânerul. Gardienii `files.write` salvează şi recuperează curăţenia. `writeText` încă respinge eșecul pentru modulele existente; `saveText` întoarce un plic structurat `{ ok, value/error }` deoarece Electron scade proprietățile personalizate pe obiecte de eroare respinse. Un trei-argument moștenitor `writeText` poate folosi baza unui singur document deschis. Mai multe documente live pentru aceeași cale necesită `editId`; apelurile moștenite ambigue nu reușesc în condiții de siguranță în loc de a alege un alt document de bază. Modulele ar trebui să elibereze mânere neutilizate. UI extern trebuie să afișeze salvarea imediat, să păstreze tampoanele murdare pe eșec, să ofere sudo numai după permisiune / eșecuri de autentificare, să arate conflicte fără suprascriere, și să ofere recuperare după pierderea conexiunii sau un rezultat necunoscut. Trebuie să traducă aceste state în cehă, germană şi engleză. Copie de stat sugerată: | 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 | ## Definiţii privind latenţia şi ciclul de viaţă **Ping** este latența raportată de un răspuns real al ICMP-ului client la IP-ul rezolvat utilizat de SSH. Core invocă platforma ping executabil cu un array argument fix, fără o coajă sau cerința de pornire a administratorului. Linux, macOS (inclusiv `ping6`) și argumentele Windows sunt selectate separat. ICMP blocat, un executabil lipsă, un timeout, ieșire invalidă sau un răspuns Windows exclusiv legat în sus, cum ar fi `<1ms` produce o valoare indisponibilă, nu un număr inventat. **SSH RTT** este monton `performance.now()` durata unui fix `true` cerere exec privind autentificarea existentă SSH Client. Acesta include configurarea canalului, procesarea serverelor și livrarea răspunsului; nu este pură durata de conectare RTT sau SSH. Indiciul de instrument tradus explică această distincție. Monitorizarea începe imediat ce terminalul se conectează. Sondele funcţionează simultan şi asincronic, cu o cerere de cinci secunde / pauză proces. Următorul eșantion este programat la douăsprezece secunde după ce eșantionul anterior se completează, prevenind suprapunerea. Deconectează Anulează ICMP, curăță cronometrele, anulează în așteptarea lucrului SSH și elimină valorile. Controalele de identitate împiedică publicarea unei conexiuni anterioare după reconectare. Eroarea ICMP nu schimbă niciodată starea conexiunii SSH. Latenta calatoreste in cadrul evenimentului `state` existent / `ssh:state` Incarcatura utila IPC: ```js latency: { pingMs: 24.1, sshRttMs: 31.25, measuredAt: "…" } ``` Numerele disponibile sunt `null`. Indicatorul terminal compact utilizează milisecunde, text indisponibil localizat și etichete Czech/German/English. Se ascunde la deconectare. Nu a fost necesară nicio capacitate suplimentară de execuție a randorului sau cerere de CPI. ## Validarea și limitele operaționale - Rulați de la `app/`: `npm ci`, apoi `npm test`. - Rezultatul final local: **179 încercări; 163 a trecut, 0 a eșuat; 16 a sărit**. Toate salturile sunt cazurile sistemului de fișiere Linux pe această gazdă macOS. `npm ci`, compilația sintaxă Python și `git diff --check` s-au finalizat cu succes. - Testele acoperă Core salvează/recuperează, sudo protocol și parola de redactare; real POSIX coajă citând căi ostile, conflicte, upload-uri, curățare eșuată, rezultate incerte, documente concurente, permisiuni IPC și ciclu de viață latență. - Testele sistemului de fișiere Linux exercită punctul de intrare Python expediat, folosind un privat căutare cont-home test: proprietate/mode/xattrs, ACL POSIX, simlinks/hardlinks, FIFO-uri, eşecuri de încărcare şi metadate, eşecurile de înlocuire, cursele ţintă, rezultatele post-relocare necunoscute şi recuperare. Montarea sistemului de fișiere încrucișate utilizează `/dev/shm` și un alt sistem de fișiere atunci când este disponibil. Aceste teste sar peste gazdele non-Linux; lipsa facilităților ACL/separat-filesystem sunt omise în mod explicit. - Jobul adăugat Linux GitHub Acţiuni rulează suita completă şi repetă sistemul de fişiere cazuri ca rădăcină. Acest flux de lucru nu a fost expediat din acest arbore de lucru. - Validarea locală a fost pe macOS. Sintaxa python sursă a fost verificat cu direct Tools de comandă Python executabil. Un real macOS Loopback ICMP smoke check returned `0.071 ms`. Nu live de la distanță SSH server, Windows runtime, Linux Runtime, SELinux implementare sau exterior Monaco UI a fost testat local. - Editarea la distanță a textului necesită acum Linux și Python 3 cu descriptor-relativ suport filesystem/xattr. Un interpret dispărut nu reuşeşte în mod explicit. Acest Core refuză în mod intenționat metadate nesigure, link-uri și configurații directoare. - Blocarea este consultativă: procesele necooperante pot concura încă îngust intervalul dintre ultima verificare de bază și redenumirea atomică. Linux nu furnizează nicio operațiune generală de comparare și relocare a conținutului atomic. Controalele detectează modificări înainte de acel interval; au păstrat copiile de lucru care susţin recuperarea după aceea. - Datele de recuperare rămân în contul de la distanță până la o curățare confirmată. Incomplet, Jurnalele contradictorii şi nesupravegheabile nu sunt niciodată aruncate în tăcere. Nu există nici o recuperare automată a fişierului de expirare şi nici o opţiune forţată suprascrie. - `npm ci` a raportat constatările auditului dependenței de 17 (9 moderat, 8 ridicat). Această schimbare nu schimbă dependențele sau modelul de încredere actualizat al aplicației. Utilizatorul a solicitat mentinerea modificarilor in arborele de lucru existent, in prezent `feature/hash-checksum-plugin`; nu s-a efectuat nici un comutator de ramura sau curatenie neintrerupta. ## Fișiere schimbate pentru această sarcină - `src/main/files/remoteFileService.js` - `src/main/files/remoteEditor.py` - `src/main/sessions/sessionManager.js` - `src/main/sessions/latencyMonitor.js` - `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` - `test/remoteEditorProtocol.test.js` - `test/remoteEditorLinux.test.js` - `test/fixtures/remoteEditorLinux.py` - `test/latencyMonitor.test.js` - `README.md` - `docs/remote-editor-latency.md` (acest fișier) - `../.github/workflows/remote-editor-tests.yml`