# Ablauf bis zum Livegang

Stand: 30. Juli 2026, Abend. Ziel: Freitag 16 Uhr fertig, danach online.
Umfang: **öffentliche Preview** — Verschlüsselung läuft im Browser und ist
ausprobierbar, das Relay wird gebaut. Die Seiten sagen das selbst.

Wer macht was: **[D]** = du, **[C]** = ich. Reihenfolge ist bindend, wo eine
Zeile eine andere blockiert.

---

## Vor dem Deploy

### 0 · Entscheidungen (blockiert fast alles)

- [ ] **[D] Domainname festlegen.** 70 Stellen im Code zeigen auf
      `cloakdrop.com`. `_headers`, `sitemap.xml`, `security.txt`, die
      OG-Karten und das Impressum brauchen ihn.
- [ ] **[D] Gespräch mit deinem Vater.** Er wird Betreiber, mit Namen im
      Impressum. Vorlage für das Gespräch: `tasks/launch.md` — dort steht,
      was existiert und was nicht. Was er wissen muss:
      er haftet für Inhalte und Missbrauch, er ist DSGVO-Verantwortlicher,
      Cloudflare läuft auf seine Rechnung.
- [ ] **[D] Impressumsdaten**: Name, ladungsfähige Anschrift, Telefonnummer,
      E-Mail. Ohne diese vier Angaben geht die Seite nicht öffentlich.

### 1 · Cloudflare (dein Vater als Kontoinhaber)

- [ ] **[D] Konto anlegen** auf dash.cloudflare.com. Danach sofort
      My Profile → Authentication → **Two-Factor an**, Recovery-Codes
      ausdrucken und wegschließen.
- [ ] **[D] Domain registrieren** (Domain Registration → Register Domain).
      Falls das TLD dort fehlt: woanders registrieren, dann **Add a Site** und
      die zwei Cloudflare-Nameserver beim Registrar eintragen. **Zuerst
      machen** — die Übernahme dauert Minuten bis Stunden.
- [ ] **[D] DNSSEC** aktivieren (DNS → Settings).
- [ ] **[D] SSL/TLS → Overview → Full (strict)**.
      Edge Certificates: *Always Use HTTPS* an, *Minimum TLS Version* 1.2,
      *Automatic HTTPS Rewrites* an.
- [ ] **[D] HSTS**: max-age **24 Stunden**, „Include subdomains" AUS,
      **Preload AUS**. Preload ist praktisch unumkehrbar — frühestens nach
      zwei stabilen Wochen.
- [ ] **[D] Nicht anfassen**: WAF-Regeln, Rate Limiting, Turnstile, R2,
      Workers-Routen, Web Analytics. Ohne Relay alles gegenstandslos.

### 2 · Inhalt (läuft parallel, blockiert den Deploy)

- [x] **[C] Versionskontrolle** — Git steht, jeder Schritt ist umkehrbar.
- [x] **[C] Cookie-Dialog** aus den App-Seiten (Einwilligung für Analytics,
      die es nicht gibt).
- [x] **[C] Icon-Satz, Web-Manifest, robots.txt**.
- [x] **[C] CSP** — Skripte nur per sha256, `default-src 'none'`,
      `connect-src 'none'`. Werkzeug: `tasks/build_headers.py`,
      Prüfung: `tasks/verify_csp.py` (mit Selbsttest).
- [x] **[C] Social-Karte** aus den echten Schriften der Seite.
- [x] **[C] Wahrheits-Pass** über alle Seiten — jede Aussage gegen das,
      was der Code wirklich tut. *(läuft)*
- [x] **[C] Anmelde-Attrappe raus** — speichert heute einen Passwortabdruck
      im Browser, obwohl es keine Konten gibt.
- [x] **[C] Newsletter-Formular raus** aus 16 Seiten — es spielt eine
      Erfolgsmeldung und verwirft die Adresse.
- [x] **[C] Cookie-Dialog raus** aus den 16 Marketing-Seiten.
- [ ] **[C] Icon- und OG-Verweise** in alle Seiten einsetzen.
- [ ] **[C] 404-Seite** im Zuschnitt der Website.
- [ ] **[C] Domainname** über alle 70 Fundstellen ziehen. *(braucht 0)*
- [ ] **[C] sitemap.xml, security.txt** *(braucht 0)*
- [ ] **[D+C] Impressum ausfüllen** *(braucht 0)*
- [ ] **[C] Datenschutzerklärung** auf das echte Setup bringen: kein Server,
      aber IndexedDB und localStorage im Browser des Besuchers.

