# Der Relay — was gebaut werden muss, damit CloakDrop wirklich überträgt

Stand: 31. Juli 2026. Grundlage: `tasks/launch.md`, Punkte 2.6 bis 2.13, 2.24, 5.1 bis 5.3.

Heute verschlüsselt CloakDrop echt, aber **im Browser und nur dort**. Ein Link
öffnet nur in dem Browser, der ihn erzeugt hat. Dieser Text beschreibt den Teil,
der daraus einen Dienst macht — und zwar so, dass er dich nicht ruinieren kann.

---

## Vorab: heute kann dir niemand Kosten machen

Solange nur die statische Seite online steht, gibt es **nichts, das pro Anfrage
abrechnet**: kein Worker, kein Speicher, kein Egress. Cloudflare Pages liefert
Dateien aus, mehr passiert nicht. Wer die Seite hunderttausendmal lädt, erzeugt
Traffic — und Traffic kostet auf dem Free-Plan nichts.

**Das ändert sich in der Sekunde, in der der Relay live geht.** Ab dann kostet
jeder Upload Speicher und Schreiboperationen, und beides läuft auf die
Kreditkarte deines Vaters. Deshalb gehören die Schutzmechanismen unten **in den
ersten Wurf des Relays**, nicht in einen späteren.

---

## Die harte Wahrheit über Ausgabendeckel

**Weder R2 noch Workers lassen sich auf einen Maximalbetrag begrenzen.** Es gibt
keinen Schalter „stoppe bei 20 €". Was es gibt, sind Alarme — und die kommen,
nachdem das Geld ausgegeben wurde.

Der einzige echte Schutz ist deshalb ein **Not-Aus, den du selbst baust**:

1. Ein Schlüssel in KV, z. B. `relay:enabled`.
2. Der Worker liest ihn bei **jedem** Upload-Start. Steht er auf `0`, wird
   abgelehnt — mit einer ehrlichen Meldung, nicht mit einem Fehler.
3. Ein Cron-Worker prüft stündlich die Nutzung über die Cloudflare-API
   (GraphQL Analytics) gegen eine Obergrenze, die du festlegst.
4. Reißt sie, setzt er `relay:enabled = 0` und schickt dir eine Push-Nachricht.
5. Downloads laufen weiter — nur neue Uploads stoppen. Wer einen Drop bekommen
   hat, verliert ihn nicht, weil jemand anders die Grenze gerissen hat.

Dazu Cloudflare-Notifications auf Billing- und R2-Schwellen. **Aber verlass dich
nicht darauf**: Benachrichtigungen kommen verzögert, der Cron-Job ist der Zaun.

---

## Missbrauchsschutz, gestaffelt

Kein einzelner Mechanismus reicht. Fünf Schichten, von außen nach innen:

### 1 · Turnstile vor dem ersten Byte
Bevor der Browser einen Upload beginnen darf, holt er sich beim Worker eine
Erlaubnis — und dafür muss er ein gelöstes Turnstile-Token vorlegen. Das kostet
nichts, ist unsichtbar für echte Menschen und stoppt jedes Skript, das nicht
gezielt gegen dich geschrieben wurde.

### 2 · Rate Limiting Rules am Edge
In der Cloudflare-Oberfläche, bevor eine Anfrage überhaupt einen Worker kostet:

| Pfad | Grenze (Vorschlag) | Zähler |
|---|---|---|
| `POST /api/drop` (Drop anlegen) | 5 pro Stunde | IP |
| `PUT /api/chunk/*` | 240 pro Minute | IP |
| `GET /api/drop/*` | 60 pro Minute | IP |
| alles andere | 600 pro Minute | IP |

Die Zahlen sind Startwerte, keine Wahrheit — nach zwei Wochen echter Nutzung
nachrechnen. Wichtig ist die Reihenfolge: **erst Edge-Limit, dann Worker.** Was
am Edge abprallt, kostet dich nichts.

### 3 · Kontingente im Worker
Rate-Limits bremsen Geschwindigkeit, nicht Menge. Deshalb zusätzlich Zähler in
KV oder einem Durable Object:

- **pro Drop**: höchstens die Größe, die du versprichst (heute 500 MB), und
  höchstens so viele Chunks, wie diese Größe zulässt
- **pro IP und Tag**: z. B. 2 GB gesamt und 10 Drops
- **global pro Tag**: eine Obergrenze für den ganzen Dienst, die deutlich unter
  deinem Kostendeckel liegt

