umbau 1.0
This commit is contained in:
169
FORTSETZUNG_Aufgabe11.md
Normal file
169
FORTSETZUNG_Aufgabe11.md
Normal file
@ -0,0 +1,169 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user