### 3 · Letzter Prüflauf vor dem Deploy

```
python tasks/build_404.py        # Fehlerseite aus der Schale
python tasks/build_head.py       # canonical, Icons, Social-Karten
python tasks/build_footer.py     # Kontaktkarte (NACH build_404)
python tasks/build_site_files.py # sitemap, security.txt, robots
python tasks/build_headers.py    # CSP-Hashes neu rechnen  (NACH jeder Änderung!)
python tasks/build_ogimage.py    # Social-Karte neu rendern
python tasks/verify_csp.py       # alle Seiten unter echter CSP
```

Alle sieben müssen grün sein. `build_headers.py` **muss** nach der letzten
Inhaltsänderung laufen — ändert sich ein Zeichen in einem `<script>`, passt
sein Hash nicht mehr und die Seite bleibt stumm.

---

## Deploy

> **Nie `npx wrangler pages deploy .` ausführen.** Der Punkt steht für den
> Projektordner, und darin liegt `tasks/` — mit `_gate-credentials.txt`, dem
> Launch-Audit und allen Generatoren. Der Fehlgriff fällt **nicht auf**, weil er
> funktioniert: `_headers` und `functions/` liegen im Wurzelverzeichnis, die
> Seite sieht danach völlig normal aus. Nur hängt der ganze Innenraum daneben im
> Netz. Immer `dist`, nie `.`.

- [x] **[C] Ausliefern** — zwei Befehle, kein Hochladen von Hand:
      ```
      python tasks/build_dist.py
      npx wrangler pages deploy dist --project-name=cloakdrop
      ```
      `build_dist.py` stellt den Ordner aus einer festen Liste zusammen und
      bricht ab, wenn etwas Internes hineingeraten ist. Das ist die Absicherung
      gegen genau den Fehlgriff oben.
- [ ] **[D] Custom Domain** hinzufügen (Apex und `www`).
      Workers &amp; Pages → cloakdrop → Custom domains → Set up a domain.
      Muss über die Oberfläche laufen: der DNS-Eintrag gehört dazu, und dafür
      reicht das Wrangler-Token nicht (`dns_records` → 403, gemessen).
- [ ] **[D]** Prüfen, dass `_headers` wirkt: Seite öffnen, DevTools →
      Network → erste Antwort → Response Headers. Dort müssen
      `Content-Security-Policy` und `Strict-Transport-Security` stehen.
      Wenn nicht: `_headers` liegt nicht im Wurzelverzeichnis des Uploads.

## Nach dem Deploy, in dieser Reihenfolge

- [ ] **[D]** Jede der 20 Seiten einmal öffnen, Konsole leer?
- [ ] **[D]** Auf dem Handy öffnen. Datei verschlüsseln, Link erzeugen.
- [ ] **[D]** Link in einem anderen Browser öffnen — er darf **nichts**
      anzeigen. Genau das sagt die Seite, und genau das muss passieren.
- [ ] **[D]** Impressum und Datenschutz von jeder Seite aus erreichbar?
- [ ] **[D]** E-Mail an die Adresse im Impressum schicken und prüfen, dass
      sie ankommt. Ein Impressum mit totem Postfach ist schlechter als keines.

## Wenn etwas schiefgeht

- **Seite weiß, keine Funktion** → CSP blockiert. `_headers` nach der letzten
  Änderung nicht neu gebaut. `python tasks/build_headers.py`, neu deployen.
- **Alles kaputt nach einem Deploy** → Pages → Deployments → vorherigen
  Deployment → *Rollback*. Dauert Sekunden.
- **Lokal etwas zerschossen** → `git log --oneline`, dann
  `git checkout <commit> -- <datei>`. Nichts ist verloren.

---

## Was ausdrücklich NICHT zum Launch gehört

Relay, Upload, Download, echter Ablauf, Burn, Konten, API, Statuszahlen,
Bezahlung. Steht alles in `tasks/launch.md` mit Aufwand und Reihenfolge.
Der Weg von „Preview" zu „Dienst" ist beschrieben — er dauert nur länger
als bis morgen.

