<!-- Testrunde 4, 31.07.2026, zehn neue Personas der Zielgruppe.
     Durchschnitt 4.04/10 (Runde 1: 3.80, Runde 2: 4.20, Runde 3: 3.81).
     Noten: 3.1, 3.3, 3.4, 3.4, 4.2, 4.2, 4.3, 4.3, 4.4, 5.8
     ja 0 / vielleicht 0 / nein 10.
     Alle zehn Protokolle lagen vollstaendig vor.
     97 Funde wurden gegengeprueft: 79 BESTAETIGT, 9 TEILWEISE,
     9 GESCHMACKSFRAGE, 0 WIDERLEGT.
     Erstmals wurde Barrierefreiheit getestet (Screenreader-Nutzer). -->

# CloakDrop — Urteil aus Testrunde 4

*Zur Datenlage: Alle zehn Protokolle lagen vollständig vor. Jede Zählung unten ist eine echte Personenzahl, keine Hochrechnung. Zusätzlich wurden 97 einzelne Funde in einer Gegenprobe am Quelltext und am laufenden System nachgestellt. In Abschnitt 6 steht nur, was diese Gegenprobe mit BESTÄTIGT oder TEILWEISE bewertet hat.*

*Neu in dieser Runde: einer der zehn Tester ist blind und arbeitet mit einem Screenreader. Barrierefreiheit wurde damit zum ersten Mal in vier Runden überhaupt geprüft. Das Ergebnis steht in Abschnitt 6 an eigener Stelle.*

---

## 1. Die Note

| | Runde 1 | Runde 2 | Runde 3 | Runde 4 | R3 → R4 |
|---|---|---|---|---|---|
| **Gesamt** | 3,80 | 4,20 | 3,81 | **4,04** | **+0,23** |
| Schlechteste Note | 3,0 | 3,0 | 2,4 | **3,1** | **+0,7** |
| Beste Note | 5,5 | 6,5 | 5,2 | **5,8** | +0,6 |
| Noten unter 3,0 | 0 | 0 | 2 | **0** | −2 |
| „würde nutzen: ja" | 0 von 10 | 0 von 10 | 0 von 10 | **0 von 10** | ±0 |
| „vielleicht" | 0 | 1 | 0 | **0** | ±0 |

**Die Rechnung:** 4,2 + 4,4 + 4,3 + 3,4 + 3,3 + 4,3 + 3,4 + 5,8 + 3,1 + 4,2 = **40,4 : 10 = 4,04**.

**Spanne: 3,1 bis 5,8. Median 4,20.**

Verteilung der zehn Noten:

| Bereich | Anzahl | Wer |
|---|---|---|
| unter 3,0 | **0** | — |
| 3,0 – 3,9 | 4 | Kern 3,1 · Bruhns 3,3 · Reineke 3,4 · J. Reinhardt 3,4 |
| 4,0 – 4,9 | 5 | M. Reinhardt 4,2 · Nadia K. 4,2 · Reiter 4,3 · Serwe 4,3 · Bergmann 4,4 |
| 5,0 und mehr | 1 | Wiedmann 5,8 |

Die Note ist gestiegen, und zwar um 0,23. Sie liegt damit über Runde 1 und Runde 3 — **aber immer noch unter Runde 2 (4,20).** Nach vier Runden und über dreißig umgesetzten Änderungen bewegt sich die Gesamtnote in einem Band von 0,4 Punkten. Das muss man aushalten, bevor man sich über den Zuwachs freut.

Interessanter als der Mittelwert ist, **wo** die Bewegung herkommt. Sie kommt fast vollständig von unten:

- In Runde 3 gab es zwei Noten unter 3,0 (2,4 und 2,6). In Runde 4 keine einzige. Die schlechteste Note der Runde ist eine 3,1.
- Die vier Defekte, die Runde 3 nach unten gezogen haben — Waisen-Bruchstücke, halber „Download all", kaputtes „Copy link again", stiller Hänger bei vollem Speicher —, hatten zusammen **27 Nennungen**. In Runde 4 haben sie zusammen **null**. Alle vier sind weg und keiner ist wiedergekommen.
- Genau das ist der Zuwachs. Er ist echt, er ist verdient, und er ist klein.

Der obere Rand hat sich ebenfalls bewegt, aber der beste Wert kommt wie in Runde 2 von jemandem, der fast nur Handwerk bewertet. Jonas Wiedmann, Site Reliability Engineer, rechnet seine 5,8 selbst vor:

> *„Handwerk 9, Ehrlichkeit 9, Betriebsreife 2 — gewichtet nach dem, was ich bewerte, sind das 5,8."* (Wiedmann, 5,8)

Eine Aufteilung nach Segmenten wie in Runde 3 habe ich diesmal nicht vorgenommen. Das Feld war anders geschnitten: neun von zehn haben Netzwerkmitschnitte gemacht, sieben haben in den Quelltext gesehen, sechs haben aktiv manipuliert. Der Unterschied zwischen „Prüfer" und „Praktiker", der Runde 3 erklärt hat, existiert in dieser Runde nicht mehr — **alle zehn haben geprüft.** Die Spreizung von 3,1 bis 5,8 erklärt sich fast vollständig aus einer einzigen Frage: wie viel Gewicht bekommt nachprüfbares Handwerk gegenüber der Aufgabe, für die jemand gekommen ist.

---

## 2. Was die Reparaturen nach Runde 3 gebracht haben

Dreizehn Änderungen. Ich gehe sie einzeln durch. „bemerkt" zählt Personen, nicht Erwähnungen.

| Änderung | bemerkt | Befund |
|---|---|---|
| Abbruch ohne unsichtbare Bruchstücke, Abbrechen-Knopf, Verlassen-Warnung | **10/10** | Volltreffer. Der meistgefundene Defekt aus Runde 3 hat null Nennungen. |
| Whitespace im Link entfernen statt abschneiden | **10/10** | Volltreffer. Kein einziger Kritikpunkt an der Sache selbst. |
| Passwort: Mindestlänge und wachsende Bremse | **9/10** | Angekommen — und der Mindestlängen-Check schleppt den meistgemeldeten Defekt der Runde mit ein. |
| „Download all" als echtes ZIP | **10/10** | Volltreffer beim Grundfall, zwei neue Fehler im Detail. |
| Vorabprüfung des freien Speichers + Frist je Schreibvorgang | **8/10** | Hänger beseitigt, Sackgasse eingebaut. |
| „Open source" → „Read the code" | **6/10 positiv, 4/10 als Blocker** | Der Widerspruch ist weg, die Forderung bleibt. |
| AAD über Frist, Drop-Id, Index | **5/10** | Reiner Gewinn. Aus 1 Finder in Runde 3 wurden 5 Lobredner. |
| limits.html nennt die Browser-Bindung zuerst | **3/10 ausdrücklich** | Die Runde-3-Beschwerde ist vollständig verschwunden. |
| „Copy link again" trägt das Salz | **2/10** | Repariert, nachgeprüft, keine Beschwerde mehr. |
| Bidi-Filter in Dateinamen | **2/10 positiv, 4/10 negativ** | Halb gemacht. Der Filter fehlt genau dort, wo er wirken würde. |
| Vorspann verschwindet im Fehlerfall | **0/10** | Beschwerde weg, Lob gibt es dafür nicht. |
| Glossar auf dem Stand der App | **0/10** | Dito. |
| Ortszeit, keine Doppeldateien, 44-px-Tippziele, fremdes Artwork raus | **0–1/10** | Dito. |

### Die drei Reparaturen, die vollständig gewirkt haben

**Der Abbruch.** In Runde 3 war das Fund A mit **zehn von zehn Nennungen** — der meistgefundene Defekt aller Runden. In Runde 4 haben neun von zehn den Abbruch aktiv getestet, und alle neun berichten dasselbe: es bleibt nichts liegen.

> *„Abbrechen mitten im Verschlüsseln von 460 MB: nach 0,15 Sekunden zurück in der Dateiliste, Speicherverbrauch von 176 MB auf 68 Kilobyte. Nichts liegengeblieben."* (M. Reinhardt, 4,2)

> *„Der Abbruchknopf mitten in 480 MB quittierte nach 0,3 Sekunden und räumte restlos auf — 0 Datensätze, 0 Bruchstücke, Verbrauch zurück auf 89 KB."* (Nadia K., 4,2)

> *„Abbruch funktioniert unter Last: CPU 20-fach gedrosselt, bei 11 % abgebrochen, Antwort nach 3,86 Sekunden, transfers leer, chunks 0."* (Wiedmann, 5,8)

Auch die „Unfinished"-Marke ist angekommen — acht Personen haben sie ausgelöst, alle acht beschreiben sie als verständlich beschriftet. Drei nennen ausdrücklich die Warnung vor dem Neuladen (Bergmann, Reiter, Serwe). Das ist die beste Reparatur der Runde: ein Defekt mit zehn Nennungen ist auf null gefallen und hat keinen Nachfolger.

Der Rest davon stimmt aber noch nicht: die versprochene Selbstreinigung „next time you open the app" tritt erst nach 120 Sekunden ein. Vier Personen haben das gemessen (§6, Fund E).

**Der Whitespace im Link.** Zehn von zehn haben einen Zeilenumbruch oder ein Leerzeichen in den Schlüssel gesetzt, zehn von zehn berichten, dass der Drop trotzdem aufgeht. Das ist neben dem Abbruch die zweite Änderung mit voller Trefferquote.

> *„Leerzeichen und Zeilenumbrüche werden aus eingefügten Links entfernt statt abgeschnitten. Ein Umbruch mitten im Schlüssel öffnete den Drop trotzdem — Mailprogramme brechen Links um, das ist real gedacht."* (J. Reinhardt, 3,4)

> *„Zeilenumbrüche und Leerzeichen im eingefügten Link werden entfernt statt abgeschnitten — genau der Fall, der bei Mailprogrammen ständig auftritt."* (M. Reinhardt, 4,2)

Was der Fix nicht abdeckt: Satzzeichen und Klammern um den Link herum. Ein Punkt am Satzende bringt weiterhin „That is not a key" (§6, Fund L).

**Die AAD-Bindung.** In Runde 3 war das Fund K mit genau **einem** Finder, und ich habe ihn damals hochgezogen, weil der Beweis sauber war. In Runde 4 haben ihn fünf Personen unabhängig getestet — und alle fünf loben ihn als Sorgfalt, die sie sonst nicht sehen.

