# Remote-Editor speichern und Latenzüberwachung ## Ursachen Der vorherige Editor hat seine Arbeitsdatei in das übergeordnete Verzeichnis des Ziels hochgeladen, welches oft nicht vom SSH-Konto unter `/etc` oder `/var` geschrieben werden kann. SFTP umbenennen lieferte keine autorisierte sudo Pfad, Ausgangskonfliktkontrolle, Sicherheit Metadaten Verifizierung oder zuverlässige Überschreiben Semantik. Sein Fehler-Handler löschte die temporäre Kopie, das Entfernen von Recovery-Material auch wenn die Fertigstellung unsicher war. Sitzungsstatus zuvor nur den Verbindungszustand ausgesetzt. Es gab keine ICMP oder authentifizierte SSH Ansprechmessung, die den Terminal-Indikator fütterte. ## Protokoll speichern 1. Ein fester SSH-Helfer öffnet eine reguläre, Single-Link-Datei mit Deskriptor-relativ Operationen und `O_NOFOLLOW` für jede Pfadkomponente. Es erfasst den Inhalt, SHA-256 Hash, Device/Inode, UID, GID, komplette Berechtigungsbits, Nanosekunden-Änderung/Änderungszeiten und alle lesbaren erweiterten Attribute. Core überprüft den Hash und entschlüsselt strenge UTF-8, Erhaltung einer BOM. Jedes Dokument erhält eine undurchsichtige `editId`, die auf seine Plugin-, Terminal-Session und Server-Identität scoped. 2. Eine nichtprivilegierte Vorbereitungsoperation löst das authentifizierte Konto Zuhause durch `pwd.getpwuid(os.getuid())`, erstellt `$HOME/ch-j-sm/` mit Modus `0700` und erstellt ein privates, exklusives Recovery Journal. Ein unsicheres Zuhause, Symlink-Workspace oder Workspace eines anderen Kontos wird abgelehnt. 3. Core lädt eine versteckte, zufällige 128-Bit `.tmp` Arbeitsdatei über SFTP mit exklusive Erstellung (`wx`), Modus `0600` und ein Sechzig-Sekunden-Kanal/Upload-Timeout. Die Zeitschrift enthält das Ziel, die ursprüngliche Ausgangsbasis und den erwarteten Arbeitshash; sie enthält keine Anmeldeinformationen. 4. **One SSH exec führt die gesamte Finalisierung**, optional durch die vorhandener Sudo-Executor. Der Helfer öffnet sich sicher und hastet die private Arbeitskopie und spült sie. Es sperrt die ursprüngliche Inode, überprüft ihre Basislinie, erstellt eine exklusive Zieldatei neben dem Ziel, schreibt alle Inhalte, gilt und überprüft Metadaten, überprüft das Original erneut und spült den Ersatz. 5. Ein gleiches Verzeichnis `os.replace` ersetzt das Ziel atomar. Die Eltern Verzeichnis wird gespült und der endgültige Pfad, Hash, Inode und Metadaten werden überprüft. Der ursprüngliche Pfad bleibt bis zum Austausch verfügbar. Die Arbeitsdatei wird nie über Dateisysteme verschoben und nie durch Finalisierung entfernt. 6. Nachdem Core einen verifizierten Erfolg erzielt hat, überprüft ein separates Cleanup das Finale Inhalt und Sicherheit Metadaten vor dem Entfernen der Arbeitsdatei und Journal. Nach wie vor meldet ein Bereinigungsfehler einen bestätigten Speicher mit `recoveryAvailable: true`. Ein fehlgeschlagener Upload, gescheitertes Sudo, Konflikt, Metadatenfehler oder fehlgeschlagener Ersatz hält das Original und jedes inszenierte Material. Unvollständige Uploads werden als solche identifiziert und können nicht als komplettes bearbeitetes Dokument wiederhergestellt werden. Verlorene SSH-Kommunikation, fehlender Exit-Status, Timeouts und unerwartete Finalisierungsergebnisse werden als **unknown** gemeldet, nie als gespeichert. Kernblocks ein weiteres Speichern auf einem unsicheren Dokument; es gibt keine automatische Ersatzwiederholung. ## Metadaten, Privilegien und Sicherheitsgrenzen Der Helfer bewahrt und überprüft UID, GID und alle POSIX Berechtigungsbits, einschließlich ausführbarer, setuid, setgid und klebriger Bits. Es reproduziert Linux erweiterte Attribute Byte für Byte, einschließlich POSIX ACLs, Fähigkeiten und SELinux-Labels. Eigentum und Dateiinhalt werden vor Sicherheitsattributen gesetzt, da writes/chown Fähigkeiten oder spezielle Berechtigungsbits freistellen kann. Vererbte Zielattribute, die im Original nicht vorhanden sind, werden entfernt. Die Änderungszeit spiegelt das neue Schreiben wider und wird nicht vom Original kopiert. Ein nicht lesbares oder unrepräsentierbares Attribut beendet die Operation; Metadaten werden nicht stillschweigend gelöscht. IMA/EVM-Signaturen werden explizit abgelehnt, weil das Kopieren von Inhalten/inodengebundenen Integritätssignaturen diese ungültig machen würde. Symlinks im Ziel- oder Heimatpfad, hard-linked Dateien und nicht-reguläre Dateien werden abgelehnt. Es wird kein an Ort und Stelle oder schwächeres SFTP Overwrite Fallback verwendet. Gewöhnliche Schreibweise spart Run als SSH-Konto. Geschützte Speicher erfordern explizites `{ sudo: true }`; ein Sudo-Passwort ist optional für passwortloses sudo. Passwörter werden nur auf Kanal stdin validiert und weitergegeben, niemals im Befehl, Journal, Arbeitsdatei, Logger oder Fernfehler. Root SSH Sessions verwenden den vorhandenen direkten Root-Executor. Fehlerhafte Autorisierung lässt das Original und die Arbeitskopie intakt. Alle als root ausgeführten Saves (direkte Root SSH oder sudo) weisen auch Zielverzeichnisse/Vorstände, die von anderen Konten besessen oder beschreibbar sind, zurück oder führen einen Zugriff auf ACL, anstatt einem privilegierten Pfadnamen zu vertrauen, der von einem anderen Konto kontrolliert wird. Der fixe Helfer läuft mit `python3 -I -B`: er ignoriert die Python-Pfads, das Arbeitsverzeichnis und die Benutzer-Site-Pakete und schreibt keinen Bytecode. Pfade und JSON-Argumente werden in Core Shell-zitiert. Plugins erhalten niemals beliebige SSH exec oder SFTP Griffe. Bestehende sandbox, CSP, manifest Berechtigungen, Host-Taste Überprüfung und Update-Verifikation bleiben im Einsatz. ## Plugin API und verbleibende Monaco-Integration **Die separat verteilte Monaco/File Manager UI fehlt in dieser Kasse. Seine UI-Integration, sudo prompt, schmutzige Pufferhandhabung und Übersetzungen konnten hier nicht implementiert oder getestet werden.** Die gebündelte Pluginquelle ist das Hash & Checksum Plugin. Es wurde keine Ersatzquelle für Dateimanager erfunden. Die bestehenden Methoden sind weiterhin verfügbar. Die Methoden/Optionen für Zusatzstoffe werden durch die Sandbox-Vorladung und die genehmigte Laufzeit ausgesetzt: ```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. ``` Recovery-Methoden akzeptieren ein optionales finales `{ sudo: true, sudoPassword }`-Argument, wenn ein Ziel überprüft wird, erfordert eine Erhöhung. Sie behalten den Workspace des authentifizierten Benutzers, selbst wenn sie durch sudo ausgeführt werden. Journals überleben App-Neustart und SSH wieder verbinden; Wiederherstellung wiederholt nie automatisch Finalisierung. Überprüfen Sie einen wiederhergestellten Puffer gegen ein frisch geöffnetes Ziel, bevor Sie es explizit speichern. `files.read` Wachen liest, Inspektion und Grifffreigabe. `files.write`-Schützen sparen und Wiederherstellung Reinigung. `writeText` weist bei bestehenden Plugins immer noch auf Fehler zurück; `saveText` gibt eine strukturierte `{ ok, value/error }`-Hüllkurve zurück, da Electron benutzerdefinierte Eigenschaften auf abgelehnte Fehlerobjekte fallen lässt. Ein altes Drei-Argument `writeText` kann die Basis eines einzigen offenen Dokuments verwenden. Mehrere Live-Dokumente für denselben Pfad erfordern `editId`; mehrdeutige Legacy-Aufrufe scheitern sicher, anstatt die Basis eines anderen Dokuments auszuwählen. Plugins sollten ungenutzte Griffe freigeben. Die externe Benutzeroberfläche muss sofort Speichern anzeigen, Puffer beim Ausfall schmutzig halten, sudo nur nach Berechtigungs-/Authentifizierungsfehlern anbieten, Konflikte ohne Überschreiben zeigen und eine Erholung nach Verbindungsverlust oder einem unbekannten Ergebnis anbieten. Sie muss diese Staaten in Tschechisch, Deutsch und Englisch übersetzen. Gewünschte Staatskopie: | Staat | Tschechisch | Deutsch | Englisch | | --- | --- | --- | --- | | Speichern | Ukládání... | Wir werden gespeichert... | Sichern... | Sparen | bestätigt | Uloženo | gespeichert | gerettet | | Ausfall | Uložení selhalo | Speichern fehlerhaften | Speichern fehlgeschlagen | | Sudo benötigt | Vyžadováno oprávnění sudo | sudo-Autorisierung erforderlich | Die Sudo-Zulassung erforderlich | | Conflict | Původní soubor byl změněn | Originaldaten wurde geändert | Ursprüngliche Datei geändert | | Nicht angeschlossen | Spojení bylo přerušeno | Verbindung unterbrochen | Anschluss verloren | | Unbekannt | Výsledek uložení není znám | Speichergeschäft unbekannt | Ergebnis speichern unbekannt | | Recovery | Obnova je dostupná | Wiederherstellung verfügbar | Wiederherstellung verfügbar | ## Latenzdefinitionen und Lebenszyklus **Ping** ist die Latenz, die von einer tatsächlichen clientseitigen ICMP-Echoantwort auf die von SSH verwendete aufgelöste IP gemeldet wird. Core ruft die Plattform ping ausführbar asynchron mit einem festen argumentar Array, ohne Shell- oder Administrator-Startanforderung. Die Argumente Linux, macOS (einschließlich `ping6`) und Windows werden separat ausgewählt. Blockierte ICMP, eine fehlende ausführbare Datei, ein Timeout, eine ungültige Ausgabe oder eine Antwort von Windows, wie z.B. `<1ms` erzeugen einen nicht verfügbaren Wert, keine erfundene Nummer. **SSH RTT** ist die monotone `performance.now()` Dauer einer festen `true` Exec Anfrage über den bestehenden authentifizierten SSH Client. Es umfasst Kanal-Setup, Server-Verarbeitung und Antwortbereitstellung; es ist nicht reine Netzwerk RTT oder SSH Login Dauer. Der übersetzte Indikator Tooltip erklärt diese Unterscheidung. Die Überwachung beginnt, sobald das Terminal angeschlossen ist. Sonden laufen gleichzeitig und asynchron, mit einem 5-Sekunden-Request/Process Timeout. Die nächste Probe wird zwölf Sekunden nach Abschluss der vorherigen Probe geplant, wodurch Überschneidungen vermieden werden. Trennen abgebrochen ICMP, löscht Timer, kündigt an SSH Arbeit und löscht Werte. Identitätsprüfungen aufzeichnen verhindern, dass eine vorherige Verbindung nach der Wiederverbindung veröffentlicht wird. ICMP-Fehler ändert nie den Verbindungszustand von SSH. Die Latenz bewegt sich innerhalb der bestehenden `state` Veranstaltung / `ssh:state` IPC Nutzlast: ```js latency: { pingMs: 24.1, sshRttMs: 31.25, measuredAt: "…" } ``` Nicht verfügbare Nummern sind `null`. Der kompakte Endgeräteanzeiger verwendet Millisekunden, lokalisierte nicht verfügbare Texte und tschechische /German/English-Etiketten. Es versteckt sich beim Trennen. Es wurde keine zusätzliche Renderer-Ausführungsfähigkeit oder IPC-Anfrage benötigt. ## Validierungs- und Betriebsgrenzen - Ausführen von `app/`: `npm ci`, dann `npm test`. - Endgültiges lokales Ergebnis: **179-Tests; 163 bestanden, 0 fehlgeschlagen, 16 übersprungen**. Alle überspringen sind die Linux Dateisystem-Fälle auf diesem macOS Host. `npm ci`, Python Syntax-Compilation und `git diff --check` erfolgreich abgeschlossen. - Die Tests umfassen Core spart / recovery, sudo Protokoll und Passwort-Redaktion, echte POSIX Shell-Zitatierung von feindlichen Pfaden, Konflikten, Uploads, fehlgeschlagener Reinigung, unsicheren Ergebnissen, gleichzeitigen Dokumenten, IPC-Berechtigungen und Latenzlebenszyklus. - Linux-Dateisystemtests üben den ausgelieferten Python-Eingangspunkt unter Verwendung eines privaten test-account-home lookup: ownership/mode/xattrs, POSIX ACLs, Symlinks/Hardlinks, FIFOs, Upload- und Metadatenausfälle, Ersatzausfälle, Zielrennen, unbekannte Ergebnisse nach der Replacement-Erholung und Wiederherstellung. Cross-filesystem staging verwendet `/dev/shm` und ein anderes Dateisystem, wenn verfügbar. Diese Tests überspringen auf nicht-Linux Hosts; fehlende ACL/separate-Dateisystem-Einrichtungen werden explizit übersprungen. - Der hinzugefügte Auftrag Linux GitHub Actions führt die komplette Suite aus und wiederholt das Dateisystem Fälle als Wurzel. Dieser Workflow wurde nicht von diesem Arbeitsbaum gesendet. - Die lokale Validierung erfolgte auf macOS. Python-Quellsyntax wurde mit der direkten Befehlszeilen-Werkzeuge Python ausführbar. Ein echter macOS Loopback ICMP Rauchcheck gab `0.071 ms` zurück. Es wurde kein SSH-Server, Windows Runtime, Linux Laufzeit, SELinux-Deployment oder externe Monaco UI lokal getestet. - Die Remote-Textbearbeitung erfordert jetzt Linux und Python 3 mit Deskriptorrelativ Unterstützung von filesystem/xattr. Ein fehlender Dolmetscher schlägt explizit fehl. Dieser Core verweigert absichtlich unsichere Metadaten, Links und Verzeichniskonfigurationen. - Locking ist beratend: Nichtkooperierende Prozesse können noch im Engen laufen Intervall zwischen der letzten Baseline-Kontrolle und dem atomaren Umbenennen. Linux liefert keine allgemeine atomare Inhalt-Hash Vergleich-und-Ersetzen Betrieb. Kontrollen erkennen Änderungen vor diesem Intervall; behaltene Arbeitskopien unterstützen die Wiederherstellung danach. - Wiederherstellung Daten bleibt auf dem Remote-Konto bis zu einer bestätigten Aufräumarbeiten. Unvollständig, konfliktreiche und uninspektible Zeitschriften werden niemals stillschweigend verworfen. Es gibt keine automatische Wiederherstellung-Datei Ablauf und keine erzwungene Überschreiben Option. - `npm ci` berichtete über 17 Abhängigkeitsaudit-Ergebnisse (9 moderat, 8 hoch). Diese Veränderung ändert die Abhängigkeiten oder das Update-Trust-Modell der Anwendung nicht. Der Benutzer forderte Änderungen im bestehenden Arbeitsbaum, z.Z. `feature/hash-checksum-plugin`, auf; es wurde kein Zweigschalter oder keine unabhängige Reinigung durchgeführt. ## Dateien für diese Aufgabe geändert - `src/main/files/remoteFileService.js` - `src/main/files/remoteEditor.py` (neu) - `src/main/sessions/sessionManager.js` - `src/main/sessions/latencyMonitor.js` (neu) - `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` (neu) - `test/remoteEditorProtocol.test.js` (neu) - `test/remoteEditorLinux.test.js` (neu) - `test/fixtures/remoteEditorLinux.py` (neu) - `test/latencyMonitor.test.js` (neu) - `README.md` - `docs/remote-editor-latency.md` (diese Datei) - `../.github/workflows/remote-editor-tests.yml` (neu)