---

## Nachtrag 31. Juli: die vier App-Seiten sind raus

dashboard, received, expired und settings sind nicht mehr Teil der Website.
Sie zeigten Empfaenger, Download-Zeiten, "Send again" und "Never opened" —
einen Betrieb, den dieser Build nicht hat — und keine einzige Seite verlinkte
sie. Generator, app.css, app.js und die zugehoerige Pruefung bleiben liegen
und sind stillgelegt; die Seiten stehen vollstaendig in Git. Sobald das Relay
existiert, werden sie wahr und koennen daraus wieder entstehen.

---

## Zugangswand, bis das Impressum steht

Die Seite geht online, ist aber nicht oeffentlich: `functions/_middleware.js`
faengt **jede** Anfrage ab. Ohne gueltiges Cookie wird keine einzige Datei
ausgeliefert — egal welche Adresse jemand aufruft, es kommt die PIN-Seite.
Das ist eine echte Sperre am Server, keine Abdeckung im Browser.

Eine Ausnahme, mit Absicht: `/.well-known/` liegt immer frei. Dort laeuft die
Zertifikatspruefung einer neuen Domain, und security.txt darf keine PIN
brauchen. Geprueft in `tasks/verify_gate.mjs`, samt Gegenprobe, dass daneben
liegende Pfade (`/.well-knownx/…`) **nicht** durchrutschen.

### Einrichten

```
npx wrangler pages secret put GATE_PIN --project-name=cloakdrop
npx wrangler pages secret put GATE_SECRET --project-name=cloakdrop
python tasks/build_dist.py
npx wrangler pages deploy dist --project-name=cloakdrop
```

Beide Werte stehen in `tasks/_gate-credentials.txt` (nicht in Git). Der Deploy
danach ist **noetig**: gemessen am 30.07. blieb die Seite nach dem reinen Setzen
auf 200 und ging erst mit dem naechsten Deployment auf 401.

Kontrolle, nicht Vertrauen:
```
curl -s -o /dev/null -w "%{http_code}\n" https://cloakdrop-3oh.pages.dev/
```

Danach die **aelteren Deployment-Adressen loeschen**. Jedes fruehere Deployment
behaelt seine eigene `<hash>.cloakdrop-3oh.pages.dev` und laeuft ohne die
Secrets weiter — es umgeht die Wand also dauerhaft. Workers & Pages → cloakdrop
→ Deployments → Menue am Eintrag → Delete. Das laufende Production-Deployment
laesst sich nicht loeschen, deshalb: erst neu deployen, dann die dann alten weg.

### Oeffentlich schalten

Nicht ueber das Loeschen von `GATE_PIN`. Sauberer und beweisbar:

```
python tasks/build_dist.py --offen
npx wrangler pages deploy dist --project-name=cloakdrop
```

`--offen` laesst `functions/` weg. Dann ist die Wand nicht abgeschaltet, sondern
gar nicht da — unabhaengig davon, wie Cloudflare Variablen bindet. Nebeneffekt:
die Seite ist wieder zu 100 % statisch und faellt damit aus dem Tageslimit von
100.000 Worker-Aufrufen heraus, das bei stehender Wand fuer **jede** Datei gilt.

Zurueck geht es genauso: `build_dist.py` ohne `--offen`, neu deployen.

### Was die Wand leistet und was nicht

Sie haelt jeden fern, der die PIN nicht hat — geprueft mit
`node tasks/verify_gate.mjs`: kein Pfad liefert etwas ohne signiertes Cookie,
gefaelschte und abgelaufene Cookies fallen durch, das Cookie ist HttpOnly,
Secure und SameSite=Lax.

Sie ist **kein** Schutz gegen jemanden, der die PIN kennt und weitergibt, und
kein Ersatz fuer eine Rate-Limit-Regel: acht Ziffern sind bei 700 ms
Verzoegerung je Fehlversuch praktisch nicht zu raten, aber wer es industriell
versucht, kostet Worker-Anfragen. Wenn die Seite laenger als ein paar Tage
hinter der Wand steht, eine Rate-Limiting-Rule auf POST `/` legen.