> *„Frist auf zehn Jahre vorgestellt, und statt klaglos zu öffnen ist die Entschlüsselung gescheitert, weil die Frist mit im Authentifizierungstag steckt. Das ist die Sorte Sorgfalt, die ich bei kommerziellen Anbietern nicht finde."* (M. Reinhardt, 4,2)

> *„Ich habe die Ablauffrist im Datensatz per Hand auf zehn Jahre gesetzt. Der Drop öffnete danach nicht mehr — die Frist hängt in der AAD des GCM-Tags. Das ist eine Sorgfalt, die ich bei bezahlten Produkten selten sehe."* (Nadia K., 4,2)

> *„Die Ablauffrist hängt kryptografisch am Chiffrat: von Hand um 30 Tage verlängert, scheitert die Entschlüsselung ... statt still durchzugehen."* (Bruhns, 3,3)

Das ist die beste Aufwand-Wirkung-Bilanz der Runde: ein Fund mit einem Melder wurde behoben und ist zu einem Lobpunkt mit fünf geworden.

### Die zwei Reparaturen, die einen Nachfolger mitgebracht haben

**„Download all" als ZIP.** Der Grundfall ist gelöst und wurde von allen zehn benutzt. Neun haben das Archiv ausgepackt und byteweise gegen ihre Originale geprüft. Einer hat die Reparatur ausdrücklich als solche erkannt:

> *„Ein Archiv statt vieler Einzeldownloads — damit ist der Chromium-Deckel von zehn selbsttätigen Downloads umschifft, und zwar erkennbar aus einem echten Testbefund heraus."* (Wiedmann, 5,8)

> *„,Alle herunterladen' baut EIN ZIP statt 43 Einzeldownloads — genau der Fehler, an dem größere Anbieter scheitern."* (Reineke, 3,4)

Der Fehler mit acht Nennungen aus Runde 3 hat jetzt null. Dafür sitzen zwei neue Fehler in dem neuen ZIP-Bauer: zwei gleichnamige Dateien werden stillschweigend zu einer (§6, Fund F), und die Bidi-Bereinigung des Dateinamens wird beim ZIP-Eintrag übersprungen (§6, Fund D).

**Die Vorabprüfung des Speichers.** Der stille Hänger aus Runde 3 (vier Nennungen, gemessene Wartezeiten bis 240 Sekunden) ist vollständig verschwunden — **kein einziger Tester in dieser Runde berichtet von einem Hänger.** Stattdessen kommen jetzt Zahlen:

> *„Voller Speicher wird vorher gemeldet, nicht mittendrin: ,This drop needs about 460.0 MB, and this browser still allows 164.2 MB. Nothing was written.'"* (M. Reinhardt, 4,2)

> *„Speicher künstlich auf 60 MB gedeckelt, 181 MB reingeworfen: nach 0,2 Sekunden klare Meldung ... statt eines Hängers."* (Reiter, 4,3)

Und genau diese Vorabprüfung erzeugt den schärfsten Fund der Runde. Weil sie mit einer Zahl rechnet, die der Browser nach dem Löschen nicht zurücksetzt, sperrt sie dauerhaft und macht den funktionierenden Fehlerzweig dahinter unerreichbar (§6, Fund B). Zwei Personen sind in diese Sackgasse gelaufen und nicht mehr herausgekommen. Dazu widerspricht die Meldung sich in bestimmten Fällen mit ihren eigenen zwei Zahlen (§6, Fund G).

### Die Reparatur, die den meistgemeldeten Defekt der Runde eingeschleppt hat

**Das Passwort-Minimum.** Neun von zehn haben die Mindestlänge ausgelöst, neun von zehn haben die wachsende Bremse mit der Stoppuhr nachgemessen. Beides funktioniert genau so, wie es soll, und wird durchweg gelobt:

> *„Die Bremse gegen Durchprobieren habe ich fünfmal ausgelöst: 0,29 s, 0,71 s, 1,25 s, 2,21 s, 4,24 s, dann 8,31 s. Sie wächst also wirklich."* (M. Reinhardt, 4,2)

> *„Sieben Zeichen werden abgelehnt, mit dem besten Satz, den ich auf einer Softwareseite gelesen habe: ,a short one is worse than none — it looks like protection without being any.'"* (Bergmann, 4,4)

Nur: die Ablehnung eines zu kurzen Passworts läuft über `showError()`, und `showError()` schaltet die gesamte Anwendung in die Empfängeransicht, verwirft die Dateiauswahl und lässt den Nutzer über die Marketingseite zurückkrabbeln. **Sechs Personen sind darüber gestolpert** — das ist der meistgemeldete Defekt dieser Runde (§6, Fund A).

> *„Ich habe zuerst ,9b2026' eingegeben, sechs Zeichen ... Ergebnis: die komplette App verschwindet."* (Bruhns, 3,3)

> *„Ich habe versehentlich ein vierstelliges Passwort gesetzt. Die App hat das richtigerweise abgelehnt — und dabei meine komplette Dateiauswahl weggeworfen. Bei 43 Belegen heißt das: alles noch einmal zusammensuchen."* (Reineke, 3,4)

Das ist dasselbe Muster wie in Runde 3 beim Passwort selbst: eine richtig gebaute Funktion, die an ihrem Rand einen Defekt hinterlässt, den mehr Leute finden als die Funktion Lob bekommt.

### Die fünf Reparaturen, die niemand bemerkt hat

Das ist keine Kritik, sondern eine Regel, die sich jetzt zum dritten Mal bestätigt: **eine gut behobene Schwachstelle ist unsichtbar. Sie verhindert Kritik, sie erzeugt kein Lob.**

- **Vorspann im Fehlerfall** (Runde-3-Fund E, 2 Melder): null Erwähnungen. Kein Tester berichtet mehr von zwei widersprüchlichen Sätzen übereinander.
- **Glossar** (Runde-3-Fund F, 3 Melder): null Erwähnungen. Zwei Tester lesen das Glossar ausdrücklich und finden nichts.
- **Ortszeit statt UTC**: null Erwähnungen. Mehrere Tester zitieren Zeitstempel wie „Cloaked 2026-07-31 19:31" und ordnen sie korrekt ein.
- **44-px-Tippziele**: null Erwähnungen. Kein Tester beschwert sich mehr über zu kleine Knöpfe — auch keiner der drei, die auf dem Handy getestet haben.
- **Fremdes App-Store-Artwork**: null Erwähnungen.

Zwei weitere Änderungen liegen dazwischen: **„Copy link again"** wurde von zwei Personen ausdrücklich nachgeprüft und für richtig befunden (Kern hat den Link „Zeichen für Zeichen" verglichen), der Runde-3-Fund mit fünf Meldern ist damit erledigt. Und **limits.html** nennt die Browser-Bindung jetzt so weit vorn, dass drei Tester sie dort zitieren — die Runde-3-Beschwerde, limits.html verschweige die wichtigste Einschränkung, taucht kein einziges Mal mehr auf.

> *„In limits.html steht es glasklar in einer Tabellenzeile — ,Where a link opens: Only in the browser that created the drop.'"* (Kern, 3,1)

### „Read the code": der Widerspruch ist weg, die Forderung nicht

Sechs Personen zitieren die Seite positiv, und zwar als das stärkste Ehrlichkeitssignal des ganzen Produkts:

> *„Die Seite ,Read the code' sagt ausdrücklich, dass CloakDrop NICHT Open Source ist, sondern nur lesbar. ... Diese Ehrlichkeit ist im Markt eine Ausnahme."* (Bergmann, 4,4)

> *„opensource.html sagt glasklar ,CloakDrop is not open source', nennt es ,readable, not licensed' ... Diese Ehrlichkeit ist in diesem Markt beinahe unanständig selten."* (Nadia K., 4,2)

