docs: eingebettetes Pad — Update-Poller als Ursache ausgeschlossen (D31)

Gemeldet: Das eingebettete Etherpad lässt sich nach einer Weile nicht mehr
bearbeiten; Verdacht auf den Update-Poller. Der ist es nicht, und das ist
belegt statt vermutet:

- `checkForUpdates()` holt `location.href`, also den Werkbaum-Origin — es kann
  die Pad-Drosselung gar nicht auslösen.
- Es lädt die Seite nicht neu; `checkAndShowUpdateNotification()` und
  `showUpdateDebug()` hängen nur `position:fixed`-Elemente an `<body>`. Kein
  Neuaufbau eines Containers um den Rahmen — der WÜRDE ihn neu laden, weil ein
  Umhängen im DOM jeden `<iframe>` neu lädt.
- Gemessen über ~6 Minuten: window-Marker überlebt (kein Seiten-Reload),
  `load`-Zähler am Rahmen bleibt 0 (kein Rahmen-Reload), Sichtbarkeit
  durchgehend `visible`.

Reproduziert wurde der Fehler nicht. Nach sechs Minuten lief die Verbindung
noch — geprüft ohne Tippen, indem das Pad von außen geändert wurde: der Rahmen
übernahm die Änderung sofort. Etherpads eigene Meldungen sind von außen nicht
lesbar (fremdstämmiger Rahmen, eigener Konsolen-Kontext).

Als Verdacht festgehalten, ausdrücklich unbewiesen: das `SameSite=Lax`-Cookie.
Die erste Verbindung gelingt, aber beim Wiederaufbau nach einem Abbruch fehlt
die Autoren-Identität — sichtbar, aber nicht mehr beschreibbar. Passt zu „nach
einer Weile" und dazu, dass es im eigenen Tab nicht auftritt.

Der entscheidende Test gehört dem, der es sieht: Pad im eigenen Tab öffnen.
Geht es dort, ist es der Dritt-Kontext (nur serverseitig zu beheben). Klemmt es
dort auch, liegt es am Pad.