Beim Überschreiten: ehrliche Meldung („Für heute erreicht"), kein stiller Fehler.

### 4 · Upload-Token — der wichtigste Punkt
Ohne ihn ist der Relay ein offener Blob-Store. Ablauf:

1. Client fragt: „Ich möchte einen Drop mit N Chunks à höchstens 4 MiB."
2. Worker prüft Turnstile, Limits und Kontingente, legt den Datensatz an und
   gibt ein **signiertes, kurzlebiges Token** zurück (HMAC, ~30 Minuten), das
   genau diese Drop-Id und genau N Chunks erlaubt.
3. Jeder `PUT` muss das Token tragen. Der Worker prüft Signatur, Ablauf,
   Chunk-Nummer und Größe, bevor er nach R2 schreibt.
4. Ohne gültiges Token wird **nichts** geschrieben.

Damit kann niemand fremde Drops überschreiben, beliebig viele Chunks
nachschieben oder R2 als Speicher zweckentfremden.

### 5 · WAF und Bot-Schutz
Bot Fight Mode an, dazu WAF-Regeln gegen offensichtliches Scannen. Kostet
nichts, filtert die Grundlast.

---

## Was der Relay technisch braucht

**Cloudflare-Bausteine**
- **Worker** für die API. Nicht Pages Functions: die Routen brauchen eigene
  Limits, eigenes Deployment und einen Cron-Trigger.
- **R2** für die verschlüsselten Chunks. Bucket in EU-Jurisdiction.
  Achtung: 4 MiB liegt unter der Multipart-Mindestgröße — jeder Chunk wird ein
  eigenes Objekt. Ein 500-MB-Drop sind ~125 Schreiboperationen. Das ist der
  wichtigste Kostentreiber, **vor** dem Bau durchrechnen.
- **KV** für Kontingente, Not-Aus und Sperrlisten.
- **Durable Object** für alles, was atomar sein muss — vor allem
  „Delete after first download": zwei gleichzeitige Downloads dürfen nicht
  beide gewinnen. Mit KV allein ist das nicht sicher lösbar.

**Datenmodell** (der Server sieht nur Chiffrat)
```
drop:<id>  ->  { chunks, bytes, created, expires, burn,
                 ownerToken, state }
r2:  drop/<id>/<n>       ein Objekt je Chunk
```
Kein Dateiname, keine Größe im Klartext, kein Empfänger — der Server weiß
nichts über den Inhalt. Das ist keine Bequemlichkeit, das ist das Produkt.

**Ablauf und Löschung**
- R2-Lifecycle allein reicht nicht: Tagesgranularität, asynchron.
- Ein Cron-Worker läuft stündlich, löscht abgelaufene Drops und schreibt einen
  Löschnachweis (Anzahl, keine Ids).
- Ein **Totmannschalter**: bleibt der Job zweimal aus, Alarm. Ein stiller
  Ausfall bricht genau die Zusage, die auf jeder Seite steht.

**Meldeweg**
Ein Formular und eine Adresse, über die jemand einen Drop melden kann, plus die
Möglichkeit, ihn per Id sofort zu sperren. Bei einem anonymen Dateidienst ist
das keine Kür — der erste Missbrauchsfall kommt vor dem ersten echten Nutzer.

---

## Reihenfolge

1. **Kryptoformat einfrieren** (launch.md 2.6). Nach dem ersten echten Link ist
   ein Formatbruch unmöglich, weil Links unveränderlich in Chats leben.
2. **Host-Trennung** (2.5): Nutzdaten auf eine eigene Domain, nicht auf
   `cloakdrop.com`. Ein einziger Missbrauchsfall kann eine Domain auf
   Sperrlisten bringen — dann sind Website, Mail und alle Links gleichzeitig weg.
3. Worker-Grundgerüst, R2-Bucket, Datenmodell, Upload-Token
4. Upload mit Wiederaufnahme, Download als Stream
5. **Not-Aus, Kontingente, Rate-Limits, Turnstile — bevor irgendjemand davon
   erfährt**
6. Löschjob mit Totmannschalter
7. Monitoring, Alarme, Meldeweg
8. Erst dann: öffentlich sagen, dass es geht

Aufwand laut Audit: rund 70 bis 95 Personentage für Stufe 2 insgesamt, davon
etwa 20 allein für den Relay-Kern.

---

## Was du dabei nicht vergessen darfst

Sobald der Relay Daten von anderen Menschen annimmt, wird dein Vater
**Verantwortlicher im Sinne der DSGVO** und Hoster im Sinne des DSA. Dann
gelten Meldeverfahren, Auskunfts- und Löschpflichten, 72-Stunden-Frist bei
Datenpannen. Das steht ausführlich in `tasks/launch.md`, Stufe 1.

Die statische Vorschau von heute löst nichts davon aus. Der erste hochgeladene
Fremd-Chunk schon.