Der Widerspruch aus Runde 3 (AGPL-Datei im Baum, README nennt eine Lizenz, opensource.html sagt „nicht offen") wird von niemandem mehr genannt. Er ist beseitigt.

Gleichzeitig nennen **vier Personen das fehlende Repository ausdrücklich als Blocker** — Reineke, Serwe, Nadia K. und Wiedmann. Der Kern ihres Einwands hat sich verschoben: es geht nicht mehr um Lizenzfragen, sondern um Nachvollziehbarkeit der Auslieferung.

> *„,lesbar' heißt nicht ,prüfbar', und nichts legt fest, was mir beim nächsten Besuch ausgeliefert wird — die Seite gibt das auf verify.html selbst zu."* (Nadia K., 4,2)

> *„Ich kann keine Fassung einfrieren, die mein Mandant bekommt."* (Reineke, 3,4)

---

## 3. Die Vertrauensfrage

**Zum vierten Mal in Folge: kein einziger Fund gegen den Anbieter. Und zum vierten Mal in Folge kein einziger Fund gegen die Kryptografie.**

Was tatsächlich gemacht wurde:

- **Netzwerkmitschnitt: 10 von 10.** Übereinstimmend null Fremdanfragen. Zahlen aus den Protokollen: 3 Anfragen in der ganzen Sitzung (M. Reinhardt, J. Reinhardt), 7 über drei Browserkontexte (Reineke), 7 im ganzen Test (Serwe), 19 über acht Unterseiten (Bruhns), null Fremdanfragen über sechs Läufe (Kern, Reiter), null über acht Läufe (Wiedmann), null über neun Seiten (Nadia K.), null zwischen Dateiauswahl und Link (Bergmann).
- **Der Quelltext wurde durchgezählt, nicht überflogen.** Drei Tester haben unabhängig nach Netzwerk-APIs gesucht: null Treffer für `fetch`, `XMLHttpRequest`, `WebSocket`, `sendBeacon` (M. Reinhardt, Reineke, Bergmann).
- **Die CSP wurde als Beweis akzeptiert, nicht als Versprechen.** Sechs Personen zitieren `connect-src 'none'` und ziehen daraus dieselbe Folgerung.
- **Bitgenauer Rücklauf: 10 von 10.** Acht davon mit einzeln verglichenen SHA-256-Prüfsummen, bis zu 200 Dateien und 365.715.501 Byte am Stück (Kern).
- **Manipulation aktiv versucht: 6 von 10.** Frist zurückdatiert, Frist auf zehn Jahre vorgestellt, Bit im Chiffrat gekippt, `disabled` per Konsole entfernt — in allen Fällen das richtige Verhalten und die richtige Meldung.

> *„Das ist keine Zusage, das ist eine Sperre."* (Reiter, 4,3, über `connect-src 'none'`)

> *„connect-src 'none' erzwingt es, ich musste es nicht glauben."* (Wiedmann, 5,8)

> *„Die Behauptung ,nothing leaves your device' hält der Messung stand."* (J. Reinhardt, 3,4)

**Was nicht hält, liegt wieder daneben — und diesmal an fünf Stellen:**

1. **Die App ist ohne Netz nicht benutzbar.** Wiedmann hat den Browser offline geschaltet und den eigenen Link aufgerufen: `net::ERR_INTERNET_DISCONNECTED`. Die eigenen Chiffrate liegen auf der eigenen Platte und sind ohne cloakdrop.com unlesbar. Ein Service Worker existiert nicht und kann nicht nachgerüstet werden, weil die eigene CSP `worker-src 'none'` setzt — die Gegenprobe hat das mit einem echten Registrierungsversuch belegt („SecurityError: … violates the Content Security Policy"). Gleichzeitig liefert die Seite ein Manifest mit `"display": "standalone"` aus, ist also installierbar wie eine App.

> *„Eine App, die ohne Netz die eigenen Daten nicht anfassen kann. ... Ein USB-Stick kann das besser. Das ist nicht boshaft gemeint: das ist genau der Vergleich, den ein Kunde zieht."* (Wiedmann, 5,8)

2. **Ein danebenliegender CSP-Skript-Hash tötet die App lautlos.** Wiedmann hat ein Zeichen im Hash verändert und die Seite ausgeliefert: die vollständige Marketingseite rendert tadellos, der Modus bleibt auf „landing", ein Empfangslink zeigt kommentarlos die Startseite. Die einzige Spur ist eine Konsolenzeile. Es gibt kein `noscript`, keine Startprüfung, keine Meldung. Nadia K. hat unabhängig davon dasselbe Bild mit abgeschaltetem JavaScript gemessen: 3.301 Zeichen Werbetext, ein Knopf, der nichts tut.

3. **Die Statusseite behauptet etwas, das sie nicht misst.** Der Status-Worker führt „Email — hello@, abuse@ und security@ — Delivering — 100 % uptime" im Block MEASURED. Gemessen wird ein DNS-Lookup auf den MX-Eintrag. Kein SMTP-Handshake, kein Zustellversuch, kein geleertes Postfach. Für ein Projekt, dessen ganze Haltung „wir behaupten nichts, was wir nicht messen" lautet, steht hier eine Behauptung im falschen Kasten.

4. **Das Größenprofil liegt byte-genau auf der Platte.** Nadia K. hat das Browserprofil geöffnet: jede Blob-Datei ist exakt Klartextlänge plus 38 Byte. Ein 2.927.794-Byte-Foto liegt als 2.927.832-Byte-Datei da, ein Video als fünfzehn Dateien zu je 4.000.038 Byte. Wer das Profil öffnet, kennt ohne jeden Schlüssel die Größenverteilung. Die Seite gibt das auf verify.html zu („It does not hide how much you sent") — in der Oberfläche steht es nicht.

5. **Der Löschknopf löscht die Bruchstücke, aber nicht die Spur.** Nach dem Löschen aller Drops stehen die Drop-Kennungen weiterhin im Klartext in der LevelDB-Datei. Es gibt in der ganzen App keine Funktion, die die Datenbank selbst entfernt. Dazu bittet die App ungefragt mit `navigator.storage.persist()` darum, diese Daten schwerer räumbar zu machen — erwähnt wird das auf keiner Produktseite.

> *„Ein Werkzeug, das Spuren hinterlässt, die es selbst nicht löschen kann, und das nichts transportiert, ist für mich heute unbrauchbar — bei aller Achtung vor der Bauqualität."* (Nadia K., 4,2)

**Zwei Präzisierungen zur Kryptografie**, beide von Nadia K., beide bestätigt und beide klein: die 310.000 PBKDF2-Runden sind die ältere OWASP-Angabe (aktuell 600.000 für HMAC-SHA256), und der Kommentar im Quelltext bezeichnet sie als aktuellen Stand. Und es gibt keinerlei Qualitätsprüfung des Passworts — „12345678" und „password" werden angenommen. Ihre Alternative Argon2id ist mit WebCrypto allein nicht erreichbar; das wäre eine Bibliothek und widerspräche dem Ein-Datei-Anspruch. Die Rundenzahl dagegen ist eine Zeile.

---

## 4. Der Aufwand

Hier ist das Produkt weiterhin unangefochten, und in dieser Runde deutlicher als je zuvor.

**Durchsatz, zehn unabhängige Messungen: 85 bis 222 MB/s.**

| Wer | Gemessen |
|---|---|
| M. Reinhardt | 460 MB in 2,1 s (222 MB/s) · 125,6 MB unter 1 s · längste Blockade des Hauptstrangs 26 ms |
| Reiter | 478,2 MB in 2,4 s (~200 MB/s) · 180,7 MB in ~1 s · 120 Dateien in 0,3 s · ZIP 478 MB in 14,1 s |
| Nadia K. | 480 MB nach 1,2 s bei 52 % (>200 MB/s) · 96,5 MB unter 1 s |
| Kern | 200 Fotos / 365,7 MB in 1,77 s · ZIP mit 200 Dateien in 9,3 s |
| Wiedmann | 457,3 MB in 2,3 s · ZIP in 13,4 s · sechs Dateien in 0,47 s |
| Reineke | 314,6 MB in 2,0 s, zurück in 8,3 s · 43 Dateien / 6,2 MB in 0,2 s |
| J. Reinhardt | 222,3 MB nach ~1,5 s bei 100 % |
| Bruhns | 42,6 MB in 0,56 s · 420 MB in ~2,1 s · ZIP in 1,7 s |
| Serwe | 60 Dateien / 157,3 MB in 1,3 s (117 MB/s) · ZIP in 4,5 s |
| Bergmann | 8 PDFs / 12,8 MB in 0,30 s · 150 MB in 1,8 s (~85 MB/s), zurück in 4,2 s |

Sätze zum Aufheben:

> *„Für dieselben 460 MB wartet meine Dropbox im Bauwagen eine gute halbe Stunde."* (M. Reinhardt)
> *„Das ist schneller, als Dropbox den Ordner überhaupt bemerkt."* (Reiter)
> *„WeTransfer braucht für denselben Stapel über meine Leitung vier bis fünf Minuten."* (Kern)
> *„42,6 MB in einer halben Sekunde, das ist schneller als das Landesportal für eine einzelne PDF-Datei braucht."* (Bruhns)
> *„Schneller als jeder Uploader, den ich kenne, weil eben nichts hochgeladen wird."* (Reiter)

**Klicks bis zum kopierten Link:** unverändert vier. Kein Konto, keine Mailadresse, keine Cookiefrage (Kern hat das ausdrücklich gezählt).

**Wo Leute ausgestiegen sind, nach Häufigkeit:**

1. **Der zweite Browserkontext — 10 von 10.** Alle zehn haben denselben Test gemacht, alle zehn sind dort stehengeblieben. Gemessene Zeiten bis zur Meldung: 2,5 s (Nadia K.), 2,52 s (Bruhns), 3,0 s (Kern), 3,2 s (Reiter), 3,3 s (Bergmann), 3,4 s (Reineke, Serwe), ~3 s (Wiedmann). Drei haben es dreimal wiederholt, weil sie es nicht glauben wollten (M. Reinhardt, Reineke, Bruhns). Für neun von zehn ist das der Punkt, an dem der Test faktisch endet.

> *„Das ist keine Einschränkung, das ist die Abwesenheit des Produkts."* (M. Reinhardt, 4,2)
> *„Ein Versandwerkzeug, das nicht versenden kann, ist für mich kein Produkt, sondern eine Vorführung."* (Bergmann, 4,4)
> *„Ein ehrlich beschriebenes Nichtprodukt bleibt ein Nichtprodukt."* (J. Reinhardt, 3,4)

2. **Die Startseite — 6 Nennungen, fünf davon mit gemessenen Positionen.** Das ist das zweitgrößte Ärgernis der Runde und das einzige, bei dem Tester das Wort „unehrlich" benutzen. Gemessen: sichtbarer Startseitentext 3.630 Zeichen; „WhatsApp" bei Position 481 (13 %); „Public preview" bei 3.283 (90 %); „relay" bei 3.304 (91 %). Am Rechner sitzt das Kanalband bei y=652 von 5.224 Pixel Seitenhöhe, der erste klare Widerruf bei y=4.975 — also bei 95 %.

> *„Wer die Unterseiten schreibt, ist ehrlich. Wer die Startseite schreibt, verkauft. Beide arbeiten offenbar an derselben Sache."* (Kern, 3,1)
> *„Wer mir zuerst zu viel verspricht, dem glaube ich die Krypto-Zusagen auch nicht mehr ungeprüft."* (Reiter, 4,3)
> *„Die wichtigste Tatsache über dieses Produkt steht in der unauffälligsten Type der Seite."* (Bergmann, 4,4)
> *„Ich finde das nicht ,ehrlich, aber unfertig'. Ich finde es unehrlich an genau der Stelle, an der die Entscheidung fällt."* (Bruhns, 3,3)

3. **Ein Eingabefehler wirft aus dem Sendeweg — 6 Nennungen.** Siehe §6, Fund A. Reineke musste 43 Belege neu zusammensuchen, Bruhns 28 Scans, J. Reinhardt acht Dateien.

4. **Das Handy — 2 Nennungen, identisch gemessen.** Nach dem Verschlüsseln liegt das Linkfeld bei `top = −249 px`, also 249 Pixel oberhalb des Bildes. Sichtbar und mittig unter dem Daumen liegt „Delete this drop". Serwe und Kern haben unabhängig denselben Wert gemessen.

> *„Der Knopf, den ich brauche, ist unsichtbar; der Knopf, der alles kaputt macht, liegt in der Mitte."* (Kern, 3,1)

Gegenprobe-Präzisierung: der Fehler tritt nur bei einem echten Klick auf „Cloak & create link" auf, weil dieser die Seite herunterrollt. Reineke, der auf dem Handy anders getestet hat, sah das Linkfeld korrekt ins Bild geholt. Beide Messungen stimmen — der Nutzerfall ist der von Serwe und Kern.

5. **Der 500-MB-Deckel — 3 nennen ihn als Blocker.** M. Reinhardt (Plansätze 70–200 MB, Ausführungsplanung 1–3 GB), Reiter (Projekte 2–8 GB), Kern (Monatsstapel 806 MB). Die Grenze selbst wird von allen sauber gemeldet und im Code durchgesetzt; Kritik gibt es nur an der Höhe und daran, dass es keinerlei Hilfe beim Aufteilen gibt.

6. **Kein Übergabenachweis — 5 Nennungen.** M. Reinhardt, Bergmann, Reiter, Reineke und Bruhns nennen unabhängig voneinander, dass sie belegen können müssen, was wann an wen ging. Das ist neu in dieser Schärfe und es ist der einzige Wunsch, der bei zwei Personen gleichrangig neben dem Relay steht.

> *„Für mich wäre ein Sendeprotokoll wichtiger als alle drei zusammen [Inbox, API, reproduzierbare Builds]. ... Es gibt keinen kryptografischen Grund, warum die Übersicht mir verschweigen muss, was ich selbst gerade verpackt habe."* (M. Reinhardt, 4,2)

---

## 5. Wahrheitsprüfung

**Was gehalten hat — jeweils mehrfach unabhängig nachgemessen:**

- *„Nothing is uploaded — you will see no request at all."* — **10/10 bestätigt.** Zum vierten Mal die bestbelegte Aussage des Projekts.
- **„500 MB … the same number the app enforces"** — hält weiterhin. Fünf Personen haben `disabled` per Konsole entfernt und trotzdem geklickt (M. Reinhardt, Bergmann, Reineke, Serwe, Wiedmann). Alle fünf sind an der Prüfung im Code hängengeblieben.
- **Die Frist hängt kryptografisch am Chiffrat** — von fünf Personen mit einer manipulierten Frist geprüft, jedes Mal korrekt gescheitert.
- **Ablauf löscht wirklich** — von sieben Personen mit zurückdatiertem Datensatz geprüft: Link tot, Datensatz und Bruchstücke beim nächsten Start weg.
- **Löschen räumt Datensatz und alle Bruchstücke** — nachgezählt von 55 auf 0 (Reiter), von 77 auf 0 (Serwe), von 4 auf 0 (Wiedmann), von 8,9 MB auf 12.734 Byte (Nadia K.).
- **„Tampering fails loudly"** — diesmal in allen geprüften Varianten bestätigt. Serwe hat sechs verschiedene kaputte Links erzeugt und sechs verschiedene, jeweils richtige Meldungen bekommen. Der Runde-3-Vorwurf, das Manifest melde Manipulation als Copy-Paste-Fehler, taucht nicht mehr auf.
- **Keine Klartext-Dateinamen im Speicher** — von drei Personen im Browserprofil nachgesucht, kein Treffer.
- **Fehlermeldungen behaupten keine Ursache, die sie nicht kennen können** — das meistgelobte Einzelmerkmal der Runde, von acht Personen ausdrücklich genannt.

> *„Die Fehlermeldungen sind die besten, die ich bei einem Web-Werkzeug gesehen habe. Sie nennen die Ursache, schließen aus, was ausgeschlossen ist, und schieben nichts auf mein Copy-Paste, wenn sie es nicht wissen können."* (M. Reinhardt, 4,2)

**Was nicht hält:**

1. **verify.html:1885 verspricht eine Fehlermeldung, die es nicht mehr gibt.** Die Seite fordert auf, ein Zeichen im Schlüssel zu ändern, und sagt, die App melde dann *„The key doesn't fit"*. Die App sagt *„This drop did not open — The authentication tag does not match."* **Fünf unabhängige Finder** (M. Reinhardt, Reiter, Reineke, Bruhns, Serwe). Das ist der meistgefundene Textfehler der Runde, und er sitzt ausgerechnet auf der Seite, deren einziger Zweck das Nachprüfen ist.

> *„Eine Prüfanleitung, deren erwartetes Ergebnis nicht existiert, ist keine Prüfung."* (Reineke, 3,4)
> *„Auf einer Seite, deren einziger Zweck es ist, mich prüfen zu lassen, ob die Behauptungen stimmen, stimmt die Behauptung über die Prüfung nicht. Das ist kein Tippfehler, das ist ein Vertrauensschaden."* (Bruhns, 3,3)

2. **limits.html:1915 und index.html:3210: „Removed next time you open the app".** Für unterbrochene Verschlüsselungen gilt das erst nach 120 Sekunden. Vier Finder mit vier voneinander unabhängigen Messreihen (Bergmann, Reineke, Nadia K., Kern). Reineke hat nach 10, 40, 80 und 130 Sekunden nachgesehen.

> *„Der Satz ist zwei Minuten lang falsch. Das ist keine Katastrophe, aber es ist eine Aussage über den Verbleib von Mandantendaten, und die muss stimmen."* (Reineke, 3,4)

3. **Der Fehlertext behauptet ausdrücklich das Gegenteil dessen, was passiert.** Bei einem verstümmelten Passwort-Link steht im ausgegebenen Text *„A shortened link is already ruled out — that is checked separately."* Genau das ist im Passwortpfad nicht der Fall. Wiedmann ist der Einzige, der das nicht nur im Kommentar, sondern im ausgegebenen Text nachweist.

4. **Die Speichermeldung widerspricht sich mit ihren eigenen Zahlen.** *„This drop needs about 30.0 MB, and this browser still allows 41.9 MB. Nothing was written."* Der Sicherheitsaufschlag von 5 % plus 16 MB kommt im Text nicht vor. Zwei Finder (Reineke, Wiedmann).

5. **Ein Quelltextkommentar behauptet, das Scroll-Problem auf dem Handy sei behoben.** Ist es nicht. Zwei Finder (Serwe, Kern).

> *„Im Code steht sogar der Kommentar, dass genau das schon einmal eine Testerin gemeldet hat."* (Serwe, 4,3)

6. **/status sagt, es gebe noch keine Statusseite — status.cloakdrop.com läuft und misst seit zwei Tagen.** Vier Personen haben die Fußzeile „Status page — coming soon" bemängelt; drei davon lagen daneben, weil status.html sich selbst als noch nicht fertig bezeichnet. Nur Wiedmann hat den echten Widerspruch belegt, indem er die laufende Subdomain abgerufen hat („All systems reachable — Last checked 2026-07-31 18:10 UTC — 38 ms", „Website: Operational, 100 % uptime — 2 days measured").

> *„Wenn ich das bei einem Anbieter finde, frage ich mich sofort, was die Statusseite mir sonst noch nicht erzählt."* (Wiedmann, 5,8)

7. **„Email — Delivering — 100 % uptime" im Block MEASURED** ist ein DNS-Lookup. Siehe §3.

8. **Die Cache-Regel für HTML-Seiten aus `_headers` greift auf keiner ausgelieferten Adresse.** Der Kommentar darüber lautet „Seiten nie aus dem Cache beantworten: ein Sicherheitsupdate des Clients muss sofort greifen". Ausgeliefert wird durchgehend die Cloudflare-Pages-Vorgabe. *Gegenprobe-Einschränkung: praktisch ist der Unterschied klein, weil `public, max-age=0, must-revalidate` ebenfalls vor jeder Verwendung zur Rückfrage zwingt.*

9. **Der Kommentar zu den 310.000 PBKDF2-Runden nennt sie die aktuelle OWASP-Zahl.** Ist sie nicht mehr.

10. **Der Bidi-Filter `sicherName()` existiert und wird an der einzigen Stelle nicht angewandt, an der er etwas verhindern würde.** Siehe §6, Fund D.

---

## 6. Neue Fehler, die mehrere unabhängig gefunden haben

Hier steht nur, was die Gegenprobe mit **BESTÄTIGT** oder **TEILWEISE** bewertet hat. Bei TEILWEISE sage ich dazu, was an der ursprünglichen Beschreibung ungenau war. Nennungen sind Personen.

### A. Jeder Eingabefehler beim Senden wirft in die Empfängeransicht und löscht die Dateiauswahl — 6 Nennungen (4× BESTÄTIGT, 2× TEILWEISE)

**Der meistgemeldete Defekt dieser Runde.** Gefunden von Bergmann, Reineke, Bruhns, J. Reinhardt, Kern und M. Reinhardt.

**Ursache, zeilengenau bestätigt:** `showError()` in index.html:3385 ruft `setMode('receive')` in 3386 und setzt damit `#app-view` auf `hidden`. Ausgelöst wird das unter anderem vom neuen Mindestlängen-Check des Passworts (2928-2934) und von der 500-MB-Prüfung (2937-2941). Der einzige Rückweg heißt „Cloak something instead" und führt auf die Marketingseite; `enterAppMode()` in 3428 setzt dabei `pending = []` — die Dateiauswahl ist weg.

**Gemessen in der Gegenprobe:** nach zwei Dateien, Fehler und vollem Rückweg ergab das Hinzufügen einer weiteren Datei „1 file · 11.1 KB". Sichtbar bleibt nur der veraltete DOM-Text der versteckten Liste.

> *„Ein Eingabefehler beim Absenden darf mich nicht auf die Empfängerseite werfen. Das ist kein Geschmacksurteil, das ist ein Bedienfehler."* (Bruhns, 3,3)

> *„Statt einer Feldmeldung schaltet die App den kompletten Modus um ... und ich stehe in der Empfänger-Fehleransicht unter der Überschrift ,Cloaked files, for your eyes.' ... Ich habe damals 40 Sekunden gebraucht, um überhaupt zu begreifen, dass ich auf einer anderen Seite bin."* (J. Reinhardt, 3,4)

> *„Validierungsfehler gehören unter das jeweilige Feld, nicht auf eine Fehlerseite in einer anderen Ansicht mit drei Klicks Rückweg."* (Bergmann, 4,4)

**Was an zwei Beschreibungen ungenau war — und zwar zu euren Ungunsten:** Bergmann und M. Reinhardt schreiben beide, die Dateiauswahl bleibe erhalten. Sie bleibt nicht erhalten. Beide haben den in der Oberfläche stehengebliebenen Zähler für die Auswahl gehalten. **Der Defekt ist schwerer als von zweien gemeldet**, und Reineke, Bruhns und J. Reinhardt beschreiben ihn korrekt.

Ein Nachbarfund gehört dazu: **das Passwortfeld wird im Fehlerfall nicht geleert.** Kern hat gemessen, dass ein Passwort aus einem gescheiterten Versuch stillschweigend auf dem nächsten Drop landet — man bekommt einen Link mit `&s=` und der Empfänger wird nach einem Passwort gefragt, das man nie vergeben hat. Reproduziert.

> *„Bei Kinderfotos ist das ärgerlich, bei einem Vertrag wäre es ein Desaster."* (Kern, 3,1)

### B. Die Speicher-Sackgasse: „Delete an older drop under Manage" führt nicht heraus — 2 Nennungen, BESTÄTIGT

**Der schärfste Fund der Runde.** Gefunden von Serwe und Bruhns, unabhängig und über zwei verschiedene Wege.

**Ursache:** `navigator.storage.estimate().usage` fällt nach dem Löschen nicht zurück — das ist die träge Buchführung des Browsers und nicht die Schuld der App. Die neue Vorabprüfung in index.html:2949-2960 rechnet aber genau mit diesem Wert und bricht ab, **bevor** etwas geschrieben wird. Damit ist der sauber gebaute `QuotaExceededError`-Zweig in 3032-3040, der tatsächlich aufräumen und ehrlich melden würde, nicht mehr erreichbar.

**Gemessen in der Gegenprobe:** nach dem Löschen aller Drops IndexedDB `{transfers: 0, chunks: 0}`, `usage` unverändert 30.006.887 Byte — unmittelbar danach, nach sechs Sekunden und über ein Neuladen hinweg.

> *„Die App hat mir gesagt, was ich tun soll, ich habe es getan, und sie sagt es mir weiter. Aus der App heraus komme ich da nicht mehr raus."* (Serwe, 4,3 — gemessen über 244 Sekunden, mit Neuladen zwischendurch, keine Erholung)

> *„Ich gehe auf Manage — da ist nichts. Die Datenbank war zu diesem Zeitpunkt komplett leer ... Die App rechnet mit einer Zahl, die der Browser meldet und die nach einem Abbruch nicht zurückgeht, und schickt mich zum Aufräumen an einen leeren Ort. Da kommt man nur mit ,Browserdaten löschen' raus, und das weiß eine Deutschlehrerin nicht."* (Bruhns, 3,3)

Ein dritter Fund gehört als Ursache dazu: **der gelöschte Drop gibt den belegten Platz nicht frei** (Reiter, BESTÄTIGT, gemessen über ein Neuladen hinweg unverändert). In Runde 3 war das ein kosmetisches Ärgernis mit zwei Nennungen. Durch die neue Vorabprüfung ist daraus eine Sperre geworden. **Das ist die wichtigste Lehre dieser Runde: eine Reparatur hat einen bekannten Schönheitsfehler in einen Blocker verwandelt.**

### C. Zweiter Tab löscht den Drop, den der erste gerade schreibt — der Sender meldet trotzdem Erfolg — 2 Nennungen, BESTÄTIGT

Gefunden von Reineke und Serwe. Beide haben denselben Ablauf gemessen: Tab 2 zeigt den laufenden Drop als „Unfinished" mit Löschknopf an, löscht ihn, meldet „nothing stored" — und Tab 1 läuft weiter bis zum Fertig-Schirm und gibt einen Link aus.

**Ursache, bestätigt:** `cloakAndStore` (2916-3080) prüft nie, ob sein eigener Datensatz noch existiert. Im gesamten Skript gibt es weder einen `BroadcastChannel` noch einen `storage`-Listener (je 0 Treffer). Das Feld „lebt", das die Aufräumroutine kennt, wird beim Löschen nicht ausgewertet.

> *„Der Link sieht perfekt aus: ,1 cloaked file, 314.6 MB total, opens for 24 more hours'. In der Datenbank lagen 69 Bruchstücke, gebraucht werden 79. ... Ein System, das mir Erfolg meldet, wenn es keinen gab, ist für meinen Beruf nicht diskutabel."* (Reineke, 3,4)

> *„Ich hätte diesen Link verschickt und wäre schlafen gegangen."* (Serwe, 4,3)

Serwes Diagnose ist die präzisere: das Lebenszeichen-Feld ist vorhanden, es wird an dieser Stelle nur nicht gelesen.

Verwandt und ebenfalls bestätigt, 1 Finder: **nach dem Löschen aus der Empfangsansicht zeigt der Sender-Tab den Link weiter als gültig** (Reineke). Dieselbe fehlende Verständigung zwischen Tabs.

### D. Der Bidi-Filter fehlt genau dort, wo er etwas verhindern würde — 4 Nennungen, BESTÄTIGT

Gefunden von M. Reinhardt, Reiter, Wiedmann und Nadia K.

Die Funktion `sicherName()` (index.html:2783) entfernt Schreibrichtungs-Steuerzeichen aus Dateinamen. Angewandt wird sie in 2831 und 3651 — also auf die Anzeige. Nicht angewandt wird sie in 3676, 3754 und 3857 — also auf den ZIP-Eintrag und den Einzeldownload.

**Gemessen:** eine Datei namens `rechnung‮gpj.exe` erscheint in Sende- und Empfangsliste als „rechnunggpj.exe". Das heruntergeladene Archiv enthält den Eintrag mit dem Steuerzeichen unverändert. Der Einzeldownload sieht nur deshalb harmlos aus, weil Chrome den Namen selbst entschärft — nicht die App.

> *„Der Filter existiert und fehlt an der einzigen Stelle, an der er etwas verhindern würde. Heute folgenlos, weil Drops nur dort aufgehen, wo sie entstanden sind — mit Relay ist es ein Übergabeweg."* (Wiedmann, 5,8)

Bemerkenswert: zwei andere Tester haben denselben Filter als vorbildlich gelobt, weil sie nur die Anzeige geprüft haben (Bergmann, J. Reinhardt). Beide haben recht — sie haben nur die andere Hälfte gesehen.

> *„Jemand hat an einen Angriff gedacht, den ich selbst nie auf dem Zettel gehabt hätte."* (Bergmann, 4,4)

### E. Unterbrochene Drops werden erst nach zwei Minuten geräumt, nicht „beim nächsten Öffnen" — 4 Nennungen, BESTÄTIGT

Bergmann, Reineke, Nadia K. und Kern. `UNFERTIG_FRIST = 120000` (index.html:2708), Aufräumen läuft nur beim Seitenstart (Aufruf 4162). limits.html:1915 und der Warntext in 3208-3211 versprechen beide etwas anderes.

**Gemessen in der Gegenprobe:** Neuladen bei 40 % eines 100-MB-Drops hinterlässt 11 Bruchstücke und 44,0 MB Verbrauch. Neuladen nach 15 s, 45 s und 85 s ändert nichts; erst der Durchgang nach rund 135 s räumt auf.

> *„Wenn ich nach dem Abbruch den Browser schließe und nicht zurückkomme, bleibt eine Datei von 412 MB im Profil, mit Zeitstempel und Klartext-Größe daneben."* (Nadia K., 4,2)

Dazu ein eigener bestätigter Fund von zwei Personen (Bruhns, Serwe): **der abgebrochene Drop wird mit seiner geplanten statt seiner tatsächlichen Größe gezählt.** Die Übersicht meldet „1 drop · 100.0 MB", während 44,0 MB auf der Platte liegen. Ausgerechnet die Zahl, nach der der Nutzer aufräumen soll, ist die falsche — und sie speist Fund B.

### F. Zwei gleichnamige Dateien werden im ZIP stillschweigend zu einer — 1 Nennung, BESTÄTIGT

Nur Serwe. Ich ziehe den Fund trotzdem hoch, weil er der einzige echte Datenverlust dieser Runde ist und weil er im Kern der neuen ZIP-Funktion sitzt.

`zipBauen` (index.html:3754) schreibt `e.name` ohne Eindeutigkeitsprüfung. Die Doppelerkennung beim Hinzufügen (2795-2799) greift nur bei gleichem Name **und** Größe **und** Änderungsdatum — zwei `Anlage_1.pdf` aus verschiedenen Ordnern gelten also zu Recht als zwei Dateien.

**Gemessen in der Gegenprobe:** zwei Dateien `Anlage_1.pdf` mit 120.000 und 130.000 Byte. Anzeige „2 files · 250.0 KB", kein Hinweis. Das Archiv enthält beide Einträge. Nach dem Auspacken liegt **eine** Datei mit 130.000 Byte da. Die andere ist ohne ein Wort weg.

> *„Ich bekomme ständig `Anlage_1.pdf` aus zwei Mandatsordnern. ... Wenn mir das mit einem unterschriebenen Vertragsanhang passiert, ist das ein Haftungsfall."* (Serwe, 4,3)

### G. Die Speicher-Fehlermeldung widerlegt sich mit ihren eigenen Zahlen — 2 Nennungen, BESTÄTIGT

Reineke und Wiedmann. Die Bedingung lautet `frei < gesamt * 1.05 + 4 * CHUNK_SIZE` (2954), der Meldungstext (2955-2958) nennt nur die beiden nackten Zahlen.

**Gemessen:** *„This drop needs about 30.0 MB, and this browser still allows 41.9 MB. Nothing was written."* 30,0 ist kleiner als 41,9. Der Nutzer liest zwei Zahlen, die seinen Fehler widerlegen.

### H. Die Übersicht kann Drops nicht auseinanderhalten — 3 Nennungen, BESTÄTIGT

M. Reinhardt, Bergmann und Kern. Der Zeitstempel geht nur bis zur Minute (3231-3234), pro Zeile gibt es genau einen Knopf: „Delete".

Alle drei räumen ausdrücklich ein, dass Dateinamen dort nicht stehen **können**, weil das Verzeichnis mitverschlüsselt ist. Alle drei sagen, das reiche als Antwort nicht.

> *„Ich habe um 19:31 zwei Drops kurz hintereinander angelegt, und die Übersicht zeigte danach zwei Zeilen mit exakt demselben Text, unterscheidbar nur an 4,5 MB gegen 3,2 MB. Die einzige Aktion pro Zeile ist ,Delete', und die ist endgültig."* (M. Reinhardt, 4,2)

> *„Die Übersicht braucht ein Merkmal, an dem ich einen Drop wiedererkenne — und sei es nur ein selbstvergebener Kurzname, der außerhalb des Manifests liegt und nichts über den Inhalt verrät."* (Bergmann, 4,4)

Kern hat zusätzlich bestätigt, dass die Zeile über der Ablage weder Anzahl noch Größe nennt — die Zahlen erscheinen erst nach einem Klick auf „Manage".

### I. Der Verlauf verliert den Drop — 3 Nennungen, BESTÄTIGT

Reiter, Serwe und Kern, an drei verschiedenen Stellen desselben Mechanismus. `history.replaceState` (3537) ersetzt den Verlaufseintrag mit dem Fragment durch den nackten Pfad.

- **Neuladen in der Empfangsansicht** wirft kommentarlos auf die Marketingseite (Reiter, Serwe).
- **Vorwärts nach Zurück** führt auf `https://cloakdrop.com/` ohne Fragment, der Drop ist nicht mehr erreichbar (Kern).
- Der Rettungsweg „Copy link again" existiert nur, solange die Ansicht steht (Serwe).

> *„Auf einem iPhone, das Tabs im Hintergrund verwirft, passiert das von allein."* (Serwe, 4,3)

### J. Der abgeschnittene Passwort-Link meldet ein falsches Passwort — 3 Nennungen, BESTÄTIGT

Reineke, Bruhns und Wiedmann. `passwortAbfragen` (3572) läuft vor der Längenprüfung (3589). Die Länge des Salzes wird an keiner Stelle geprüft.

**Gemessen in der Gegenprobe:** bei 1, 5, 10 und 15 fehlenden Zeichen erscheint die Passwortmaske, und das **richtige** Passwort ergibt „That password does not open this drop." Erst ab 25 fehlenden Zeichen — wenn `&s=` ganz wegfällt — kommt korrekt „That is not a key". Derselbe Schaden ohne Passwort wird sofort richtig gemeldet.

Bruhns' Beschreibung ist die genaueste der drei:

> *„Wenn das Frau Wendler passiert, ruft sie mich an und sagt, mein Passwort stimme nicht, und ich schwöre ihr, dass es stimmt, und wir beide werden nie darauf kommen. ... Ausgerechnet die Nutzer, die sich Mühe geben, laufen in die falsche Meldung."* (Bruhns, 3,3)

> *„Das erzeugt Telefonate mit Mandanten über ein Passwort, das stimmt."* (Reineke, 3,4)

### K. verify.html nennt einen Fehlertext, den die App nicht mehr ausgibt — 5 Nennungen, BESTÄTIGT

M. Reinhardt, Reiter, Reineke, Bruhns und Serwe. Siehe §5, Punkt 1. Alle fünf haben es nachgestellt, alle fünf haben dieselbe Abweichung gemessen. Die alte Zeichenkette steht in index.html nur noch in drei Kommentaren.

### L. Der Einfügekasten wirft Links mit Satzzeichen weg und gibt dem Nutzer die Schuld — 1 Nennung, BESTÄTIGT

Nur Bergmann, aber sauber gemessen und mit der besten Begründung. `frag.replace(/\s+/g, '')` (3981) entfernt nur Whitespace.

**Gemessen:** Link + `.`, Link + `, viele Grüße`, `<Link>`, `"Link"` und Link + `)` führen alle fünf zur Meldung „That is not a key … copy it again, from the first character to the last".

> *„Ein Link am Satzende ist in Outlook der Normalfall, nicht die Ausnahme, und die Meldung ,That is not a key' schiebt mir die Schuld zu."* (Bergmann, 4,4)

Von derselben Person und ebenfalls bestätigt: **die eigene www-Subdomain wird als fremde Seite abgewiesen.** Die Herkunftsprüfung (3964-3966) normalisiert `www.` nicht — obwohl `functions/_middleware.js` und `_redirects` www dauerhaft auf den Apex umleiten, www-Links also erwünscht und in der Adresszeile funktionsfähig sind.

> *„Das ist die eigene Seite."* (Bergmann, 4,4)

### M. Die Startseite bewirbt oberhalb der Falz den Versand, den es nicht gibt — 6 Nennungen (1× BESTÄTIGT, 2× TEILWEISE, 3× ohne eigene Messung)

Reiter (BESTÄTIGT), Bergmann und Bruhns (beide TEILWEISE), dazu M. Reinhardt, Reineke und Kern. Die gemessenen Positionen sind in §4 aufgeführt und wurden von der Gegenprobe auf das Zeichen genau reproduziert.

**Was ungenau war:** Bergmann verortet den Gegenhinweis „Preview: a link opens only on the device that made it" auf der Startseite bei y=564. Dieser Satz liegt in `#app-view`, das im Landing-Modus versteckt ist — auf der Startseite steht er gar nicht. Ihre Kritik wird dadurch **schärfer**, nicht milder. Und Bruhns nennt 837 Wörter Startseitentext; gezählt sind 597 Wörter bei 3.630 Zeichen. Ihre inhaltliche Aussage bleibt richtig.

### N. Ein fehlendes Bruchstück macht auch die heilen Dateien unerreichbar — 1 Nennung, BESTÄTIGT

Bergmann. Der Fehlerzweig von „Download all" (3684-3689) ruft `showError`, und `showError` versteckt `#receive-list` — also genau die Liste, in der die Einzeldownload-Knöpfe der unbeschädigten Dateien stehen. Zurück kommt man nur über ein erneutes Öffnen des Links.

### O. Herkunftsprüfung greift nur bei Schemata mit „://" — 2 Nennungen, BESTÄTIGT

J. Reinhardt und Nadia K. Das Muster in 3964 verlangt `://`, weshalb `javascript:alert(1)#t=a&k=b` und `data:text/html,…#t=a&k=b` durchrutschen und als Drop-Link behandelt werden. **Ausgeführt wird nichts, heute ist es folgenlos** — aber die Prüfung wurde laut Kommentar ausdrücklich für das Relay gebaut, und dann sollte sie dicht sein. Beide Finder ordnen das selbst genau so ein.

### P. Eine 0-Byte-Datei läuft ohne jeden Hinweis bis ins Archiv — 2 Nennungen, BESTÄTIGT

M. Reinhardt und Serwe. Weder `addFiles` noch `renderList` prüfen auf `size === 0`; der ZIP-Eintrag hat 0 Byte und CRC 0x0. Kein Wort an keiner Stelle. Beide räumen ein, dass die Ursache in ihrem eigenen Testaufbau lag — die fehlende Ansage bleibt.

### Q. Betriebsfunde: offline unlesbar, CSP-Hash tötet lautlos, kein noscript — 2 Nennungen, BESTÄTIGT

Wiedmann (offline, CSP-Hash) und Nadia K. (kein noscript, dieselbe tote Seite). Siehe §3. Beide Wege enden in derselben perfekt gerenderten Seite, die nichts kann.

> *„Für ein Produkt, dessen einziger Auslieferungspfad diese eine Datei ist, ist das der Fehler, der mich um drei Uhr morgens weckt."* (Wiedmann, 5,8)

> *„Im Tor Browser auf ,Safest' lädt die komplette Werbeseite mit 3.301 Zeichen Versprechen, der Knopf ,Cloak a file' tut nichts, und es gibt keinen einzigen noscript-Hinweis. Genau meine Zielgruppe läuft in eine tote Seite."* (Nadia K., 4,2)

### R. Die Fußzeile sagt „coming soon" über eine Seite, die es gibt — 4 Nennungen (1× BESTÄTIGT, 3× TEILWEISE)

M. Reinhardt, Bergmann, J. Reinhardt (alle TEILWEISE) und Wiedmann (BESTÄTIGT).

**Was an dreien ungenau war:** status.html bezeichnet sich selbst als noch nicht fertig („A status page is coming … It is being set up and is not ready yet"). Die Beschriftung sagt also nicht das Gegenteil der Seite, sondern dasselbe. Der Widerspruch, den die drei beschreiben, existiert in dieser Form nicht. Wiedmann hat den echten belegt: die Subdomain status.cloakdrop.com läuft und misst bereits. *Einschränkung der Gegenprobe: die Subdomain steht selbst hinter der PIN-Wand und ist damit noch nicht öffentlich.*

### Weitere bestätigte Einzelfunde, kurz

Alle mit sauberem Beweis, je 1 Finder:

- **Der Fertig-Schirm zeigt einen unbeschrifteten Link, der aus einer früheren Aktion stammen kann** (Bergmann). Gemessen: Drop A erzeugt, anderen Drop angesteuert, zurück auf `#app` — im Feld steht exakt Link A. Kein Dateiname, keine Uhrzeit, keine Anzahl daneben. *„Wer da auf ,Copy' drückt und in eine Mail klebt, schickt den falschen Schlüssel an den falschen Menschen."*
- **„Start a new drop" vernichtet den Link ohne Rückfrage** (M. Reinhardt). Zwei Zentimeter neben „Copy". Danach existiert der Schlüssel nirgends mehr, der Drop ist nur noch löschbar. *„Das Löschen hat eine zweistufige Bestätigung bekommen — die Aktion, die tatsächlich unwiderruflich Daten verliert, hat keine."*
- **Leeres Passwort plus „Unlock" löst gar nichts aus** (Kern). Zustand unverändert, Fehlerzeile bleibt versteckt. *„Meine Mutter drückt dreimal und ruft dann an."*
- **Auf WebKit fällt die Platzvorprüfung ersatzlos aus** (M. Reinhardt). `navigator.storage` ist dort `undefined`. Übrig bleibt der 30-Sekunden-Notausstieg.
- **Der gesamte Klartext einer großen Datei liegt beim Entschlüsseln im JS-Speicher** (M. Reinhardt). Gemessen mit 250 MB: Heap von 26,9 MB auf 269,1 MB.
- **Ein Fragment mit leerem `t` fällt kommentarlos auf die Startseite** (Wiedmann), während `#t=abc&k=` korrekt „This link is incomplete" meldet.
- **„Manage" ist aus der Fertig-Ansicht nicht erreichbar** (Nadia K.).
- **Das Sammelarchiv heißt nach der Drop-Kennung**, nicht nach dem Inhalt (Bruhns) — die Dateinamen liegen an dieser Stelle bereits entschlüsselt vor.
- **Die Beschriftung der Umschaltpille wird doppelt gezeichnet**, 3,5 px versetzt (M. Reinhardt). Bei 1440 und bei 390 Pixel Breite identisch. *„Sieht aus wie ein Druckfehler auf einem Plankopf, und bei einem Produkt, das mir Präzision verkauft, fällt mir so etwas sofort auf."*
- **Die Bremse gegen Passwortraten überlebt kein Neuladen** (Bruhns). Sechs Fehlversuche in einem Tab: 16,53 s. Ein Fehlversuch in einem frischen Tab: 0,13 s. Der Quelltextkommentar räumt das ausdrücklich ein, die Passwortmaske sagt dem Nutzer nichts davon.
- **Keine Passwortqualitätsprüfung** (Nadia K.): „12345678" und „password" werden angenommen.
- **Die App bittet ungefragt um dauerhaften Speicher** (Nadia K.) — `navigator.storage.persist()`, auf keiner Produktseite erwähnt.
- **Nach dem Löschen bleiben die Drop-Kennungen in der LevelDB-Datei** (Nadia K.); es gibt keine Funktion, die die Datenbank selbst entfernt.
- **Zwei verschiedene HSTS-Werte vom selben Host in einem Seitenaufruf** (Wiedmann, TEILWEISE). Die Messung stimmt, die Ursachenzuweisung nicht: `_headers` setzt für `/assets/*` keinen HSTS-Header, der kurze Wert kommt aus der Edge-Schicht bei zwischengespeicherten Antworten.
- **Die Cache-Regel für HTML greift auf keiner ausgelieferten Adresse** (Wiedmann, TEILWEISE). Der Kern stimmt und ist gemessen; „genau das Gegenteil der Absicht" ist übertrieben, weil `public, max-age=0, must-revalidate` ebenfalls jede Verwendung revalidieren lässt.

### Barrierefreiheit — zum ersten Mal geprüft, und das Ergebnis ist eindeutig

Jonas Reinhardt, 29, blind seit Geburt, NVDA-Nutzer. Er hat neun eigenständige Funde gemeldet. **Die Gegenprobe hat alle neun bestätigt**, in mehreren Fällen mit auf die Zeile und auf die zweite Nachkommastelle identischen Werten. Ich gebe dem einen eigenen Platz, weil es der erste Test dieser Art in vier Runden ist und weil zwei der Funde für sich allein Ausschlusskriterien sind.

**1. Null Live-Bereiche in der gesamten App.** Gemessen auf der Live-Seite: `[aria-live]` = 0, `[role=status]` = 0, `[role=progressbar]` = 0, `[aria-atomic]` = 0, `[aria-busy]` = 0. Der Fortschrittsbalken ist ein nacktes DIV, das per `transform:scaleX` skaliert wird.

> *„Ich hänge acht Dateien an, und es passiert — für mich — nichts. Ich drücke Enter auf ,Cloak & create link', und es passiert nichts. Der Balken läuft, der Text unter ihm zählt hoch, und ich höre kein einziges Wort davon. Ich weiß nicht, ob die App arbeitet, hängt oder abgestürzt ist."*

**2. Der Fokus fällt nach jedem Zustandswechsel auf BODY.** `showState` (2756-2768) setzt ausschließlich `hidden`. Wird das fokussierte Element versteckt, hat der Browser keine Wahl. An sechs Übergängen gemessen, drei davon von der Gegenprobe nachgemessen — jedes Mal dasselbe.

> *„Als Screenreader-Nutzer bediene ich diese App nicht, ich rate."*

**3. Ein falsches Passwort erzeugt keine wahrnehmbare Fehlermeldung.** `#pw-err` ist ein `<p hidden>` ohne `role` und ohne `aria-live`. Das Feld wird geleert, der Text erscheint sichtbar und wird nie angesagt. Das ist ein Verstoß gegen WCAG 3.3.1 auf Stufe A — der niedrigsten, die es gibt.

**4. Über der 500-MB-Grenze verschwindet der Absendeknopf aus der Tabreihenfolge.** `disabled` statt `aria-disabled`, die Begründung steht in einem Element ohne Live-Bereich und ohne `aria-describedby`. Ein deaktivierter Knopf ist nicht fokussierbar — die Begründung erreicht die Tastaturnutzung nie.

**5. Mehrfach identische Bedienknöpfe ohne Bezug zur Datei.** Acht Dateien ergeben acht Knöpfe mit dem Namen „Remove", in der Empfangsansicht drei mit dem Namen „Download". Keine Listensemantik, keine Positionsangabe.

**6. Der zweistufige Löschknopf gibt keinerlei zugängliche Rückmeldung.** Kein `aria-live`, kein `aria-pressed`. Der Textwechsel auf „Press again to delete", die Selbstentschärfung nach vier Sekunden und das Löschen selbst laufen lautlos.

**7. Sieben unsichtbare Tabstopps in geschlossenen Menüs.** `opacity: 0` und `pointer-events: none` ohne `visibility`, ohne `inert`, ohne `aria-hidden`. Die Gegenprobe ist die Tabreihenfolge mit echten Tastenanschlägen abgelaufen und hat die Stopps 3–7 und 9–10 bestätigt. *Einzige Korrektur: das ist eher WCAG 2.4.3/4.1.2 als 2.4.7.*

**8. Vier Textstile reißen den geforderten Kontrast.** `.pw-hint` 3,14:1, `.drops-note` 3,14:1, `.dz-bind` 3,30:1, `.progress-note` 3,30:1 — gefordert sind 4,5:1. Alle vier Werte auf die zweite Nachkommastelle reproduziert.

> *„Dass ausgerechnet der Fortschrittstext der kontrastschwächste der Seite ist, hat schon Humor."*

**9. Der Schieberegler auf limits.html liest sich als nackte Zahl.** `aria-label` „Largest single drop", kein `aria-valuetext`. NVDA liest „69". 69 was?

Und jetzt der Teil, der wehtut. Derselbe Tester hat sechs Dinge gefunden, die **richtig** gemacht sind — und zwar so richtig, dass die Lücke keine Frage des Könnens sein kann:

- Die Ablauffrist ist eine lehrbuchmäßige Radiogruppe mit `role=radiogroup`, wanderndem `aria-checked` und funktionierenden Pfeiltasten.
- Das Themenmenü setzt `aria-expanded`, bewegt den Fokus hinein und gibt ihn bei Escape korrekt zurück.
- Das Einfügefeld für Links setzt `aria-invalid`, holt den Fokus und hängt die Meldung per `aria-describedby` an das Feld.
- Nirgends ein `outline: none` — der Fokusring wird an keiner Stelle unterdrückt.
- Die Überschriftenhierarchie stimmt, es gibt `main`, `nav` und `footer` als Landmarken.
- **contact.html und die Glossarsuche haben korrekte Live-Bereiche** — `aria-live=polite`, `role=alert`, `role=status` — und bewegen bei Fehlern den Fokus auf das betroffene Feld.

> *„Das heißt: Der Entwickler kann Live-Bereiche. Er hat sie in ein Kontaktformular und in eine Suchfilterung eingebaut — und in die Verschlüsselung von 500 MB nicht. Das ist keine Unfähigkeit, das ist eine Prioritätenentscheidung, und die ärgert mich mehr als Unwissen."* (J. Reinhardt, 3,4)

Er beziffert den Aufwand selbst und ich halte die Schätzung für realistisch:

> *„Ich komme wieder, wenn zwei Dinge stimmen: ein Relay, das den Link zu meinem Kollegen trägt, und ein role=status neben dem Fortschrittsbalken. Das zweite ist ein Nachmittag Arbeit. Es wäre gut angelegt."*

### Was sich in der Gegenprobe nicht halten ließ

**Von 97 geprüften Funden wurde kein einziger vollständig widerlegt.** Das ist jetzt die vierte Runde in Folge ohne einen einzigen widerlegten Fund, und es ist bemerkenswert: die Melder haben Zeilenangaben und Messwerte in der großen Mehrheit auf die Zeile beziehungsweise auf die Nachkommastelle genau geliefert.

Neun Funde wurden mit TEILWEISE bewertet. Zwei davon sind für die Priorisierung wichtig und stehen oben bei den jeweiligen Funden (A und M) — in beiden Fällen war der gemeldete Defekt **schwerer** als beschrieben, nicht milder. Die übrigen sieben betreffen Beschreibungsfehler am Rand: eine falsche Ursachenzuweisung beim HSTS-Wert, eine übertriebene Folgerung bei der Cache-Regel, eine falsche Wortzahl der Startseite, und die vier Meldungen zur Fußzeile „coming soon", von denen drei am eigentlichen Widerspruch vorbeigreifen.

**Elf Funde waren keine Defekte, sondern Bewertungen dokumentierter Entscheidungen.** Ich nenne sie, weil sie in der Wahrnehmung schwer wiegen und im Bericht trotzdem nicht als Fehler zählen dürfen: das fehlende Relay (sechs Melder — an mindestens sechs Stellen der eigenen Seiten offen angesagt, unter anderem in der Fehlermeldung selbst), der 500-MB-Deckel (im Code durchgesetzt, auf limits.html genannt), die fehlende Bildvorschau in der Empfangsansicht, die fehlende Hilfe beim Aufteilen über der Grenze und das fehlende Alles-Löschen. Die Fakten stimmen in allen elf Fällen. Es sind Urteile über den Zuschnitt, keine Fehlfunktionen.

Eine Ausnahme davon mache ich, und die Gegenprobe macht sie mit: **die berechtigte Hälfte der Relay-Kritik — dass die Startseite oberhalb der Falz Messenger-Versand bewirbt und die Einschränkung erst bei 90 % des Seitentexts nennt — ist ein eigener, bestätigter Fund** und steht als M in der Liste.

---

## 7. Was die Note am stärksten heben würde

Sortiert nach Wirkung. „Nennungen" sind Personen von zehn.

| # | Maßnahme | Nennungen | Ohne Relay machbar? | Aufwand |
|---|---|---|---|---|
| 1 | **Relay bauen** | 10/10 als Blocker, 9× auf Platz 1 | nein, per Definition | groß |
| 2 | **Eingabefehler am Feld melden statt in die Empfängeransicht zu springen** — und die Dateiauswahl behalten | **6** | **ja** | klein bis mittel |
| 3 | **Die Startseite über der Falz die Wahrheit sagen lassen** (Kanalband weg oder umbenennen, bis das Relay steht) | **6** | **ja** | klein |
| 4 | **Speicher-Sackgasse auflösen**: Vorabprüfung entschärfen, den vorhandenen QuotaExceeded-Zweig wieder erreichbar machen | **2** (+1 als Ursache) | **ja** | klein bis mittel |
| 5 | **verify.html auf den Stand der App bringen** | **5** | **ja** | 1 Zeile |
| 6 | **Übergabenachweis / lokales Sendeprotokoll mit Dateinamen** | **5** | **ja**, rein lokal | mittel |
| 7 | **Barrierefreiheit: `role=status` am Fortschritt, Fokus nach jedem Zustandswechsel setzen, `#pw-err` als Live-Bereich** | **1** (aber 9 bestätigte Einzelfunde, 2 davon Ausschlusskriterien) | **ja** | ein Nachmittag für die drei wichtigsten |
| 8 | **BIDI-Filter auch im ZIP-Bauer anwenden** | **4** | **ja** | 1 Zeile |
| 9 | **Unfertige Drops sofort beim Start räumen** oder limits.html korrigieren | **4** | **ja** | klein |
| 10 | **Gleichnamige Dateien im ZIP eindeutig machen** | 1 | **ja** | klein |
| 11 | **Passwort-Link: Längenprüfung vor die Passwortabfrage** | **3** | **ja** | Reihenfolge zweier Blöcke |
| 12 | **Zweiten Tab absichern** (BroadcastChannel oder das vorhandene Lebenszeichen-Feld auswerten) | **2** | **ja** | klein bis mittel |
| 13 | **Übersicht: ein selbstvergebener Kurzname je Drop** | **3** | **ja** | klein |
| 14 | **Handy: Linkfeld nach dem Verschlüsseln ins Bild holen** (scrollIntoView nach showState) | **2** | **ja** | 2 Zeilen |
| 15 | **Satzzeichen und die eigene www-Subdomain im Einfügefeld verzeihen** | **1** | **ja** | klein |
| 16 | **Service Worker für den Offline-Fall** — dafür muss `worker-src` fallen | **1** | **ja** | mittel |
| 17 | **Startprüfung + noscript**, damit ein toter Client sich meldet | **2** | **ja** | klein |
| 18 | **Statusseite und /status in Übereinstimmung bringen**, „Delivering" aus MEASURED nehmen | **1** | **ja** | klein |
| 19 | **Öffentliches Repository + reproduzierbare Builds** | **4 als Blocker** | **ja** | groß |
| 20 | **Deckel über 500 MB** | 3 | teilweise — der Browserspeicher begrenzt mit | mittel |
| 21 | **PBKDF2 auf 600.000, Kommentar korrigieren** | 1 | **ja** | 1 Zeile |
| 22 | **Missbrauchskonzept vor dem Relay** | 2 nennen Firefox Send namentlich | nein, aber jetzt zu entscheiden | Konzept |
| 23 | **Kleinkram:** Umschaltpille doppelt gezeichnet, „Start a new drop" ohne Rückfrage, leeres Passwort ohne Reaktion, leeres `t` im Fragment, ZIP-Name, 0-Byte-Datei, Manage aus der Fertig-Ansicht, `persist()` dokumentieren | je 1 | **ja** | ein Nachmittag |

**Die Zeilen 2 bis 5 sind die Nachricht dieser Runde.** Sie haben zusammen **19 Nennungen**, sie sind alle ohne Relay behebbar, und drei von vieren sind entweder ganz neu (Sackgasse) oder durch eine Reparatur der letzten Runde entstanden (Eingabefehler). Zum Vergleich: in Runde 3 hatten die vier meistgenannten behebbaren Punkte zusammen 27 Nennungen. Der Berg schrumpft, aber er baut sich an neuer Stelle wieder auf.

**Punkt 5 ist eine Zeile Code mit fünf Nennungen** — das beste Aufwand-Wirkung-Verhältnis dieser Runde, so wie es „Copy link again" in Runde 3 und HSTS in Runde 2 war.

**Punkt 6 ist der wichtigste neue Wunsch.** Fünf Personen aus fünf verschiedenen Berufen nennen unabhängig voneinander, dass sie belegen können müssen, was wann an wen ging. Zwei setzen es gleichrangig neben das Relay. Und M. Reinhardt hat den entscheidenden Hinweis mitgeliefert: **das ist kein Widerspruch zu Zero Knowledge.** Ein rein lokales Protokoll kann die Dateinamen aus dem Manifest lesen, solange der Nutzer den Link noch hat. Es gibt keinen kryptografischen Grund, warum die Übersicht dem Absender verschweigen muss, was er selbst gerade verpackt hat.

**Punkt 7 gehört nach oben, nicht nach unten.** Er hat nur eine Nennung, weil nur eine Person mit einem Screenreader getestet hat. Das ist keine Aussage über die Zahl der Betroffenen, sondern über die Zusammensetzung des Testfelds. Zwei der neun Funde sind für sich allein Ausschlusskriterien, und die App beweist an drei Stellen, dass das Wissen dafür im Haus ist.

**Ehrliche Einschätzung zur erreichbaren Note.** Wenn ihr die Punkte 2 bis 15 vollständig abarbeitet und kein Relay baut, erwarte ich **4,4 bis 4,9** und weiterhin kein „ja". Das ist etwas höher als die Runde-3-Prognose (4,3–4,8), und der Grund ist, dass die Reparaturen dieser Runde tatsächlich gehalten haben: kein einziger der vier behobenen Defekte ist zurückgekommen. Die Prognose gilt wie immer nur, wenn beim Abarbeiten nichts Neues eingeschleppt wird — und die Speicher-Sackgasse zeigt, dass genau das zum dritten Mal in Folge passiert ist.

---

## 8. Die härteste Wahrheit

Dreizehn Reparaturen. Alle wichtigen davon haben gehalten. Die vier Defekte, die Runde 3 nach unten gezogen haben — 27 Nennungen zusammen —, haben in Runde 4 **null**. Die Note ist um 0,23 gestiegen und liegt immer noch unter Runde 2.

Das ist die eigentliche Nachricht: **ihr habt vier Runden lang die Fehlerliste abgearbeitet, und die Note bewegt sich in einem Band von vier Zehntelpunkten.** Nicht, weil die Arbeit schlecht wäre. Sondern weil die Note nicht an der Fehlerliste hängt.

Zehn Leute, zehnmal „nein". Und wenn man liest, **womit** sie ihr Nein begründen, steht viermal in Folge derselbe Satz da:

> *„Ich bewerte kein Kryptomodul, ich bewerte ein Werkzeug, mit dem ich Planstände verschicke."* (M. Reinhardt, 4,2)
> *„Ich kaufe kein Verschlüsselungsverfahren, ich kaufe die Übergabe einer Bewerbungsmappe an einen Fachbereich."* (Bergmann, 4,4)
> *„Es ist kein Transferdienst. Es ist eine Verschlüsselungsdemo mit einer Adressleiste dran."* (Reiter, 4,3)
> *„Der Link ist ein Lesezeichen auf meinen eigenen Rechner."* (Reineke, 3,4)
> *„Für mich ist das kein Mangel, das ist die Abwesenheit des Produkts."* (Kern, 3,1)
> *„Das ist kein Transportweg, das ist eine Verschlüsselung mit Extraschritten."* (Nadia K., 4,2)
> *„Ein sehr gut gebauter Motor ohne Räder."* (Reiter, 4,3)

Sieben verschiedene Menschen, sieben verschiedene Formulierungen für dieselbe Sache. Keiner von ihnen ist wütend. Sechs von ihnen loben das Handwerk in denselben Absätzen ausdrücklich und ausführlich. Zwei schreiben, sie hätten es gern.

Und jetzt die zweite Hälfte, die unangenehmer ist als die erste. In Runde 3 lautete der Vorwurf: *„Es verschickt nichts — und der fertige Teil verliert mir stillschweigend Dateien."* Die vier Defekte, die das getragen haben, sind weg. **An ihre Stelle sind vier neue getreten, und sie haben exakt dieselbe Signatur:**

- Der zweite Tab löscht den laufenden Drop, der Sender bekommt einen Erfolgs-Link. **2 von 10.**
- Zwei gleichnamige Dateien werden im ZIP zu einer, ohne ein Wort. **1 von 10, gemessener Datenverlust.**
- Der verstümmelte Passwort-Link wird dem Empfänger dauerhaft als falsches Passwort verkauft. **3 von 10.**
- Der Speicher sperrt und die App schickt einen zum Aufräumen an einen leeren Ort. **2 von 10.**

Zwei davon sitzen in Funktionen, die es in Runde 3 noch gar nicht gab. **Die dritte Runde in Folge, in der eine Reparatur einen neuen Defekt eingeschleppt hat** — Runde 2 das Passwort, Runde 3 „Copy link again", Runde 4 die Speicher-Vorabprüfung und der Mindestlängen-Check. Das Muster ist kein Zufall mehr und es hat einen benennbaren Grund: es gibt keine Regressionstests. Jede Reparatur wird beim nächsten Kundentest zum ersten Mal von jemand anderem angefasst. Zehn Personas finden zuverlässig, was ein einziger automatisierter Durchlauf vorher gefunden hätte.

Und dann ist da der Fund, der nichts mit alldem zu tun hat und trotzdem der wichtigste dieser Runde sein könnte. Zum ersten Mal in vier Runden hat jemand mit einem Screenreader getestet. Er hat neun Funde gemeldet, alle neun sind bestätigt, zwei davon sind Ausschlusskriterien. Er hat die App nicht bedient, er hat geraten. Und im selben Protokoll steht, dass das Kontaktformular und die Glossarsuche alles richtig machen: `aria-live`, `role=alert`, `role=status`, Fokus auf das fehlerhafte Feld.

**Das Wissen ist im Haus. Es steckt im Kontaktformular und nicht in der Verschlüsselung von 500 Megabyte.** Das ist derselbe Befund wie beim Bidi-Filter, der die Anzeige bereinigt und das Archiv nicht, und derselbe wie bei der Speichermeldung, die einen fertigen, richtigen Fehlerzweig hat, den die neue Vorabprüfung unerreichbar macht. Dreimal dasselbe Bild: die richtige Lösung ist schon da und wird an der Stelle nicht angewandt, an der sie zählt.

Die gute Nachricht steht wie in jeder Runde in derselben Zahl. **Vier Runden, 97 gegengeprüfte Funde allein in dieser, kein einziger Fund gegen die Kryptografie und kein einziger gegen den Anbieter.** Zehn Leute haben es diesmal ernsthaft versucht, sechs haben aktiv manipuliert, drei haben das Browserprofil auf der Platte durchsucht. Das Fundament trägt, es trägt nachweislich, und es ist inzwischen härter geprüft als das der meisten Bezahlprodukte am Markt.

Und deshalb steht am Ende dieselbe Frage wie in Runde 1, nur teurer geworden: Ihr habt vier Runden lang das gebaut, was schon funktioniert hat, immer besser gemacht. Jede dieser Runden hat euch Fehler eingebracht, die ihr ohne die Runde nicht gefunden hättet, und jede hat euch ungefähr zwei Zehntel Note gekostet oder gebracht. Der Unterschied zwischen 4,04 und einer 7 liegt nicht in dieser Fehlerliste. Er liegt in einem Satz, den Katrin Bergmann so aufgeschrieben hat:

> *„Ich kann nicht wechseln: es gibt hier nichts zu wechseln, weil nichts ankommt."*
