170 lines
9.8 KiB
Markdown
170 lines
9.8 KiB
Markdown
# Fortsetzungsdokument: Aufgabe #11 (SSH Copy-Paste + Terminal-Farben)
|
|
|
|
Stand: 2026-09-02, Code-Stand abgeschlossen und regressionsfrei verifiziert;
|
|
Live-Browser-Test weiterhin ausstehend (siehe Abschnitt 3 + Nachtrag in
|
|
Abschnitt 4 -- dieselbe Einschraenkung wie bei Teil F).
|
|
Repo: `ssh_jumphost`, erreichbar ueber die `device_bash`-Bridge unter
|
|
`$HOME/mnt/ssh_jumphost`.
|
|
|
|
**Einordnung**: Aufgabe #11 ist vom Nutzer nachtraeglich hinzugefuegt worden,
|
|
nicht Teil von `Umsetzungsauftrag_Sonnet5.md` und hatte bis zu dieser Session
|
|
keine Detail-Spec -- nur das Stichwort "SSH Copy-Paste + Terminal-Farben"
|
|
(siehe `FORTSETZUNG_Teil_C.md`/`_D.md`/`_F.md`). Das Scope wurde zu Beginn
|
|
dieser Session per Rueckfrage geklaert (zwei AskUserQuestion-Antworten):
|
|
|
|
1. **Copy-Paste**: "kopieren mit markieren des textes und einfuegen mit
|
|
rechtsklick, wenn es umsetzbar ist sonst mit Rechtsklickkontextmenu."
|
|
2. **Terminal-Farben**: "Vom Benutzer waehlbar."
|
|
|
|
Beides betrifft ausschliesslich SSH (`static/js/terminal.js`,
|
|
`SshTerminalSession`) -- RDP hat ueber Guacamole bereits eine eigene,
|
|
funktionierende Zwischenablage-Anbindung (`onclipboard` in `rdp.js`) und war
|
|
nie Teil der Aufgabe (Titel: "**SSH** Copy-Paste").
|
|
|
|
---
|
|
|
|
## 1) SSH Copy-Paste
|
|
|
|
* **Kopieren**: `copyOnSelect: true` bei der `Terminal`-Konstruktion
|
|
(`_setupTerminal()`). xterm.js kopiert eine Markierung damit sofort in die
|
|
System-Zwischenablage -- kein Strg+C/Cmd+C mehr noetig. Strg+C OHNE
|
|
Markierung bleibt unveraendert SIGINT (xterm.js' Standardverhalten, von
|
|
`copyOnSelect` nicht beruehrt -- kein neues Verhalten, keine Ueberraschung
|
|
fuer bestehende Nutzung).
|
|
* **Einfuegen per Rechtsklick**, zweistufig, genau wie gewuenscht:
|
|
1. `contextmenu`-Listener auf `this.terminalContainer`
|
|
(`_wireClipboard()`) ruft `event.preventDefault()` auf (unterdrueckt
|
|
das native Browser-Kontextmenue) und versucht direkt
|
|
`navigator.clipboard.readText()` (`_attemptDirectPaste()`). In den
|
|
meisten Chromium-Browsern reicht ein Rechtsklick als "transiente
|
|
Aktivierung" fuer diese Berechtigung -- Einfuegen passiert dann sofort,
|
|
ohne sichtbares Menue.
|
|
2. Schlaegt das fehl (kein `navigator.clipboard`, Berechtigung verweigert
|
|
-- typischerweise Firefox/Safari ausserhalb einer frischen
|
|
Klick-Geste, oder unsicherer Kontext), erscheint ersatzweise ein
|
|
winziges Kontextmenue mit einem "Einfuegen"-Eintrag (`_showPasteMenu()`).
|
|
Dessen Klick ist selbst wieder eine frische Benutzergeste und hat
|
|
dadurch nochmal bessere Chancen auf die Berechtigung. Schlaegt auch das
|
|
fehl, zeigt der Status-Bereich der Sitzung einen erklaerenden Hinweis
|
|
("... bitte Strg+Umschalt+V verwenden") statt eines stillen No-Ops.
|
|
3. Das eigentliche Einfuegen laeuft ueber `this.term.paste(text)` (xterm.js
|
|
v5 API, bestaetigt durch `.paste=`-Vorkommen in `vendor/xterm.js`) --
|
|
das ist KEIN separater Codepfad zum normalen Tippen: `paste()` loest
|
|
intern denselben `onData`-Callback aus wie eine Tastatureingabe, geht
|
|
also automatisch durch die bestehende WS-"input"-Sendefunktion.
|
|
* **CSP-Falle vermieden**: der erste Entwurf positionierte das
|
|
Ruecksicherungs-Kontextmenue ueber `menu.style.left/top` an der
|
|
Klickposition -- das haette der Server-CSP (`style-src 'self'`, kein
|
|
`unsafe-inline`) im echten Browser stillschweigend blockiert (dieselbe
|
|
Regel, die JS-gesetzte `element.style`-Aenderungen genauso trifft wie
|
|
`style="..."`-Attribute, siehe app.css-Kopfkommentar zu `.hidden`).
|
|
Ersetzt durch vier feste CSS-Klassen (`.term-paste-menu-{top,bottom}` x
|
|
`{left,right}`, app.css), die je nach Klick-Viertel von `.session-shell`
|
|
gesetzt werden -- keine Pixelgenauigkeit, aber vollstaendig CSP-konform
|
|
und konsistent mit der einzigen im ganzen Projekt verwendeten
|
|
Sichtbarkeits-/Positionierungstechnik (Klassen, nie `.style`).
|
|
* Aufraeumen: `_closePasteMenu()` entfernt das Menue plus seine
|
|
Dokument-Listener (Klick-daneben/Escape/Scroll) -- aufgerufen aus
|
|
`dispose()` UND aus `setActive(false)` (ein Umschalten auf eine andere
|
|
Sitzung soll kein Geister-Kontextmenue im Hintergrund hinterlassen).
|
|
|
|
## 2) Terminal-Farben (vom Benutzer waehlbar)
|
|
|
|
* Vier feste Farbschemata (`TERMINAL_THEMES`, Modul-Konstante):
|
|
Standard (dunkel, bisheriges Verhalten unveraendert als Vorgabe),
|
|
Dunkel/kontrastreich, Solarized Dark, Solarized Light. Bewusst eine kleine
|
|
feste Auswahl statt eines vollen Theme-Editors -- deckt "vom Benutzer
|
|
waehlbar" ab, ohne eine neue Einstellungsseite einzufuehren.
|
|
* `<select class="theme-select">` in der Sitzungs-Toolbar (zwischen
|
|
"Dateitransfer" und dem Status-Text). Aenderung setzt
|
|
`this.term.options.theme = ...` (xterm.js v5: `options` ist ein
|
|
Getter/Setter-Objekt, bestaetigt durch `OptionsService`/`onOptionChange`
|
|
in `vendor/xterm.js` -- kein `setOption()` mehr, das gab es nur bis v4).
|
|
* **Persistenz**: `localStorage` (Schluessel `jumphost_terminal_theme"`),
|
|
rein clientseitig, kein Server-Roundtrip -- konsistent mit der ueblichen
|
|
Behandlung reiner Darstellungspraeferenzen. Bewusst KEIN neues DB-Feld/
|
|
keine neue Migration: die Wahl ist eine Eigenschaft des Browsers/Nutzers
|
|
vor Ort, keine sicherheits- oder audit-relevante Einstellung.
|
|
Try/catch um jeden Zugriff (privater Modus/blockierter Speicher faellt
|
|
dann einfach auf das Standardschema zurueck, kein Fehler).
|
|
* **Scope-Grenze, bewusst so belassen**: die Wahl gilt fuer NEUE
|
|
Sitzungen ab dem Zeitpunkt der Aenderung (liest `localStorage` beim
|
|
Sitzungsaufbau in `_setupTerminal()`) -- sie synchronisiert sich NICHT
|
|
live in andere, gerade schon offene Sitzungen (F4: mehrere gleichzeitige
|
|
Instanzen moeglich). Dieselbe Klasse von Eventual-Consistency wie an
|
|
mehreren anderen Stellen im Projekt bereits akzeptiert (z.B. keine
|
|
Live-Aktualisierung der Sitzungsliste zwischen Tabs, `FORTSETZUNG_Teil_F.md`).
|
|
Ein Wechsel-Knopf in jeder einzelnen Toolbar ist bewusst so belassen statt
|
|
einer neuen globalen Einstellungsseite -- kein Mehrwert gegenueber "einmal
|
|
in einer beliebigen Sitzung waehlen, gilt danach ueberall".
|
|
|
|
## 3) Verifikation
|
|
|
|
* `node --check static/js/terminal.js` -- fehlerfrei.
|
|
* CSS-Klammerbalance (`{`/`}`) in `app.css` geprueft -- ausgeglichen.
|
|
* Voller Regressionslauf ueber alle 23 Testdateien (unveraendert gegenueber
|
|
Teil-F-Stufe F5 -- diese Aufgabe aendert ausschliesslich
|
|
`static/js/terminal.js` und `static/css/app.css`, keine Python-Datei,
|
|
keine Migration, kein Template):
|
|
|
|
| Gruppe | Ergebnis |
|
|
|---|---|
|
|
| csp_compliance/teil_f_schritt2/teil_f_schritt3/teil_f_schritt5 | 22 passed, 0 failed |
|
|
| admin_crud/admin_groups_tokens/audit_chain/auth_flow/phase9 | 36 passed, 1 failed |
|
|
| passwords_totp/pentest_security/phase10/phase11 | 37 passed, 2 failed |
|
|
| phase12/phase13 | 22 passed, 6 failed |
|
|
| phase14/phase15/rbac/teil_d_schritt5/teil_d_schritt6/session_recorder/session_reaper | 29 passed, 9 failed |
|
|
| **Summe** | **146 passed, 18 failed, 164 total** |
|
|
|
|
Identisch zu Teil F Stufe F5 -- dieselben 18 laengst bekannten,
|
|
dokumentierten Fehlschlaege (`FORTSETZUNG_Teil_C.md`), **null neue
|
|
Regressionen**.
|
|
* **Kein Live-Browser-Test moeglich** (dieselbe Sandbox-Einschraenkung wie
|
|
bei Teil F, siehe `FORTSETZUNG_Teil_F.md` Abschnitt 6): weder das direkte
|
|
Rechtsklick-Einfuegen (haengt vom tatsaechlichen Berechtigungsverhalten
|
|
des jeweiligen Browsers ab, nicht vollstaendig durch Code-Lesen
|
|
verifizierbar) noch das Ruecksicherungs-Kontextmenue noch die visuelle
|
|
Wirkung der vier Farbschemata wurden tatsaechlich im Browser
|
|
durchgeklickt. **Empfehlung**: bei Gelegenheit einmal in einem echten
|
|
Chromium- UND einem echten Firefox-Fenster gegenstesten (Chromium deckt
|
|
den Direktpfad ab, Firefox eher den Menue-Fallback) -- am besten zusammen
|
|
mit dem noch ausstehenden F.6-Live-Test aus Teil F, da beide dieselbe
|
|
echte SSH-Zielumgebung brauchen.
|
|
|
|
## 4) Nachtrag: Rueckfrage zum urspruenglichen Symptom
|
|
|
|
Bei der Klaerung des Scopes (Abschnitt oben) kam in einer spaeteren
|
|
Rueckfrage eine praezisere Beschreibung des urspruenglichen Problems: "Ich
|
|
konnte in der SSH-Sitzung nichts mit der linken Maustaste markieren" -- und
|
|
zwar an einem GANZ NORMALEN Shell-Prompt, nicht in einem Vollbild-Programm
|
|
mit eigener Maussteuerung (tmux/vim/htop/...). Das schliesst die
|
|
naheliegendste Erklaerung ("Mausklicks gehen an ein Programm wie tmux, nicht
|
|
an die lokale Markierung -- kein Bug, Standardverhalten jedes Terminals")
|
|
fuer DIESEN konkreten Fall aus.
|
|
|
|
**Wahrscheinlichste Erklaerung** (kein Live-Test moeglich, daher nicht
|
|
absicherbar): xterm.js unterstuetzt Markieren-per-Ziehen schon immer nativ,
|
|
unabhaengig von `copyOnSelect` -- das war also vermutlich nie kaputt. Ohne
|
|
`copyOnSelect` (Zustand VOR dieser Session) landet eine Markierung aber
|
|
NICHT automatisch in der Zwischenablage; der naheliegende Reflex Strg+C
|
|
loest bei xterm.js ohne Markierung SIGINT aus (unveraendertes
|
|
Standardverhalten) -- aus Nutzersicht sieht das exakt so aus wie "Markieren
|
|
geht nicht", obwohl technisch nur der Kopiervorgang danach fehlte. Genau das
|
|
behebt `copyOnSelect: true` (Abschnitt 1 oben): Ziehen MARKIERT UND kopiert
|
|
in einem Schritt, ganz ohne Strg+C.
|
|
|
|
**Zusaetzlich ergaenzt, unabhaengig vom obigen Verdacht**: ein
|
|
`title`-Tooltip auf `.session-terminal` erklaert das (bereits vorher
|
|
bestehende, unveraenderte) Shift+Ziehen-Verhalten fuer den Fall, dass doch
|
|
einmal ein Vollbild-Programm mit eigener Maussteuerung im Spiel ist -- rein
|
|
zusaetzliche Dokumentation direkt in der Oberflaeche, kein neuer Codepfad,
|
|
kein Risiko fuer bestehendes Verhalten.
|
|
|
|
**Weiterhin nicht abschliessend geklaert ohne Live-Test**: ob
|
|
`copyOnSelect: true` das urspruenglich beschriebene Symptom tatsaechlich
|
|
vollstaendig behebt, kann nur der Nutzer selbst durch Ausprobieren
|
|
bestaetigen (Text im Terminal markieren, dann an anderer Stelle einfuegen --
|
|
sollte jetzt ohne Strg+C funktionieren). Sollte es weiterhin nicht gehen,
|
|
ist das ein Hinweis auf eine andere, noch nicht gefundene Ursache und
|
|
braucht eine zweite Runde.
|