Behelf ist schon eingebaut: Einmal durch den Ansichts-Wähler schalten lädt den
Rahmen neu (über `about:blank`). Bewusst NICHT in den Neu-laden-Knopf gelegt —
der zieht nach dem Tippen Spiegel und Diagramm nach, und ein Rahmen-Reload
dabei kostete jedes Mal die Schreibmarke im Pad.
This commit is contained in:
mhoennig
2026-07-30 13:38:19 +02:00
parent 816a77d9e7
commit 6917b420d8
4 changed files with 65 additions and 4 deletions
+6 -1
View File
@@ -139,7 +139,12 @@ löscht.
für jeden lesbar, der die Adresse kennt. Im eingebetteten Rahmen wird Etherpads
Autoren-Cookie (`SameSite=Lax`) nicht mitgesendet — man gilt bei jedem Laden als
neuer Autor, was nur serverseitig zu beheben ist (`cookie.sameSite: "None"`).
Siehe `docs/DECISIONS.md` D31 und D32.
Aus demselben Grund ist der eingebettete Rahmen vor allem zum **Mitlesen** gut:
Sollte das Bearbeiten darin einmal aufhören zu funktionieren, den Ansichts-Wähler
einmal durchschalten (das lädt den Rahmen neu) oder über „im Pad bearbeiten" im
eigenen Tab weiterarbeiten, wo das Cookie gilt. Siehe `docs/DECISIONS.md` D31
und D32.
### Lokal ausführen
+6 -2
View File
@@ -131,8 +131,12 @@ ordinary label. It stays in the text until someone deletes it.
**Be aware:** your plan text then lives on third-party infrastructure, and a pad
is readable by anyone who knows its address. In an embedded frame Etherpad's
author cookie (`SameSite=Lax`) is not sent, so you count as a new author on every
load — fixable only on the server (`cookie.sameSite: "None"`). See
`docs/DECISIONS.md` D31 and D32.
load — fixable only on the server (`cookie.sameSite: "None"`).
For the same reason the **embedded frame is best for reading along**: if editing
in it ever stops working, cycle the view selector once (that reloads the frame),
or use the "edit in the pad" button and work in the pad's own tab, where the
cookie does apply. See `docs/DECISIONS.md` D31 and D32.
### Running it locally
+46
View File
@@ -1238,3 +1238,49 @@ Notwendigkeit (§3) — test-abgedeckt, damit niemand später Status oder `optio
daran koppelt. **Nicht** in das kanonische Beispiel (SPEC §10) aufgenommen: Das
ist zugleich Test-Fixture, und ein dauerhafter Zeigefinger darin wäre eine
Aussage, die niemand gemacht hat.
**Nachtrag zu D31 — „der eingebettete Rahmen lässt sich nach einer Weile nicht
mehr bearbeiten".** Gemeldet vom Nutzer, mit dem Verdacht, es hänge am
Update-Poller. **Der ist es nicht**, und das ist belegbar statt vermutet:
- `checkForUpdates()` holt `location.href`, also den **Werkbaum**-Origin. Es kann
die Drosselung des Pads (10 Abrufe je 90 s, siehe oben) gar nicht auslösen.
- Es lädt die Seite nicht neu, sondern zeigt nur ein Banner;
`checkAndShowUpdateNotification()` und `showUpdateDebug()` hängen ausschließlich
`position:fixed`-Elemente an `<body>` — kein Neuaufbau eines Containers, in dem
der Rahmen steckt (das *würde* ihn neu laden, denn ein Umhängen im DOM lädt
jeden `<iframe>` neu).
- Gemessen über ~6 Minuten mit sichtbarem Tab: Marker auf `window` überlebt
(kein Seiten-Reload), ein `load`-Zähler am Rahmen bleibt bei **0** (kein
Rahmen-Reload), Sichtbarkeit durchgehend `visible`.
**Reproduziert wurde der Fehler nicht.** Nach sechs Minuten war die Verbindung
noch lebendig — geprüft ohne Tippen, indem das Pad von außen geändert wurde: Der
Rahmen übernahm die Änderung sofort, seine Socket-Verbindung lief also. Etherpads
eigene Meldungen sind von außen nicht lesbar (fremdstämmiger Rahmen, eigener
Konsolen-Kontext), eine Instrumentierung von unserer Seite gibt es dafür nicht.
**Verdacht, ausdrücklich unbewiesen:** das `SameSite=Lax`-Cookie (siehe oben).
Die erste Verbindung gelingt, aber Etherpads Autoren-Token wird im
fremdstämmigen Rahmen nicht mitgesendet. Bricht die Socket-Verbindung später
einmal ab (Netzwechsel, Standby, Timer-Drosselung eines Hintergrund-Tabs), fehlt
beim Wiederaufbau die Identität — und ein Etherpad ohne gültige Sitzung ist genau
das: sichtbar, aber nicht mehr beschreibbar. Das passt zu „nach einer Weile" und
dazu, dass es im eigenen Tab (erstanbieter-Kontext, Cookie wird gesendet) nicht
auftritt.
**Der Test, der es entscheidet**, gehört in die Hand dessen, der es sieht: Wenn
es wieder klemmt, das Pad über den „im Pad bearbeiten"-Knopf im **eigenen Tab**
öffnen. Geht es dort, ist es der Dritt-Kontext (dann hilft nur serverseitig
`cookie.sameSite: "None"`). Klemmt es dort auch, liegt es am Pad selbst.
**Behelf, der schon eingebaut ist:** Den Ansichts-Wähler einmal durchschalten
lädt den Rahmen neu — „nur Text" setzt `src` auf `about:blank`, zurück auf „beide"
setzt die Pad-Adresse wieder ein, und das ist ein vollständiger Neuaufbau samt
Verbindung. Bewusst **nicht** in den Neu-laden-Knopf gelegt: Dessen Zweck ist,
nach dem Tippen im Pad Spiegel und Diagramm nachzuziehen — würde er dabei den
Rahmen neu laden, verlöre man bei jedem Diagramm-Update die Schreibmarke im Pad.
**Haltung daraus:** Der Rahmen ist zum **Mitlesen** gut; für längeres Schreiben
ist der eigene Tab die verlässliche Fläche, solange das Cookie nicht
serverseitig auf `SameSite=None` steht.
+7 -1
View File
@@ -169,7 +169,13 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der
`revealEditor()` schaltet 'pad' → 'both', sonst zeigte der Sprung (D25) ins
Nichts. Das Markup: `#srcArea` umschließt Rahmen + Splitter + `#src`, damit die
Legenden-Aufteilung unberührt bleibt — `.editor-body textarea` ist ein
Nachfahren-Selektor und greift weiter.
Nachfahren-Selektor und greift weiter. Nebenwirkung, die als Behelf taugt:
Einmal durch die Ansichten schalten **lädt den Rahmen neu** (über
`about:blank`) — das ist der Ausweg, wenn ein eingebettetes Pad nicht mehr
beschreibbar ist. Nicht in den Neu-laden-Knopf legen: der zieht nach dem Tippen
Spiegel und Diagramm nach, und ein Rahmen-Reload dabei kostete jedes Mal die
Schreibmarke im Pad. **Umhängen im DOM lädt jeden `<iframe>` neu** — wer
Container um `#srcArea` herum neu aufbaut, wirft die Pad-Sitzung weg.
- Fokusmarke `!!!` (D32, SPEC §1): Parser setzt `focus`, Renderer die Klasse
`focusmark`, CSS teilt die Regel mit `.node.current` (ein Begriff „hier
schauen"). Erkannt **nur alleinstehend**`(^|\s)!!!(?=\s|$)`, bewusst ohne