Workers P4: Betriebsanleitung nach der Endprüfung (Reihenfolge, Schema mit Setup-Schlüssel, Rückweg-Image, Live-Prüfungen, Pilot, Kauf-Link-Schalter)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8bebe86c62
commit
f388a37c46
1 file changed
+429
-19
@@ -981,23 +981,433 @@ Spec §5 (Freigabe-Pult): „Folge-Antworten von Plattformen kommen über die Be
|
||||
|
||||
## Betriebsanleitung (Kenso)
|
||||
|
||||
Voraussetzung: P1–P3 laufen (P3-Betriebsanleitung durchgeführt), die Absender-Domain samt Postfach (SMTP + IMAP) ist eingerichtet (SPF, DKIM, DMARC `p=none`, Aufwärmphase läuft). Alle Befehle auf dem Server, `cd /home/webklar/apps`. Agenten führen davon nichts aus. Nie ein nacktes `docker compose up -d`.
|
||||
Reihenfolge einhalten: Block A bis J. **[Claude]** macht Claude für dich, alles andere tippst du selbst auf dem Server. Zugangsdaten (Passwörter, Schlüssel) tippst du nur selbst ein (`read -rs` oder direkt in `.env`), nie in einen Chat und nie in einen Befehl, der sie ausgibt. Nach jeder Änderung an `.env` oder `docker-compose.yml` startest du mit `cd /home/webklar/apps && docker compose up -d --no-deps workers` neu (nie `docker restart`: das liest `.env` nicht neu ein; nie ein nacktes `docker compose up -d`). Wird ein `git push` abgelehnt: nie `--force`, nie `rebase`, Claude Bescheid. Agenten führen von diesen Befehlen nichts aus.
|
||||
|
||||
1. **Branch übernehmen.** `cd /home/webklar/apps/workers-dev && git log --oneline -3` zeigt den Commit `P4-T33`. Dann `git push origin p4-gespraeche:main` (P4 baut auf dem Stand von P3 auf, `main` rückt per Fast-Forward vor; wird der Push abgelehnt, zuerst `git pull --rebase origin main`) und `cd /home/webklar/apps/workers && git pull --ff-only`. Prüfung: `git -C /home/webklar/apps/workers log --oneline -1` und `git -C /home/webklar/apps/workers-dev log --oneline -1` zeigen denselben Commit. Mit dem Pull kommen auch die Persona-Dateien `prompts/{nora,max,theo,bob,bianca,ben,paul}.md` ins Produktions-Checkout; der Ordner `prompts/` ist schreibgeschützt in den Container eingehängt (P1), spätere Änderungen an einer Persona brauchen nur `git pull --ff-only` im Produktions-Checkout, keinen Neubau.
|
||||
2. **Backups.** `cd /home/webklar/apps && cp .env .env.bak-$(date +%F)-workers-p4 && cp docker-compose.yml docker-compose.yml.bak-$(date +%F)-workers-p4`. Prüfung: `ls -l .env.bak-*workers-p4 docker-compose.yml.bak-*workers-p4` zeigt beide Dateien von heute.
|
||||
3. **Absender-Postfach und Abmelde-Geheimnis in `.env`** (Werte nie anzeigen; P1s Compose-Block reicht diese Namen schon durch). In den spitzen Klammern die echten Werte eintragen:
|
||||
`cd /home/webklar/apps && read -rs -p 'Passwort des Absender-Postfachs: ' K; echo; printf 'WORKERS_SMTP_HOST=<smtp-host>\nWORKERS_SMTP_PORT=587\nWORKERS_SMTP_USER=<postfach>\nWORKERS_SMTP_FROM=<postfach>\nWORKERS_SMTP_PASS=%s\nWORKERS_IMAP_HOST=<imap-host>\nWORKERS_IMAP_PORT=993\nWORKERS_IMAP_USER=<postfach>\nWORKERS_IMAP_PASS=%s\nWORKERS_UNSUB_SECRET=%s\nWORKERS_AUTOMAIL=nein\n' "$K" "$K" "$(openssl rand -hex 32)" >> .env; unset K`
|
||||
Der Datenschutz-Schalter ist **kein** Env-Wert, sondern `settings.privacyInteressentenLive` (Schritt 10/11). Prüfung: `command grep -c '^WORKERS_\(SMTP\|IMAP\)_' .env` gibt `9`; `command grep -c '^WORKERS_UNSUB_SECRET=.' .env` gibt `1`; `command grep -c '^WORKERS_SMTP_HOST=<' .env` gibt `0` (keine Platzhalter übrig).
|
||||
4. **Compose-Zeilen** aus `/home/webklar/apps/workers/ops/compose-p4.md` im Dienst `workers` ergänzen (die vier neuen Umgebungszeilen) und den vorhandenen `tmpfs`-Eintrag `- /tmp` durch `- /tmp:size=256m` ersetzen. Prüfung: `docker compose config -q && echo KONFIG-OK`.
|
||||
5. **Bauen und starten.** `free -m | sed -n 2p` (mindestens 1,5 GB verfügbar), `docker compose build workers`, dann `docker compose up -d --no-deps workers`. Prüfung: `docker logs --tail 30 webklar-workers` zeigt `workers listening on 8092` und `vorschau listening on 8093` ohne Fehlerzeile; `docker exec webklar-workers chromium --version` zeigt eine Version; `docker exec webklar-workers sh -c 'mkdir -p /data/vorschau && id -un && ls -ld /data/vorschau'` zeigt `node` und `node` als Besitzer und `drwxr-xr-x` (0755; in einem schon vorhandenen Volume fehlt der Ordner bisher; scheitert `mkdir`, meldet Claude den Fehler und ändert nichts am Volume). Der Dienst legt Vorschau-Verzeichnisse selbst mit 0755 und Dateien mit 0644 an, damit der schreibgeschützt eingehängte Portal-Container (P5) sie lesen kann (A14).
|
||||
6. **Schema nachziehen** (jetzt, im laufenden Container): `docker exec webklar-workers node scripts/setup-collections.mjs --check; echo "Exit $?"` → erwartet `workersPreviews.idx_status FEHLT`, `workersSettings.sendingHalted FEHLT`, `workersSettings.sendingHaltedReason FEHLT` (Bounce-Notbremse, H4), `Exit 1`; dann derselbe Befehl ohne `--check` (Ende `Fertig.`), danach wieder mit `--check` → `Alles vorhanden.`, `Exit 0`.
|
||||
7. **Traefik-Route.** `cp /home/webklar/apps/workers/ops/traefik/workers-entwurf.yml /home/webklar/apps/traefik/dynamic/workers-entwurf.yml` (Hot-Reload, kein Neustart). Nach etwa 1 Minute: `curl -sI https://entwurf.project.webklar.com/abc` zeigt `404` und `x-robots-tag: noindex, nofollow`; `curl -sv https://entwurf.project.webklar.com/abc 2>&1 | rg -a -i 'issuer'` zeigt Let's Encrypt. Bei Zertifikatsfehler 5 Minuten warten und `docker logs --tail 50 webklar-traefik | rg -a entwurf` lesen.
|
||||
8. **WOMS ausliefern.** `git -C /home/webklar/apps/ticket.webklar.com/dev-workers push origin feature/workers:test`. Prüfung nach dem Deploy: `https://ticket.webklar.com/hustler` → Reiter „Freigabe“ lädt ohne Fehler.
|
||||
9. **Live-Prüfungen (je einzeln, Kosten nur bei `build`).**
|
||||
- `docker exec webklar-workers node scripts/p4-livecheck.mjs smtp --to kenso.gri@gmail.com --ja-echt` → Mail kommt an; in Gmail „Original anzeigen“: SPF, DKIM, DMARC `PASS`, `List-Unsubscribe` und `List-Unsubscribe-Post` vorhanden. Meldet das Skript einen Login-Fehler, **nicht** wiederholen: Passwort in `.env` prüfen, erst dann erneut.
|
||||
- `docker exec webklar-workers node scripts/p4-livecheck.mjs imap --ja-echt` → druckt `uidValidity`, `uidNext`, `exists`.
|
||||
- `docker exec webklar-workers node scripts/p4-livecheck.mjs screenshot --ja-echt` → druckt je Ansicht Bildgrößen (lange Kante ≤ 1456) und den Spitzen-Speicher; parallel `docker stats --no-stream webklar-workers` in einem zweiten Fenster. Liegt der Speicher nahe 768 MB oder der Container wird beendet: `mem_limit` und `memswap_limit` auf `1g` anheben (Kensos Entscheidung), `docker compose up -d --no-deps workers`.
|
||||
- `docker exec webklar-workers node scripts/p4-livecheck.mjs build --ja-echt` → ein echter Opus-Aufruf über Streaming (etwa 1–3 $, Dauer einige Minuten); Ausgabe nennt Tokens, Kosten und `validateBuildFiles: ok`. Bricht der Aufruf mit Zeitüberschreitung oder 400er-Fehler ab, **nicht** wiederholen, sondern die Meldung an Claude geben.
|
||||
10. **Pilot mit eigenem Postfach** (nur Mo–Fr 09–16 Uhr). Das Tor lässt die erste Nachricht in einem Faden nur zu, wenn der Datenschutz-Schalter an ist. Für den Test geht die Mail nur an die eigene Adresse; deshalb den Schalter kurz einlegen (P3-Skript): `docker exec webklar-workers node scripts/datenschutz-schalter.mjs --an` und **am Ende dieses Schritts** wieder `… --aus`, solange der Abschnitt „Interessenten“ nicht live ist (P6). Dann `docker exec webklar-workers node scripts/p4-livecheck.mjs pilot --to kenso.gri@gmail.com --name "Testbetrieb Muster" --ja-echt` → innerhalb von 5 Minuten kommt die Testmail. Antworte „ja, gern“. Erwartung in WOMS `/hustler`: Ereignis „Antwort eingegangen“ (Nora), Bau-Auftrag, nach etwa 5–15 Minuten im Reiter „Freigabe“ ein Eintrag „Vorschau für Testbetrieb Muster freigeben“ mit Link. Link öffnen; Rechte der Vorschau-Dateien prüfen: `docker exec webklar-workers sh -c 'ls -ld /data/vorschau/* | head -3; ls -l /data/vorschau/*/ | head -8'` zeigt `drwxr-xr-x` für die Verzeichnisse und `-rw-r--r--` für die Dateien (A14, sonst kann der Portal-Container sie nicht lesen). Dann „Freigeben & senden“ → Mail mit Vorschau-Link kommt an (innerhalb von 5 Minuten, im Sendefenster). Abmelde-Link der Mail im Browser öffnen: es erscheint nur die Seite mit Knopf; erst „Abmelden“ sperrt. Danach erneut `pilot` mit derselben Adresse: die Ereignisse zeigen keinen Versand (Kontakt gesperrt). **Aufräumen:** Der Abmelde-Test hat `kenso.gri@gmail.com` für immer auf die Sperrliste gesetzt; ohne Aufräumen kämen künftige Tests und Mails an diese Adresse nie an. Dokument-Id berechnen: `printf 'mail:kenso.gri@gmail.com' | sha256sum | cut -c1-32`, dann in der Appwrite-Konsole (Datenbank `woms-database`, Sammlung `workersSuppression`) das Dokument mit dieser Id löschen. Danach `docker exec webklar-workers node scripts/datenschutz-schalter.mjs --aus` (siehe oben). Der Pilot-Interessent bleibt als Testeintrag in `workersProspects` (Quelle `pilot`). **Plattform-Folge-Antwort (T34, A20):** Solange noch kein echter Plattform-Eintrag existiert (P3-Pilot), entfällt dieser Test. Sonst im Reiter „Freigabe“ (Filter „Erledigt“) bei einem von dir gesendeten Eintrag „Antwort auf …“ auf „Antwort des Kunden einfügen“ klicken, einen Beispieltext einfügen („Wie lange dauert das?“) und absenden: Meldung „Eingefügt. Nora sortiert die Antwort ein.“; innerhalb von 2 Minuten Ereignis „Antwort von der Plattform eingegangen“ (Nora), kurz danach ein neuer Eintrag „Folge-Antwort für …“ mit Claras Entwurf (Art `plattform_antwort`); der Text „Bitte abmelden“ sperrt den Interessenten sofort. Der Entwurf wird wie jeder Plattform-Entwurf von Hand kopiert und gesendet; Max sendet auf Plattformen nie. **Plattform-Benachrichtigungen aus dem Alarm-Postfach** werden erst ausgewertet, wenn der Betreff-Ausdruck der jeweiligen Plattform in `REPLY_SUBJECTS` (`src/gespraeche/plattformMail.js`) steht: Sobald du auf Kleinanzeigen, freelancermap oder freelance.de die erste echte Antwort auf eine von dir gesendete Nachricht bekommst, leite die Benachrichtigungs-Mail an Claude weiter (ohne persönliche Daten, nur Betreff und Aufbau), der den Ausdruck einträgt und testet. Bis dahin ist nur das Einfügen aktiv; Antwort-Mails im Alarm-Postfach behandelt P3 dann wie jede andere Nicht-Alarm-Mail.
|
||||
11. **Dauerbetrieb freigeben.** Erst nach Warm-up und live veröffentlichtem Datenschutz-Abschnitt „Interessenten“: Schalter mit P6s Skript bzw. `docker exec webklar-workers node scripts/datenschutz-schalter.mjs --an` setzen (Prüfung `… --status` → `an`); optional `WORKERS_AUTOMAIL=ja` in `.env` (Max sendet Claras Mail-Antworten selbst), dann `docker compose up -d --no-deps workers`. Prüfung: `docker exec webklar-workers printenv WORKERS_AUTOMAIL`. **Bounce-Notbremse (H4):** Stoppt der Dienst den Versand (Mail „[Hustler] Versand gestoppt (Bounces)“ an die Berichtsadresse, in WOMS die Warnzeile „Versand gestoppt: …“), zuerst die Ursache prüfen (Adressquellen, Postfach, DNS/DKIM); freigegeben wird ausschließlich im Einstellungs-Dialog („Versand wieder freigeben“, nur Admin) – bis dahin bleiben alle Mail-Aufträge offen und gehen nach der Freigabe raus.
|
||||
12. **Zurückrollen.** `mv /home/webklar/apps/traefik/dynamic/workers-entwurf.yml /home/webklar/apps/`; `cp .env.bak-<Datum>-workers-p4 .env`; `cp docker-compose.yml.bak-<Datum>-workers-p4 docker-compose.yml` (die Sicherungen aus Schritt 2); `docker compose up -d --no-deps workers`; in WOMS Pausenschalter setzen. Prüfung: `curl -sI https://entwurf.project.webklar.com/abc` liefert nicht mehr `x-robots-tag` vom Workers-Dienst.
|
||||
Was P4 tut: Der Dienst liest jetzt die Antworten im Absender-Postfach (Nora), baut nach einem „Ja“ eine kostenlose Vorschau-Website (Bob, Bianca, Ben), lässt Paul sie prüfen und zeigt sie unter `https://entwurf.project.webklar.com/<Token>/`; jede Mail an einen Interessenten geht durch das Sende-Tor von der Absender-Domain. Kalte Erstmails gibt es erst mit P6. **Achtung Kosten:** ein Bau mit Opus kostet je Runde meist 0,3 bis 0,7 $ (Details in I1). Im Standard gehen die ersten 10 Vorschauen nie ohne deine Freigabe hinaus.
|
||||
|
||||
### A. Voraussetzungen prüfen
|
||||
|
||||
**A1. P1 und P3 laufen.**
|
||||
```
|
||||
curl -s https://ticket.webklar.com/api/workers/health
|
||||
```
|
||||
*Erwartet:* `{"ok":true,"version":"0.1.0"}`. *Wenn nicht:* erst die Betriebsanleitungen von P1 (bis „Fertig, wenn“) und P3 (mindestens Block B) abarbeiten. Die WOMS-Auslieferung von P3 (Block E) darf noch offen sein, siehe E.
|
||||
|
||||
**A2. Stand des Dienstes, Stand des Pushs, altes Image.** Die erste Nummer ist **ALT-DIENST** (für den Rückweg in J), die Image-Kennung der Zeile `latest` ebenso.
|
||||
```
|
||||
git -C /home/webklar/apps/workers rev-parse --short HEAD && git -C /home/webklar/apps/workers-dev ls-remote origin main | cut -c1-7 && docker images webklar-workers --format '{{.Tag}} {{.ID}} {{.CreatedSince}}' && git -C /home/webklar/apps/workers-dev branch --show-current && git -C /home/webklar/apps/workers-dev log --oneline -1
|
||||
```
|
||||
*Erwartet:* `b742e79`, `b742e79`, eine Zeile `latest <Kennung> …`, `p4-gespraeche` und `b6234ea …` mit einem Titel (oder eine neuere Nummer; Claude nennt dir die endgültige). *Wenn nicht:* zweite Nummer `dda99db` = der Push von P3 (P3 B1) fehlt; erste Nummer anders oder `…/apps/workers` fehlt = P1 oder P3 sind nicht ausgeliefert: zuerst deren Anleitungen; ein anderer Zweig im Dev-Checkout = Claude Bescheid (das Schema in B6 kommt aus diesem Zweig).
|
||||
|
||||
Dazu der Zustand des Produktions-Checkouts (der `git pull --ff-only` in B7 braucht einen Zweig):
|
||||
```
|
||||
git -C /home/webklar/apps/workers status -sb | head -n1
|
||||
```
|
||||
*Erwartet:* `## main...origin/main`. *Wenn nicht* (zum Beispiel `## HEAD (no branch)` nach einem früheren Rückweg): `git -C /home/webklar/apps/workers checkout main` und diesen Befehl wiederholen; sonst scheitert der Pull in B7 mit „You are not currently on a branch“.
|
||||
|
||||
**A3. Platz und Speicher.**
|
||||
```
|
||||
df -h / | tail -1 && free -m | sed -n 2p
|
||||
```
|
||||
*Erwartet:* mindestens 3 GB frei (die Chromium-Schicht braucht rund 0,5 GB) und in der Spalte „available“ mindestens 1500 (MB). *Wenn nicht:* nicht bauen, erst Platz bzw. Speicher freimachen (frag Claude).
|
||||
|
||||
**A4. Absender-Domain und Postfach** (Anbieter-Oberfläche, `domain.tld` einsetzen). Anforderungen: eine eigene Domain nur für diese Mails (nie `webklar.com` oder eine Subdomain davon: das Sende-Tor verweigert sie), SMTP-Server nicht von Hetzner (`*.your-server.de`), Postfach mit SMTP (Port 587 mit STARTTLS oder 465) und IMAP (Port 993), SPF, DKIM und DMARC mit `p=none` stehen, die Aufwärmphase läuft, und keine DMARC-Berichtsadresse (`rua`/`ruf`) zeigt auf dieses Postfach (solche Berichte sind Mails ohne Faden und können die 10 Pult-Plätze je Tag füllen).
|
||||
```
|
||||
dig +short TXT domain.tld; dig +short TXT _dmarc.domain.tld
|
||||
```
|
||||
*Erwartet:* eine Zeile mit `v=spf1 …` und eine mit `v=DMARC1; p=none …`. DKIM prüfst du in D1. *Wenn nicht:* im DNS-Panel nachtragen, bevor du weitermachst.
|
||||
|
||||
**A5. DNS der Vorschau-Adresse.**
|
||||
```
|
||||
getent hosts entwurf.project.webklar.com ticket.webklar.com
|
||||
```
|
||||
*Erwartet:* zwei Zeilen mit derselben Server-Adresse. *Wenn nicht:* der Wildcard-Eintrag `*.project.webklar.com` fehlt; ohne ihn bekommt Traefik in C kein Zertifikat.
|
||||
|
||||
**A6. Kostengrenze steht** (wie P3 A5): Anthropic-Console → Workspace „Hustler“ → Ausgabenlimit **150 $ pro Monat**. *Erwartet:* 150 $ steht dort. *Wenn nicht:* jetzt setzen.
|
||||
|
||||
### B. Dienst: Sicherung, Konfiguration, Schema, Image, Neustart
|
||||
|
||||
**B1. Sicherungen und Rückfall-Image** (das Image **vor** dem Bauen sichern).
|
||||
```
|
||||
cd /home/webklar/apps && cp -p .env .env.bak-$(date +%F)-workers-p4 && cp -p docker-compose.yml docker-compose.yml.bak-$(date +%F)-workers-p4 && docker tag webklar-workers:latest webklar-workers:vor-p4
|
||||
```
|
||||
*Erwartet:* keine Ausgabe; `ls -l .env.bak-*-workers-p4 docker-compose.yml.bak-*-workers-p4` zeigt zwei Dateien von heute, `docker images webklar-workers` zeigt `latest` und `vor-p4` mit derselben Kennung. *Wenn nicht:* nichts ändern, bis alles da ist. Das Image `vor-p4` löschst du nicht, solange P4 nicht bewährt ist.
|
||||
|
||||
**B2. Absender-Postfach in `.env`, Teil 1** (kein Geheimnis; die Beispielwerte in den Anführungszeichen durch deine ersetzen; `WORKERS_UNSUB_BASE` steht fest im Compose-Block und gehört nicht in die `.env`).
|
||||
```
|
||||
printf 'WORKERS_SMTP_HOST=%s\nWORKERS_SMTP_PORT=%s\nWORKERS_SMTP_USER=%s\nWORKERS_SMTP_FROM=%s\nWORKERS_IMAP_HOST=%s\nWORKERS_IMAP_PORT=993\nWORKERS_IMAP_USER=%s\nWORKERS_AUTOMAIL=nein\nWORKERS_KAUFLINK=nein\n' 'smtp.beispiel.de' '587' 'max@beispiel.de' 'max@beispiel.de' 'imap.beispiel.de' 'max@beispiel.de' >> /home/webklar/apps/.env
|
||||
```
|
||||
*Erwartet:* keine Ausgabe. *Wenn nicht:* Tippfehler: die Zeilen im Editor korrigieren (Sicherung aus B1).
|
||||
|
||||
**B3. Passwort und Abmelde-Geheimnis in `.env`, Teil 2** (das Passwort tippst du verdeckt; SMTP und IMAP nutzen dasselbe Postfach, also dasselbe Passwort; das Geheimnis wird zufällig erzeugt).
|
||||
```
|
||||
read -rs -p 'Passwort des Absender-Postfachs: ' K; echo; printf 'WORKERS_SMTP_PASS=%s\nWORKERS_IMAP_PASS=%s\nWORKERS_UNSUB_SECRET=%s\n' "$K" "$K" "$(openssl rand -hex 32)" >> /home/webklar/apps/.env; unset K
|
||||
```
|
||||
*Erwartet:* keine Ausgabe. Enthält das Passwort `$`, `#` oder ein Leerzeichen, setzt du es in der `.env` von Hand in einfache Anführungszeichen (`WORKERS_SMTP_PASS='…'`, ebenso `WORKERS_IMAP_PASS`), sonst verstümmelt Compose es; ein `'` im Passwort geht nicht, setz dann im Postfach ein anderes. **Das Abmelde-Geheimnis änderst oder löschst du nie wieder**, sobald eine echte Mail hinausging: jeder schon versendete Abmelde-Link antwortet sonst mit „nicht gefunden“ und ein Widerspruch ginge verloren. Lösche deshalb nie alle `.env`-Sicherungen. *Wenn nicht:* B4 zeigt, ob etwas fehlt oder doppelt ist.
|
||||
|
||||
**B4. `.env` prüfen** (zeigt nur Zahlen).
|
||||
```
|
||||
cd /home/webklar/apps && command grep -c '^WORKERS_\(SMTP\|IMAP\)_' .env; command grep -c '^WORKERS_UNSUB_SECRET=.' .env; command grep -c '^WORKERS_\(AUTOMAIL\|KAUFLINK\)=nein$' .env; command grep -c '^WORKERS_\(SMTP\|IMAP\)_.*beispiel' .env
|
||||
```
|
||||
*Erwartet:* vier Zahlen: `9`, `1`, `2`, `0`. *Wenn nicht:* mehr als erwartet = doppelte Zeilen aus früheren Versuchen, nur die doppelten im Editor löschen; weniger = fehlende ergänzen (alle fünf SMTP- und alle vier IMAP-Werte gehören zusammen, sonst bricht der Dienst beim Start mit `Konfiguration unvollständig: <Namen>` ab); letzte Zahl über 0 = ein Beispielwert ist nicht ersetzt.
|
||||
|
||||
**B5. Compose-Zeilen** (einmal; ändert nur den Dienst `workers` im Block aus P1: Speicher 768m → 1g, `/tmp` auf 256m, fünf neue Umgebungszeilen laut `ops/compose-p4.md`; einen veröffentlichten Port oder einen Healthcheck gibt es nicht, Traefik und nginx erreichen den Dienst im Docker-Netz). Der Befehl tut nichts, wenn `WORKERS_KAUFLINK` schon in der Datei steht (kein doppeltes Einfügen).
|
||||
```
|
||||
cd /home/webklar/apps && [ "$(command grep -c WORKERS_KAUFLINK docker-compose.yml)" = 0 ] && sed -i '/^ workers:$/,/^ [a-z0-9_-]*:$/{
|
||||
s/^ mem_limit: 768m$/ mem_limit: 1g/
|
||||
s/^ memswap_limit: 768m$/ memswap_limit: 1g/
|
||||
s/^ - \/tmp$/ - \/tmp:size=256m/
|
||||
/^ - WORKERS_UNSUB_SECRET=/a\
|
||||
- WORKERS_CHROMIUM_PATH=/usr/bin/chromium\
|
||||
- WORKERS_AUTOMAIL=${WORKERS_AUTOMAIL:-nein}\
|
||||
- WORKERS_KAUFLINK=${WORKERS_KAUFLINK:-nein}\
|
||||
- HOME=/tmp\
|
||||
- XDG_CACHE_HOME=/tmp/.cache
|
||||
}' docker-compose.yml
|
||||
```
|
||||
Prüfen:
|
||||
```
|
||||
cd /home/webklar/apps && sed -n '/^ workers:$/,/^ [a-z0-9_-]*:$/p' docker-compose.yml | grep -E '^ (mem_limit|memswap_limit):|^ - (/tmp|WORKERS_CHROMIUM_PATH|WORKERS_AUTOMAIL|WORKERS_KAUFLINK|HOME|XDG_CACHE_HOME)' && docker compose config -q && echo KONFIG-OK
|
||||
```
|
||||
*Erwartet:* acht Zeilen (`mem_limit: 1g`, `memswap_limit: 1g`, `- /tmp:size=256m`, dann die fünf neuen Umgebungszeilen) und `KONFIG-OK`. *Wenn nicht:* eine Zeile fehlt oder ist doppelt = `cp -p docker-compose.yml.bak-<Datum>-workers-p4 docker-compose.yml` und Claude Bescheid; fehlen die Zeilen nach dem Einfügen (der Befehl ändert nichts, wenn der Block anders eingerückt oder benannt ist), setzt du die Werte von Hand nach `ops/compose-p4.md`.
|
||||
|
||||
**B6. Schema nachziehen** (auf dem Host, **vor** dem Bau und dem Neustart, sonst kann der Dienst die Notbremse nicht speichern und fragt Vorschauen ohne Index ab). Der Laufzeit-Schlüssel darf das nicht. Lege in der Appwrite-Konsole (Projekt `6a1058610003c5a13a05` → Integrationen → API-Schlüssel) einen Schlüssel `workers-setup` an: Ablauf 1 Tag, Bereiche `databases.read`, `collections.read/write`, `attributes.read/write`, `indexes.read/write`, **nie** `databases.write`, nicht in `.env`.
|
||||
```
|
||||
cd /home/webklar/apps/workers-dev && ( read -rs -p 'Appwrite-Key workers-setup: ' APPWRITE_API_KEY; echo; export APPWRITE_API_KEY; timeout 300 node --max-old-space-size=1024 scripts/setup-collections.mjs --check; echo "Exit $?" )
|
||||
```
|
||||
*Erwartet:* 13 Zeilen `= workers…: N Attribute, M Indizes vorhanden` (`workersSettings` mit 28 Attributen, `workersPreviews` mit 0 Indizes) und genau vier Zeilen `- workersSettings.sendingHalted FEHLT`, `- workersSettings.sendingHaltedReason FEHLT`, `- workersSettings.sendingHaltedClearedAt FEHLT`, `- Index workersPreviews.idx_status FEHLT`, dann `4 Eintrag/Einträge fehlen.` und `Exit 1`. Dann derselbe Befehl ohne `--check` (drei Zeilen `+ Attribut …`, `+ Index workersPreviews.idx_status`, am Ende `Fertig.`), danach wieder mit `--check`: `Alles vorhanden.`, `Exit 0`. **Danach den Schlüssel `workers-setup` in der Appwrite-Konsole löschen.** *Wenn nicht:* 401 oder „missing scope“ = falscher Schlüssel; mehr als vier `FEHLT`-Zeilen = ein früherer Schritt (P3 B4) fehlt, der Lauf ohne `--check` zieht alles nach (wiederholbar); `NICHT BEREIT` = ein paar Minuten warten und `--check` wiederholen.
|
||||
|
||||
**B7. Stand übernehmen** (erst jetzt, gleich vor dem Bau: der `pull` ändert auch `prompts/*.md`, die der laufende P3-Dienst sofort liest). P4 baut auf P3 auf, `main` rückt per Fast-Forward vor.
|
||||
```
|
||||
git -C /home/webklar/apps/workers-dev push origin p4-gespraeche:main && git -C /home/webklar/apps/workers pull --ff-only
|
||||
```
|
||||
*Erwartet:* kein Fehler; `git -C /home/webklar/apps/workers log --oneline -1` und `git -C /home/webklar/apps/workers-dev log --oneline -1` zeigen dieselbe Nummer (`b6234ea` oder neuer). [Claude] bestätigt danach, dass `grep -rn '\.sendMail(' /home/webklar/apps/workers/src` nur `src/mail/gate.js` und `src/notify.js` nennt (jede Mail an Interessenten geht durch das Sende-Tor). *Wenn nicht:* bei „non-fast-forward“ oder „Not possible to fast-forward“ nie `--force`, nie `rebase`, Claude Bescheid.
|
||||
|
||||
**B8. Image bauen und Dienst neu starten.**
|
||||
```
|
||||
cd /home/webklar/apps && free -m | sed -n 2p && docker compose build workers && docker compose up -d --no-deps workers
|
||||
```
|
||||
*Erwartet:* „available“ mindestens 1500; der Bau dauert länger als bei P3 (Chromium kommt als Paket ins Image), dann wird der Container neu erstellt. *Wenn nicht:* „Killed“ oder Speicherfehler siehe A3, nichts erzwingen; sonst die letzten Zeilen an Claude.
|
||||
|
||||
**B9. Läuft der neue Dienst?** Sechs Prüfungen, jede einzeln.
|
||||
```
|
||||
docker logs --tail 30 webklar-workers
|
||||
```
|
||||
*Erwartet:* Zeilen `workers listening on 8092` und `vorschau listening on 8093`, keine Zeile mit `Abbruch:` oder `Konfiguration`.
|
||||
```
|
||||
docker exec webklar-workers chromium --version
|
||||
```
|
||||
*Erwartet:* eine Zeile `Chromium <Version>`.
|
||||
```
|
||||
docker inspect -f '{{.HostConfig.Memory}} {{.HostConfig.MemorySwap}} {{.State.OOMKilled}} {{.RestartCount}}' webklar-workers
|
||||
```
|
||||
*Erwartet:* `1073741824 1073741824 false 0`.
|
||||
```
|
||||
docker exec webklar-workers sh -c 'df -h /tmp | tail -1; mkdir -p /data/vorschau; id -un; ls -ld /data/vorschau'
|
||||
```
|
||||
*Erwartet:* eine Zeile für `/tmp` mit Größe `256.0M`, dann `node`, dann `drwxr-xr-x … node node … /data/vorschau`.
|
||||
```
|
||||
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://ticket.webklar.com/api/workers/pult/abc/start-build
|
||||
```
|
||||
*Erwartet:* `401` (die neue Route gibt es, du bist nur nicht angemeldet). *Wenn nicht:* `404` = der alte Dienst läuft noch (B8 wiederholen, `docker ps`); `Abbruch:` oder `Konfiguration unvollständig`/`ungültig` im Log = ein Eintrag in `.env` fehlt oder ist kaputt (der Dienst startet dann in einer Schleife neu): Zeile an Claude, nichts raten; `Konfiguration: WORKERS_UNSUB_SECRET ist leer` = B3 fehlt; `OOMKilled true` oder Neustarts über 0 = Speicher, Claude. Das Rückfall-Image aus B1 liegt bereit (J3).
|
||||
```
|
||||
docker exec webklar-workers sh -c 'printenv WORKERS_AUTOMAIL WORKERS_KAUFLINK WORKERS_CHROMIUM_PATH; printenv WORKERS_UNSUB_BASE; printenv WORKERS_UNSUB_SECRET | wc -c'
|
||||
```
|
||||
*Erwartet:* fünf Zeilen: `nein`, `nein`, `/usr/bin/chromium`, `https://entwurf.project.webklar.com/abmelden` und `65` (64 Zeichen plus Zeilenende; das Geheimnis selbst wird nicht ausgegeben). Das ist der Stand im laufenden Container, nicht nur in den Dateien aus B4 und B5. *Wenn nicht:* eine andere Zahl oder ein fehlender Wert = die Compose-Zeile (B5) oder die `.env`-Zeile (B2, B3) fehlt: dort ergänzen und mit B8 neu starten.
|
||||
|
||||
**B10. Posteingang hat seinen Lesestand** (nach etwa 2 Minuten; der erste Lauf übernimmt nur den aktuellen Stand des Postfachs, Mails davor werden nie gelesen: **schick vorher keine Pilot-Mail**).
|
||||
```
|
||||
docker exec webklar-workers cat /data/imap-state.json
|
||||
```
|
||||
*Erwartet:* ein Eintrag `"antworten":{"uidValidity":…,"lastUid":…}` (und `"alarme"`, wenn das Alarm-Postfach aus P3 Block C eingerichtet ist). Zusätzlich muss dieser Befehl leer bleiben:
|
||||
```
|
||||
docker logs --since 10m webklar-workers 2>&1 | grep -iE 'invalid query|index not found|attribute not found|unknown attribute|Tick abgebrochen|Unbehandelte|Fehler bei|Anmeldung abgelehnt'
|
||||
```
|
||||
*Wenn nicht:* kein `antworten` nach 5 Minuten = `docker logs --since 10m webklar-workers 2>&1 | grep Posteingang`: `Anmeldung abgelehnt, Pause 6 Stunden` heißt falsches Passwort oder Benutzer: in `.env` korrigieren (Sicherung B1), einmal neu starten, nicht in einer Schleife wiederholen (der Anbieter sperrt sonst das Konto); eine `Invalid query`- oder `Index`-Zeile = B6 ist nicht vollständig durchgelaufen, Claude.
|
||||
|
||||
### C. Traefik-Route für die Vorschau-Adresse
|
||||
|
||||
**C1. Datei einspielen** (erst nach B9; Traefik lädt sie ohne Neustart).
|
||||
```
|
||||
cp /home/webklar/apps/workers/ops/traefik/workers-entwurf.yml /home/webklar/apps/traefik/dynamic/workers-entwurf.yml
|
||||
```
|
||||
*Erwartet:* keine Ausgabe; `docker logs --since 2m webklar-traefik 2>&1 | grep -i entwurf` zeigt keine Fehlerzeile. *Wenn nicht:* Fehler in der Datei: Traefik-Zeile an Claude; die Datei wieder entfernen nimmt die Route zurück.
|
||||
|
||||
**C2. Antwort und Kopfzeilen** (nach etwa 1 Minute; Traefik holt das Zertifikat beim ersten Aufruf).
|
||||
```
|
||||
curl -sI https://entwurf.project.webklar.com/abc
|
||||
```
|
||||
*Erwartet:* `HTTP/2 404`, `x-robots-tag: noindex, nofollow`, `content-security-policy: default-src 'none'; …`, `cache-control: no-store`, kein `set-cookie`. *Wenn nicht:* curl-Fehler zum Zertifikat = 5 Minuten warten, dann `docker logs --tail 50 webklar-traefik 2>&1 | grep -i entwurf`; `404` ohne `x-robots-tag` = die Anfrage landet bei einem anderen Router (DNS A5 oder Datei C1); `502` = der Dienst läuft nicht (B9).
|
||||
|
||||
**C3. Zertifikat.**
|
||||
```
|
||||
curl -sv https://entwurf.project.webklar.com/abc 2>&1 | grep -i 'issuer'
|
||||
```
|
||||
*Erwartet:* eine Zeile mit `Let's Encrypt`. *Wenn nicht:* wie bei C2 warten; steht dort `TRAEFIK DEFAULT CERT`, fehlt der DNS-Eintrag (A5).
|
||||
|
||||
**C4. Umleitung auf https und Port nicht nach außen.**
|
||||
```
|
||||
curl -sI http://entwurf.project.webklar.com/abc | head -n 3; ss -ltn | grep -c ':8093 '
|
||||
```
|
||||
*Erwartet:* `HTTP/1.1 301 Moved Permanently` mit `Location: https://entwurf.project.webklar.com/abc`, dann `0`. *Wenn nicht:* die Zahl über 0 heißt, der Port 8093 ist am Host veröffentlicht (Compose-Block prüfen, Claude); keine Umleitung = Datei C1.
|
||||
|
||||
**C5. Begrenzung** (jeder Dateiabruf liest die Datenbank; ohne diese Grenze könnte Dauerfeuer Appwrite beschäftigen: 10 Anfragen je Sekunde und Quelle, Spitze 30).
|
||||
```
|
||||
for i in $(seq 1 80); do curl -s -o /dev/null -w '%{http_code}\n' https://entwurf.project.webklar.com/abc & done | sort | uniq -c
|
||||
```
|
||||
*Erwartet:* beide Zahlen kommen vor, `404` und `429`. Öffne danach `https://entwurf.project.webklar.com/abc` einmal am Handy im Mobilfunknetz: „Nicht gefunden“, kein 429. *Wenn nicht:* gar kein `429` = die Datei wirkt nicht oder vor Traefik sitzt ein Dienst, hinter dem alle Besucher dieselbe Adresse haben (dann würde das Limit alle bremsen): Claude Bescheid, vor Dauerbetrieb klären.
|
||||
|
||||
### D. Live-Prüfungen mit `scripts/p4-livecheck.mjs`
|
||||
|
||||
Jeder Befehl macht genau eine echte Probe gegen ein echtes System und läuft im Container. Ohne `--ja-echt` tut er nichts (`Abbruch: Ohne --ja-echt wird nichts ausgeführt.`, Exit 2). Ausgegeben werden nur Zahlen, Ids, Dateinamen und Fehlercodes, nie Passwort, Schlüssel oder Mailtext. Exit 0 = bestanden, 1 = Probe fehlgeschlagen, 2 = Aufruf oder Konfiguration falsch. `smtp`, `build` und `nora` machen **einen** Versuch ohne Wiederholung. Der Dienst darf nicht angehalten sein (sonst `Abbruch: Budget gestoppt (pause)` bei `nora` und `build`).
|
||||
|
||||
**D1. Testmail** (Kosten 0 $; die einzige Probe ohne Schutz des Sende-Tors: kein Zähler, keine Sperrliste, keine Absender-Wache; nur an deine eigene Adresse). Prüfe vorher selbst, von wo sie hinausgeht (kein Geheimnis):
|
||||
```
|
||||
docker exec webklar-workers sh -c 'printenv WORKERS_SMTP_HOST; printenv WORKERS_SMTP_FROM'
|
||||
```
|
||||
*Erwartet:* der Host endet nicht auf `your-server.de`, die Domain der Absenderadresse ist weder `webklar.com` noch eine Subdomain davon. *Wenn nicht:* D1 nicht ausführen und B2 korrigieren (Sicherung aus B1, Neustart wie oben). Dann die Testmail:
|
||||
```
|
||||
docker exec webklar-workers node scripts/p4-livecheck.mjs smtp --to kenso.gri@gmail.com --ja-echt
|
||||
```
|
||||
*Erwartet:* `Testmail gesendet (ein Versuch). Message-ID: <…>`, Exit 0. In Gmail „Original anzeigen“: SPF, DKIM und DMARC `PASS`; `List-Unsubscribe: <mailto:…?subject=abmelden>, <https://entwurf.project.webklar.com/abmelden/…>` und `List-Unsubscribe-Post: List-Unsubscribe=One-Click`; die Message-ID hat nach dem @ deine Absender-Domain. *Wenn nicht:* `SMTP-Login abgelehnt (…)` = **nicht wiederholen** (der Anbieter sperrt sonst die Adresse): Benutzer und Passwort in `.env` prüfen (Sicherung B1), neu starten, erst dann einmal erneut; `Abbruch: SMTP ist nicht eingerichtet` = B2 bis B4; die Mail liegt im Spam oder ein PASS fehlt = DNS bzw. Aufwärmphase, Claude. Hat dein Anbieter die Message-ID ersetzt (zum Beispiel Google als SMTP-Server), ordnet der Dienst echte Antworten über die Adresse zu, die Pilot-Antwort in G aber nicht (sie landet als „Mail ohne Faden“ im Pult): sag Claude Bescheid, bevor du G startest.
|
||||
|
||||
**D2. Absender-Postfach lesen** (Kosten 0 $; liest nur, ändert nichts).
|
||||
```
|
||||
docker exec webklar-workers node scripts/p4-livecheck.mjs imap --ja-echt
|
||||
```
|
||||
*Erwartet:* `[antworten] uidValidity=… uidNext=… exists=…`, Exit 0; `exists` klein. *Wenn nicht:* `[antworten] Fehler: IMAP_AUTH` = Passwort oder Benutzer, nicht in einer Schleife wiederholen (B10); andere Fehler = Host oder Port (nur 993 mit TLS).
|
||||
|
||||
**D3. Chromium und Speicher** (Kosten 0 $; Chromium gegen eine Testseite im Container). Auf Wunsch in einem zweiten Fenster `docker stats webklar-workers`.
|
||||
```
|
||||
docker exec webklar-workers node scripts/p4-livecheck.mjs screenshot --ja-echt
|
||||
```
|
||||
*Erwartet* (in dieser Reihenfolge): `Testseite: http://127.0.0.1:<Port>/`, `Desktop: 3 Bilder (1366x1456, 1366x1456, 1366x<Rest>)`, `Handy: 3 Bilder (390x1456, …)` (lange Kante höchstens 1456), `Weiterleitung auf fremden Host: abgebrochen`, `Zugriffe auf /weiter am Testserver: 1` (eine Zahl ab 1), `Fremde Zugriffe auf den Testserver: 0`, `Speicher während der Probe (Container): Spitze N MB, Grenze 1024 MB`, `Node-Prozess: Spitze N MB`, Exit 0. „Spitze“ ist der Speicher des ganzen Containers samt Dateicache und `/tmp`-Speicher und übertreibt eher; Richtwert: klar unter 1024 MB (grob unter 900). Danach:
|
||||
```
|
||||
docker inspect -f '{{.State.OOMKilled}} {{.RestartCount}}' webklar-workers; docker exec webklar-workers sh -c 'ps | grep -c "[c]hromium"'
|
||||
```
|
||||
*Erwartet:* `false 0` und `0` (kein Chromium-Rest). *Wenn nicht:* eine Zeile `Fehler: …` (Aufnahme fehlgeschlagen, Weiterleitung nicht abgebrochen, fremde Zugriffe) = Pauls Prüfung oder die Netzsperre funktioniert nicht: **Pilot nicht starten**, Zeile an Claude; Spitze nahe 1024 MB oder `OOMKilled true` = die Grenze ist zu klein: Claude Bescheid, kein Bau (das Anheben von `mem_limit` und `memswap_limit` ist deine Entscheidung); ein Chromium-Rest = `docker restart webklar-workers` (`.env` ist unverändert, I3 beachten).
|
||||
|
||||
**D4. Nora** (Kosten unter 0,01 $, ein Haiku-Aufruf; prüft, ob die Aufrufwerte angenommen werden: lehnt die API sie ab, würde jede echte Antwort als „unklar“ im Pult landen).
|
||||
```
|
||||
docker exec webklar-workers node scripts/p4-livecheck.mjs nora --ja-echt
|
||||
```
|
||||
*Erwartet:* `Klasse: ja, Konfidenz: 0,xx, Thema: …, Quelle: modell`, Exit 0. *Wenn nicht:* `Fehler: Aufruf fehlgeschlagen (… 400 …)` oder `Fehler: Erwartet war die Klasse ja aus dem Modell` = **Pilot nicht starten**, Zeile an Claude.
|
||||
|
||||
**D5. Opus-Bau** (Kosten höchstens etwa 0,7 $: ein Aufruf mit Streaming, höchstens 32000 Ausgabe-Token zu 20 $ je Million; sie erscheinen auch in „API heute“; Dauer einige Minuten).
|
||||
```
|
||||
docker exec webklar-workers node scripts/p4-livecheck.mjs build --ja-echt
|
||||
```
|
||||
*Erwartet:* `Tokens: Eingabe N, Ausgabe M`, `Kosten: $X`, `Bau bestanden: N Dateien, B Byte, geschrieben nach /tmp/p4-build-test: index.html (… Byte), …`, Exit 0 (die Dateien liegen nur im flüchtigen `/tmp` des Containers). *Wenn nicht:* `Fehler: Die Ausgabe besteht die Prüfung nicht: …`, eine Zeitüberschreitung oder ein 400er-Fehler = die Kosten sind angefallen, **nicht wiederholen**, die Meldung an Claude; `Abbruch: Budget gestoppt (…)` = Pause oder Tagesgrenze (I1).
|
||||
|
||||
### E. WOMS ausliefern (P4, gegebenenfalls zusammen mit P2 und P3)
|
||||
|
||||
Erst jetzt, wenn B9 `401` zeigte: Die neuen Knöpfe rufen Routen auf, die es nur im neuen Dienst gibt. Der WOMS-Zweig `feature/workers` enthält P2, P3 und P4; war P3 Block E noch nicht dran, gehen mit diesem Push alle drei live (dann gilt zusätzlich P3 E2: die Entscheidung zur Handy-Startansicht, ohne Antwort bleibt es bei Wahl 1).
|
||||
|
||||
**E1. nginx-Vertrag prüfen** (60-Sekunden-Frist und 64-KB-Grenze für lange Antworttexte aus P1).
|
||||
```
|
||||
docker exec webklar-ticket nginx -T 2>/dev/null | sed -n '/location \/api\/workers\//,/}/p'
|
||||
```
|
||||
*Erwartet:* `limit_req zone=workers_api burst=40 nodelay;`, `proxy_read_timeout 60s;` und `client_max_body_size 64k;`. *Wenn nicht:* P1 Schritt 11 (nginx) war nicht vollständig: nachholen, bevor du pushst.
|
||||
|
||||
**E2. [Claude] Zweig vorbereiten.** Sag Claude: „WOMS-Zweig mit origin/test zusammenführen und prüfen.“ Claude führt im Ordner `/home/webklar/apps/ticket.webklar.com/dev-workers` zuerst `git fetch origin` aus, notiert `git rev-parse origin/test` als **ALT-WOMS**, sichert offene Änderungen (committen oder zurücklegen), führt `git merge origin/test` aus (nie `--force`), startet die Suite (`timeout 900 node --max-old-space-size=1024 --test --test-concurrency=2 tests/*.test.mjs tests/unit/*.test.mjs`) und den Vite-Build (`systemd-run --scope -p MemoryMax=1500M -p MemorySwapMax=0 --quiet timeout 600 npx vite build --outDir "$(mktemp -d)"`). *Erwartet:* Merge ohne offenen Konflikt, `# fail 0`, Build Exit 0. *Wenn nicht:* Claude löst Konflikte oder meldet sich; du pushst nichts, bevor alles grün ist.
|
||||
|
||||
**E3. Pushen.**
|
||||
```
|
||||
git -C /home/webklar/apps/ticket.webklar.com/dev-workers push origin feature/workers:test
|
||||
```
|
||||
*Erwartet:* Push angenommen; nach 1 bis 3 Minuten baut der Webhook. *Wenn nicht:* „non-fast-forward“ = `test` hat neue Commits: nie erzwingen, E2 wiederholen.
|
||||
|
||||
**E4. Seite ansehen.** Kein Befehl; WOMS → Hustler, Seite hart neu laden (Strg/Cmd+Umschalt+R), weiter mit F1. *Erwartet:* der Reiter „Freigabe“ lädt. *Wenn nicht:* noch 2 Minuten warten; „Das Pult ist gerade nicht erreichbar“ = B9.
|
||||
|
||||
**E5. Kein Müll im gemeinsamen `node_modules`** (nach dem Deploy; Test und Build laufen auf `build/node_modules`).
|
||||
```
|
||||
ls -d /home/webklar/apps/ticket.webklar.com/build/node_modules/.vite* 2>/dev/null
|
||||
```
|
||||
*Erwartet:* keine Ausgabe. *Wenn nicht:* Claude Bescheid, nichts selbst löschen.
|
||||
|
||||
### F. Abnahme im Browser (Pult-Knöpfe)
|
||||
|
||||
Die Knöpfe erscheinen nur an Einträgen der passenden Art. F1 machst du sofort, F2 bis F4 an den Einträgen, die der Pilot in G erzeugt (G sagt, wann), F5 am Ende.
|
||||
|
||||
**F1. Seite und Figuren.** WOMS → Hustler. *Erwartet:* „Freigabe“ lädt ohne Fehlermeldung; im Hochhaus sind Nora, Max, Clara, Theo, Bob, Bianca, Ben und Paul nicht grau (grau sind nur Such-Räume ohne Anschluss). *Wenn nicht:* Seite hart neu laden; sonst Claude.
|
||||
|
||||
**F2. Eintrag „Vorschau freigeben“** (nach G5). *Erwartet:* `Vorschau ansehen` öffnet die Vorschau in einem neuen Tab; `Freigeben & senden` fragt beim ersten Klick `Wirklich freigeben?` (verfällt nach 4 Sekunden), der zweite Klick gibt frei, oben steht `„Vorschau für Testbetrieb Muster freigeben“ freigegeben. Max sendet den Link im nächsten Sendefenster.`; `Verwerfen` fragt `Wirklich verwerfen?` und trägt den Hinweis „„Verwerfen“ sendet die Vorschau nicht.“; „Erledigt“ und „Anzeige öffnen“ gibt es bei diesem Eintrag nicht. *Wenn nicht:* steht statt des Links „Keine gültige Vorschau-Adresse hinterlegt“, ist `Freigeben & senden` gesperrt (gewollt; stimmen die Basisadresse des Dienstes und WOMS nicht überein, Claude).
|
||||
|
||||
**F3. „Als Mensch antworten“ und „Vorschau bauen“** (nach G8; an Einträgen der Art „Mensch gewünscht“, „Preisfrage“, „Unsicher – bitte prüfen“ und „Antwort per E-Mail“, deren Interessent eine Adresse hat). *Erwartet:* `Als Mensch antworten` öffnet ein Feld mit Zähler `N / 8000` (rot ab 8001), `Abbrechen` und `Jetzt senden`; Esc schließt das Feld, der Fokus geht zurück auf den Knopf, der Text bleibt erhalten; auf einem „Unsicher“-Eintrag gibt es zusätzlich `Vorschau bauen` (erster Klick `Wirklich bauen?` mit dem Hinweis „Startet einen Opus-Lauf und baut die Vorschau, als hätte der Interessent Ja gesagt.“). **Den zweiten Klick nur bei einem Interessenten, der schon eine Vorschau hat** (der Dienst baut dann nicht und antwortet mit einem Satz); sonst startet er einen echten Bau. *Wenn nicht:* beide Knöpfe fehlen, wenn ein Kollege den Eintrag übernommen hat (steht in der Zeile); `Als Mensch antworten` fehlt außerdem, wenn der Interessent keine Adresse hat, `Vorschau bauen` bei einem gesperrten, verlorenen oder Kunden-Interessenten und bei einem Eintrag ohne Interessenten (bei einem gesperrten lehnt der Dienst das Antworten von Hand ab).
|
||||
|
||||
**F4. „Antwort des Kunden einfügen“** (nur an Einträgen „Antwort auf Plattform-Anfrage“, auch an gesendeten; siehe G12). *Erwartet:* der Knopf öffnet ein Feld mit Hinweis, Zähler und `Einfügen`. *Wenn nicht:* an einem verworfenen Eintrag fehlt der Knopf, das ist richtig.
|
||||
|
||||
**F5. Handy** (390 Pixel breit, echtes Gerät oder Entwicklerwerkzeug), auf einem Eintrag mit mehreren Knöpfen. *Erwartet:* kein seitliches Scrollen, Knöpfe untereinander in voller Breite, das Antwortfeld mit Zähler und Knöpfen passt, in „Details“ ist `Schließen` mindestens 40 Pixel hoch. *Wenn nicht:* Bild und Gerät an Claude.
|
||||
|
||||
### G. Pilot mit eigenem Postfach
|
||||
|
||||
Nur Mo bis Fr zwischen 09:00 und 16:00 Uhr Berliner Zeit (Max sendet nur im Sendefenster), am besten vormittags. Die Mails gehen nur an Adressen, die dir gehören (G4: deine eigene, G10: deine Plus-Adresse, G11: eine nicht vorhandene Adresse deiner eigenen Domain); der Absender ist immer die neue Absender-Domain, nie webklar.com. Der Pilot verbraucht eine der ersten 10 Freigaben (der Zähler lässt sich nicht zurücksetzen) und kostet je Bau-Runde meist 0,3 bis 0,7 $ (höchstens 3 Runden) plus 0,05 bis 0,1 $ je Prüfrunde von Paul. **Brichst du den Pilot irgendwo zwischen G3 und G13 ab (Fehler, falscher Tag, Fenster verpasst), mach trotzdem sofort G13 (1): den Datenschutz-Schalter auf den Stand aus G1 zurück.**
|
||||
|
||||
**G1. Stand des Datenschutz-Schalters notieren.**
|
||||
```
|
||||
docker exec webklar-workers node scripts/datenschutz-schalter.mjs --status
|
||||
```
|
||||
*Erwartet:* `Datenschutz-Schalter: aus` oder `…: an`. Schreib dir das Wort auf: **Stand vorher: ____**. Am Ende (G13) stellst du genau diesen Stand wieder her; ein blindes `--aus` würde Clara stoppen, falls P3 den Schalter schon eingeschaltet hatte. *Wenn nicht:* Fehlermeldung an Claude.
|
||||
|
||||
**G2. Offene Mail-Aufträge prüfen.** Appwrite-Konsole → Datenbank `woms-database` → Sammlung `workersJobs`, Filter Status = `offen`. *Erwartet:* kein Auftrag der Art `antwort`, `vorschau_link`, `erinnerung`, `nachfass` oder `erstmail`. *Wenn nicht:* nicht einschalten: solche Aufträge gingen mit dem Schalter sofort hinaus; Claude fragen.
|
||||
|
||||
**G3. Schalter an** (nur nötig, wenn G1 `aus` zeigte; sonst überspringen). Vorher muss der Datenschutz-Abschnitt online stehen (P3 G2, dieselbe Prüfung wie in H1):
|
||||
```
|
||||
curl -sL https://www.webklar.com/datenschutz | grep -Ec 'id=.interessenten'
|
||||
```
|
||||
```
|
||||
curl -s -o /dev/null -w '%{http_code}\n' https://www.webklar.com/impressum
|
||||
```
|
||||
*Erwartet:* mindestens `1` und `200`. *Wenn nicht:* den Schalter nicht einschalten und Claude Bescheid sagen. Dann:
|
||||
```
|
||||
docker exec webklar-workers node scripts/datenschutz-schalter.mjs --an
|
||||
```
|
||||
*Erwartet:* `Datenschutz-Schalter: an`; Clara kann jetzt Entwürfe für schon bewertete echte Anfragen anlegen (sie liegen im Pult, nichts geht von selbst hinaus). *Wenn nicht:* „Unknown attribute“ = B6.
|
||||
|
||||
**G4. Pilot anlegen.**
|
||||
```
|
||||
docker exec webklar-workers node scripts/p4-livecheck.mjs pilot --to kenso.gri@gmail.com --name "Testbetrieb Muster" --ja-echt
|
||||
```
|
||||
*Erwartet:* `Pilot angelegt. Interessent: <Id>, Faden: <Id>, Auftrag: <Id>` (die Interessenten-Id aufschreiben). Innerhalb von 5 Minuten (Sende-Tick) kommt die Mail in dein Postfach: Absendername „Max, KI-Assistent von WEBklar“, Anrede „Guten Tag,“, der Testtext, ein Satz zum Angebot, Claras KI-Hinweis mit dem Datenschutz-Link (`https://www.webklar.com/datenschutz#interessenten`), darunter die Signatur „Clara, KI-Assistentin von WEBklar“ mit Adresszeile und Impressum-Link und die Zeile „Abmelden: Antworten Sie mit „abmelden“ oder nutzen Sie diesen Link: …“; das Wort „Hustler“ oder „Workers“ kommt nirgends vor. Im Hochhaus bei Max: `Antwort gesendet`. *Wenn nicht:* `Kontakt gesperrt/vorhanden: …` (Exit 1) = für diese Adresse gab es schon einen Pilot (nichts angelegt; auch nach dem Löschen der Sperrliste geht dieselbe Adresse nie wieder): nimm eine andere, zum Beispiel `kenso.gri+p2@gmail.com`; `Der Interessent … ist angelegt, Faden oder Auftrag nicht` = das Dokument mit dieser Id in `workersProspects` in der Appwrite-Konsole löschen (WOMS hat dafür keinen Knopf) und mit anderer Adresse neu; nach 10 Minuten keine Mail = Uhrzeit und Wochentag, Pause in WOMS, Schalter (G1 bis G3) prüfen, dann `docker logs --since 15m webklar-workers 2>&1 | grep -iE 'Sende-Tor|Fehler bei senden'` an Claude.
|
||||
|
||||
**G5. Erste Antwort: „ja, gern“.** Antworte direkt auf die Pilot-Mail (Antworten-Knopf, damit die Zuordnung über die Kopfzeilen klappt) mit `ja, gern`. *Erwartet:* innerhalb von 2 Minuten im Hochhaus bei Nora `Antwort eingegangen` und `Antwort eingeordnet`, dann `Ja eingegangen – Bau-Auftrag an Bob` (oder Bianca, Ben), beim Bauer `Runde 1: Bau beginnt` und nach einigen Minuten `Runde 1: N Dateien gebaut`, bei Paul `Runde 1: bestanden` (oder `Runde 1: zurück an Bob`, dann eine zweite Runde, höchstens drei); der Ereignistext „Im Pult: …“ gehört dem Worker „system“ und steht in keiner Spur, sichtbar wird der Eintrag erst in „Freigabe“; insgesamt 5 bis 15 Minuten. In „Freigabe“ steht der Eintrag „Vorschau für Testbetrieb Muster freigeben“ (Etikett „Vorschau freigeben“); „Details“ zeigt deine Antwort ohne den zitierten Mail-Fuß („Hinweise zu dieser Nachricht …“). Weiter mit F2. *Wenn nicht:* nach 3 Minuten kein `Antwort eingegangen` = B10 prüfen (Lesestand) und ob die Antwort wirklich auf die Pilot-Mail ging; `Antwort nicht eingeordnet, Budget gestoppt (…)` = Pause oder Tagesgrenze; ein Eintrag „Bau fehlgeschlagen: Testbetrieb Muster“ oder „Vorschau … nach 3 Runden nicht freigegeben“ = Text lesen, an Claude.
|
||||
|
||||
**G6. Rechte der Vorschau-Dateien** (sonst kann der Portal-Container sie später nicht lesen).
|
||||
```
|
||||
docker exec webklar-workers sh -c 'ls -ld /data/vorschau/* | head -3; ls -l /data/vorschau/*/ | head -8'
|
||||
```
|
||||
*Erwartet:* `drwxr-xr-x` für die Ordner, `-rw-r--r--` für die Dateien. *Wenn nicht:* Claude Bescheid, jeder Bau liefe sonst ins Leere.
|
||||
|
||||
**G7. Freigeben und Vorschau-Link** (F2 an diesem Eintrag). Öffne „Vorschau ansehen“, dann `Freigeben & senden` (zweimal klicken). *Erwartet:* die Vorschau-Seite öffnet ohne Anmeldung; innerhalb von 5 Minuten kommt die Mail mit dem Link, im Hochhaus `Vorschau-Link gesendet` und `Vorschau-Link verschickt`. Prüfe den Link (aus der Mail einsetzen):
|
||||
```
|
||||
curl -sI 'https://entwurf.project.webklar.com/<Token aus der Mail>/'
|
||||
```
|
||||
*Erwartet:* `HTTP/2 200`, `content-type: text/html; charset=utf-8`, `x-robots-tag: noindex, nofollow`, `content-security-policy: default-src 'none'; …`, `cache-control: no-store`, kein `set-cookie`. *Wenn nicht:* `404` = der Token ist falsch oder abgeschnitten abgeschrieben, oder die Vorschau wurde verworfen (nach einem falschen Token 60 Sekunden warten, der Dienst merkt sich „nicht gefunden“ so lange); keine Mail nach 10 Minuten wie bei G4.
|
||||
|
||||
**G8. Weitere Antworten** (alle optional, je eine neue Antwort auf die Vorschau-Mail; Nora sortiert mit einem Modell, sortiert sie einmal anders, entfällt nur der jeweilige Knopf-Test). Schreib weder „abmelden“ (das sperrt für immer; das kommt erst in G9) noch Wörter einer Beschwerde („Abmahnung“, „Unterlassung“, „Widerspruch nach Art. 21“): das sperrt die Adresse sofort und löst die Beschwerde-Mail aus.
|
||||
- `Ich möchte lieber mit einem Menschen sprechen.` *Erwartet:* Eintrag „Gespräch mit einem Menschen gewünscht“ (Etikett „Mensch gewünscht“). Teste F3: `Als Mensch antworten`, tippe `Das ist ein Test, danke.`, `Jetzt senden`. Es erscheint `„Gespräch mit einem Menschen gewünscht“ gesendet.`, im Hochhaus bei Max steht dazu nichts (bei Mails von Menschen gehört das Ereignis „Antwort gesendet“ dem Worker „system“, im Hochhaus fliegt nur ein Brief vom Pult nach außen), die Mail kommt an mit Absender „WEBklar“ und Signatur „Ein Mitarbeiter von WEBklar“ (kein KI-Hinweis, aber Abmelde-Satz).
|
||||
- `Hmm, vielleicht.` *Erwartet:* meist ein Eintrag „Unsichere Antwort“ (Etikett „Unsicher – bitte prüfen“). Teste `Vorschau bauen` zweimal: der zweite Klick liefert `Für diesen Interessenten gibt es schon eine Vorschau.` (kein Bau, kein Geld); dann `Verwerfen`.
|
||||
- `Die Vorschau gefällt mir, ich möchte sie kaufen.` *Erwartet:* Eintrag „Kaufwunsch – Kauf-Link noch nicht aktiv“ (Etikett „Preisfrage“) mit deinem Text, es geht keine Mail zurück und es entsteht kein Kauf-Link. Erledige ihn mit `Erledigt`.
|
||||
|
||||
*Wenn nicht:* nach 3 Minuten kein Eintrag = im Hochhaus bei Nora nachsehen; eine Antwort von Max statt eines Eintrags ist eine allgemeine Frage, die er selbst beantwortet (auch richtig).
|
||||
|
||||
**G9. Abmelden über den Link** (der Link steht am Ende jeder Mail). Öffne ihn im Browser, lade ihn zweimal. *Erwartet:* eine Seite mit „Möchten Sie keine Nachrichten mehr von WEBklar erhalten?“ und dem Knopf `Abmelden`; es passiert nichts (Mail-Scanner rufen jeden Link ab). Prüfe, dass noch nichts gesperrt ist:
|
||||
```
|
||||
printf 'mail:kenso.gri@gmail.com' | sha256sum | cut -c1-32
|
||||
```
|
||||
*Erwartet:* `1c62e91bf02fbdcc31efc48db472560a`; in der Appwrite-Konsole (`woms-database`, Sammlung `workersSuppression`) gibt es **kein** Dokument mit dieser Id. Klicke jetzt `Abmelden` (Gmails „Abbestellen“ macht dasselbe). *Erwartet:* „Sie wurden abgemeldet.“; das Dokument mit dieser Id existiert jetzt; im Hochhaus stempelt höchstens Arne kurz „Gesperrt“ (der Text `Abmeldung über den Link` gehört dem Worker „system“ und steht nur in der Sammlung `workersEvents` in der Appwrite-Konsole); die Vorschau-Adresse antwortet mit 404 (Vorschau verworfen). Ein neuer `pilot` an diese Adresse meldet `Kontakt gesperrt/vorhanden`. *Wenn nicht:* die Seite zeigt „Seite nicht gefunden“ = `WORKERS_UNSUB_SECRET` wurde nach dem Versand der Mail geändert, oder der Link ist abgeschnitten; „Das hat nicht geklappt.“ = Dienstlog an Claude.
|
||||
|
||||
**G10. Abmelden per Antwort** (empfohlen; braucht eine zweite Adresse, weil die erste jetzt gesperrt ist). Wiederhole G4 mit `--to kenso.gri+p2@gmail.com`. Ist die Mail angekommen, schaltest du in WOMS „Alles anhalten“ ein (Pausen-Probe) und antwortest auf die Mail mit `Bitte abmelden.`; danach „Fortsetzen“. *Erwartet:* innerhalb von 2 Minuten, auch in der Pause, im Hochhaus bei Nora `Abmeldung: Interessent gesperrt`; kein Bau. *Wenn nicht:* nichts nach 5 Minuten = B10 und Claude.
|
||||
|
||||
**G11. Unzustellbar-Probe** (empfohlen, **einmal**, nicht am Tag von G10; zwei harte Bounces unter den letzten 10 Mails lösen die Notbremse aus). Wiederhole G4 mit einer Adresse, die es nicht gibt, bei einer Domain, die dir gehört (zum Beispiel `--to nichtda-4711@webklar.com`; so trifft die Probe keinen Fremden). *Erwartet:* entweder lehnt der Empfänger-Server die Adresse sofort ab (die Adresse steht dann auf der Sperrliste) oder innerhalb weniger Minuten liegt ein Unzustellbar-Bericht im Absender-Postfach und Nora meldet `Antwort eingegangen`, `Antwort eingeordnet`; der Interessent gilt als verloren, nur diese Adresse (nicht die Domain) ist gesperrt, und ein einzelner Bounce löst die Notbremse nicht aus. *Wenn nicht:* kein Ereignis und der Bericht bleibt unbearbeitet = Claude braucht die Kopfzeilen des Berichts, **bevor** echte Interessenten angeschrieben werden.
|
||||
|
||||
**G12. Plattform-Folge-Antwort** (nur wenn es schon einen echten Eintrag „Antwort auf Plattform-Anfrage“ gibt, titelähnlich „Kleinanzeigen: <Titel der Anfrage>“; sonst überspringen). Im Reiter „Erledigt“ bei einem von dir gesendeten Eintrag: F4, `Antwort des Kunden einfügen`, Text `Wie lange dauert das?`, `Einfügen`. Nie „abmelden“ bei einem echten Interessenten einfügen (sperrt ihn für immer). *Erwartet:* `Eingefügt. Nora sortiert die Antwort ein.`; innerhalb von 2 Minuten bei Nora `Antwort von der Plattform eingegangen`, `Antwort eingeordnet` und `Rückmeldung von der Plattform – Entwurf an Clara`; kurz danach der neue Eintrag „Folge-Antwort auf Plattform-Rückmeldung“ (Claras Entwurf, endet mit KI-Signatur und Abmelde-Satz). Verwirf den Entwurf. Dasselbe Einfügen noch einmal meldet `Diese Antwort war schon eingefügt.` Max sendet auf Plattformen nie. *Wenn nicht:* kein Eintrag nach 5 Minuten = Spur von Nora und Clara lesen, Claude.
|
||||
|
||||
**G12a. Weitere Antwortformen** (optional, aber vor dem Dauerbetrieb sinnvoll; je Probe ein frischer Pilot wie in G4 mit einer eigenen Plus-Adresse, zum Beispiel `kenso.gri+p3@gmail.com`; die feste Abmelde-Regel sperrt für immer, also lieber jetzt als bei einem echten Interessenten testen).
|
||||
- Eine Antwort `Hmm, vielleicht.` (ergibt meist einen Eintrag „Unsichere Antwort“, kostet nichts) einmal aus Outlook (englische Oberfläche) und einmal aus iOS Mail, jeweils mit zitiertem Original. *Erwartet:* in „Details“ des Eintrags steht deine Antwort, der zitierte Fuß („Hinweise zu dieser Nachricht …“) nicht.
|
||||
- Zweimal `Hmm, vielleicht.`, einmal mit der Zeile `Datenschutzbeauftragter: x@y.de` darunter und einmal mit der Zeile `Bitte keine Mails mit großen Anhängen` darunter. *Erwartet:* bei Nora `Antwort eingeordnet`, der Interessent wird nicht gesperrt (kein `Abmeldung: Interessent gesperrt`); die feste Regel greift nur bei ausdrücklichen Wendungen mit „mehr“, „bitte“ oder „nie wieder“ am Satzende.
|
||||
- Eine Antwort `Ich widerspreche der Verarbeitung meiner Daten.` *Erwartet:* kein Bau und keine automatische Antwort von Max; entweder ist er danach gesperrt (bei Nora `Abmeldung: Interessent gesperrt`, `Beschwerde: Interessent gesperrt` oder `Absage: Interessent gesperrt`) oder die Antwort liegt als „Unsichere Antwort“ im Pult. Eine feste Regel gibt es dafür nicht (sie kennen nur Wendungen wie „Art. 21 DSGVO“), das Urteil kommt von Nora.
|
||||
- Den Abbestellen-Weg deines Mailprogramms (Apple Mail, Outlook; ob es den Link oder die `mailto`-Adresse nimmt, bestimmt das Programm). *Erwartet:* bei Nora `Abmeldung: Interessent gesperrt`. *Wenn nicht:* Kopfzeilen `Auto-Submitted` und `Precedence` der Abbestell-Mail (Quelltext anzeigen, ohne Adressen) an Claude, denn die Regeln prüfen „automatisch“ vor „abmelden“.
|
||||
|
||||
*Wenn nicht* (alle Punkte): wird ein Interessent gesperrt, der es nicht sein sollte, oder nicht gesperrt, der es sein sollte, den genauen Wortlaut der Antwort an Claude.
|
||||
|
||||
**G13. Zurücksetzen und Reste.** (1) Schalter: war er in G1 `aus`, jetzt `--aus`; war er `an`, **nichts tun**.
|
||||
```
|
||||
docker exec webklar-workers node scripts/datenschutz-schalter.mjs --aus
|
||||
```
|
||||
*Erwartet:* `Datenschutz-Schalter: aus` (nur wenn G1 `aus` war). (2) Sperrliste aufräumen: G9 bis G11 haben Adressen für immer gesperrt; ohne Aufräumen geht nie wieder eine Mail an sie. Berechne die Ids (je gesperrter Adresse: deine Test-Adresse, die Absenderadresse deiner Antwort in G10, falls abweichend, und die nicht vorhandene aus G11; hast du G12a gemacht, auch deren Plus-Adressen in die Liste eintragen):
|
||||
```
|
||||
for a in kenso.gri@gmail.com kenso.gri+p2@gmail.com nichtda-4711@webklar.com; do printf 'mail:%s' "$a" | sha256sum | cut -c1-32; done
|
||||
```
|
||||
und lösche diese Dokumente in der Appwrite-Konsole (`workersSuppression`). *Erwartet:* die Dokumente sind weg. (3) Reste, die bleiben dürfen: die Pilot-Interessenten in `workersProspects` (Quelle `pilot`), die Vorschau-Ordner (der Aufräumer entfernt sie nach 60 Tagen), der um 1 erhöhte Freigabe-Zähler. (4) Kosten: „API heute“ liegt nach dem Pilot grob unter 3 $ und es gab keine Budget-Meldung. *Wenn nicht:* ein gelöschtes Dokument taucht nicht auf = Id falsch (Adresse klein geschrieben, ohne Leerzeichen); deutlich mehr Kosten = Claude.
|
||||
|
||||
(5) Log nach dem ersten echten Bau (erst G5 löst die Abfrage auf `workersPreviews` mit dem Index `idx_status` und die Abfragen der Bau-Aufträge aus; die Tests prüfen nicht, ob Abfragen auf indizierten Spalten laufen):
|
||||
```
|
||||
docker logs --since 3h webklar-workers 2>&1 | grep -iE 'invalid query|index not found|attribute not found|unknown attribute|Tick abgebrochen|Unbehandelte'
|
||||
```
|
||||
*Erwartet:* keine Ausgabe. *Wenn nicht:* die Zeilen an Claude, vor H nicht weitermachen.
|
||||
|
||||
### H. Dauerbetrieb freigeben
|
||||
|
||||
Erst nach A bis G. P4 allein verschickt keine Kaltmails; im Dauerbetrieb gehen Antworten auf Anfragen, Vorschau-Links, Erinnerungen und deine Pult-Antworten hinaus. Einträge „Antwort per E-Mail“ beantwortest du jetzt mit `Als Mensch antworten` (die Mail geht über das Sende-Tor von der Absender-Domain), nicht mehr mit `E-Mail schreiben` aus deinem eigenen Programm. Max beantwortet allgemeine Fragen zur Vorschau und zum Ablauf selbst (höchstens zwei automatische Antworten je Gespräch und 24 Stunden); Preisfragen, Verhandlung, „Mensch gewünscht“, Beschwerden und alles Unsichere landen bei dir im Pult.
|
||||
|
||||
**H1. Voraussetzungen** (alle müssen stimmen, einer fehlt = nicht einschalten):
|
||||
- Die Aufwärmphase ist durch; die Mails aus D1 und G4 landen im Posteingang, nicht im Spam.
|
||||
- Der Datenschutz-Abschnitt „Interessenten“ ist live:
|
||||
```
|
||||
curl -sL https://www.webklar.com/datenschutz | grep -Ec 'id=.interessenten'
|
||||
```
|
||||
*Erwartet:* mindestens `1`; im Browser springt `https://www.webklar.com/datenschutz#interessenten` zum Abschnitt.
|
||||
- Der Lesestand steht (B10) und die offenen Mail-Aufträge sind geprüft (G2).
|
||||
- Die Absender-Prüfung aus D1 stimmt (Host nicht `your-server.de`, Domain weder `webklar.com` noch eine Subdomain davon); hast du `.env` seitdem geändert, wiederhole sie.
|
||||
- WOMS → Hustler → Hochhaus → „Einstellungen“ (Admin): Gruppe „Vorschau“ zeigt „Freigabe vor dem Versand: nur die ersten N“ mit „Anzahl N“ = 10, Gruppe „Mails“ zeigt 3 unverlangte und 15 Antwort-Mails je Tag.
|
||||
*Wenn nicht:* die Einstellung im Dialog ändern (auch „immer“ ist sicher: dann geht jede Vorschau über dich).
|
||||
|
||||
**H2. Schalter an.**
|
||||
```
|
||||
docker exec webklar-workers node scripts/datenschutz-schalter.mjs --an
|
||||
```
|
||||
*Erwartet:* `Datenschutz-Schalter: an`; mit `--status` gegenprüfen. Wie bei P3 G5 liest du die ersten fünf Entwürfe von Clara selbst, bevor etwas hinausgeht. Sobald P6 steht, nimmst du stattdessen `p6-freischalten.mjs datenschutz` (`--check`, dann `--set`; es prüft vorher die Live-Seite). *Wenn nicht:* `--aus` und Claude.
|
||||
|
||||
**H3. `WORKERS_AUTOMAIL=ja`** erst, wenn du die ersten Entwürfe gelesen hast **und** H2 schon steht (Max sendet dann Claras Entwürfe für Anfragen mit E-Mail-Adresse selbst; ein erster Antwort-Auftrag, der am Schalter hängt, hielte sonst alle späteren Antworten desselben Typs auf). Vorher: in `workersJobs` keine offenen `antwort`-Aufträge, die älter als 1 Stunde sind; I3 beachten.
|
||||
```
|
||||
cd /home/webklar/apps && cp -p .env .env.bak-$(date +%F)-automail && sed -i 's/^WORKERS_AUTOMAIL=nein$/WORKERS_AUTOMAIL=ja/' .env && docker compose up -d --no-deps workers
|
||||
```
|
||||
*Erwartet:* `docker exec webklar-workers printenv WORKERS_AUTOMAIL` zeigt `ja`. *Wenn nicht:* `nein` = Zeile in `.env` prüfen; zurück: dieselbe Zeile auf `nein` und neu starten.
|
||||
|
||||
**H4. `WORKERS_KAUFLINK` bleibt `nein`, bis die Kaufseite des Portals (P5) live ist und im Portal `WORKERS_KAUF_ENABLED=on` steht (nach der Rechtsrunde und der Testbestellung aus der P5-Anleitung)**; die P5-Anleitung nennt `WORKERS_KAUFLINK` nicht, du setzt es erst danach selbst in der `.env` auf `ja` und startest wie oben neu. Bis dahin legt Theo bei einem Kaufwunsch nach einer gesendeten Vorschau keinen Link an, sondern einen Eintrag „Kaufwunsch – Kauf-Link noch nicht aktiv“ (Etikett „Preisfrage“, mit dem Text des Kunden); du antwortest von Hand. Je Interessent gibt es diesen Eintrag nur einmal: nach `Erledigt` erzeugt ein weiterer Kaufwunsch desselben Interessenten keinen neuen, schau dann in „Details“ (Nachrichtenverlauf) nach neuen Nachrichten. *Erwartet:* `docker exec webklar-workers printenv WORKERS_KAUFLINK` zeigt `nein`. *Wenn nicht:* `ja` vor P5 = sofort auf `nein` und neu starten, sonst führt ein Kauf-Link auf eine Seite, die es nicht gibt.
|
||||
|
||||
**H5. Bounce-Notbremse.** Der Dienst stoppt den Versand selbst, wenn unter den letzten 10 gesendeten Mails 2 hart zurückkommen oder in 7 Tagen mehr als 5 % (Mindestnenner 20 Mails). Dann kommt die Mail „[Hustler] Versand gestoppt (Bounces)“ an die Berichtsadresse, im Hochhaus steht oben die rote Zeile „Versand gestoppt: <Grund>. Ein Admin kann ihn in den Einstellungen freigeben.“, und nichts geht mehr hinaus (auch nicht von Hand); alle Mail-Aufträge bleiben offen. Prüfe zuerst die Ursache (Adressquellen, Postfach, DNS und DKIM). Freigeben nur so: WOMS → Hustler → Hochhaus → „Einstellungen“ (Admin) → oben im Abschnitt „Versand gestoppt“ → `Versand wieder freigeben`. Bounces bis dahin zählen danach nicht mehr; die offenen Aufträge gehen im nächsten Sendefenster hinaus. Probe (einmal, vor dem Dauerbetrieb): in der Appwrite-Konsole im Dokument `workersSettings/main` `sendingHalted` auf wahr und `sendingHaltedReason` auf `Test` setzen. *Erwartet:* WOMS zeigt „Versand gestoppt: Test. …“; nach `Versand wieder freigeben` steht im Dokument `sendingHalted` falsch, `sendingHaltedReason` leer und `sendingHaltedClearedAt` gefüllt. *Wenn nicht:* die Meldung erscheint nicht = Seite neu laden; ein Fehler beim Freigeben = B6 war nicht vollständig, Claude.
|
||||
|
||||
**H6. Antworten von Plattformen aus dem Alarm-Postfach.** Der Betreff der Mails, mit denen Kleinanzeigen, freelancermap und freelance.de eine Kundenantwort melden, ist noch unbekannt (`REPLY_SUBJECTS` in `src/gespraeche/plattformMail.js` ist leer). Bis dahin ist nur `Antwort des Kunden einfügen` aktiv, und Antwort-Mails im Alarm-Postfach behandelt der Dienst wie jede andere Nicht-Alarm-Mail. Sobald du auf einer dieser Plattformen die erste echte Antwort auf eine von dir gesendete Nachricht bekommst, leite die Benachrichtigungs-Mail an Claude weiter (ohne persönliche Daten, nur Betreff und Aufbau); Claude trägt den Ausdruck ein und testet ihn (solche Mails ordnet nur Nora mit dem Modell ein, feste Regeln gelten für ihre Fußzeilen nicht). *Erwartet:* kein Befehl von dir. *Wenn nicht:* du bekommst Antworten, ohne dass Claude eine Mail hat = weiterleiten.
|
||||
|
||||
### I. Beobachten und Betriebshinweise
|
||||
|
||||
**I1. Kosten** (jeden Morgen). WOMS → Hochhaus, „API heute“ (darunter „von 6,00 $“); den Monat zeigt die Anthropic-Console. Ein Bau mit Opus kostet je Runde meist 0,3 bis 0,7 $, mit zweitem Versuch bis etwa 1,4 $, eine Vorschau hat höchstens 3 Runden, dazu 0,05 bis 0,1 $ je Prüfrunde von Paul: bei mehreren Vorschauen mit Wiederholungen kann die Tagesgrenze von 6 $ erreicht werden, dann warten die Bauten bis morgen (Mail „[Hustler] Budget-Stopp: Tagesbudget erreicht“, in Ottos Spur „Das Tagesbudget ist erreicht (… von 6,00 $) …“). Die Tagesgrenze gilt für Bauten, Suche und Bewertung; Antworten von Nora, Max und Theo ignorieren nur sie, nie die Monatsgrenze von 150 $. *Erwartet:* ruhige Tage ohne Budget-Meldung. *Wenn nicht:* „Budget-Warnung“ (ab 80 %) ist ein Hinweis; deutlich mehr als erwartet = Pause (J1) und Claude fragen.
|
||||
|
||||
**I2. Logs** (täglich).
|
||||
```
|
||||
docker logs --since 24h webklar-workers 2>&1 | grep -E 'Fehler bei|fehlgeschlagen|Posteingang|Sende-Tor|Bounce-Notbremse|Werkstatt|Vorschau-Aufräumen|Abmelden: Fehler|Tick abgebrochen|Unbehandelte Ablehnung|Prompt (fehlt|leer)'
|
||||
```
|
||||
*Erwartet:* keine Zeile (Zugangsdaten sind geschwärzt). *Wenn nicht:* Zeilen an Claude; `Posteingang: Anmeldung abgelehnt, Pause 6 Stunden` = Passwort des Absender-Postfachs geändert (B10). Das Freigabe-Pult zeigt standardmäßig nur die 50 jüngsten offenen Einträge: liegen mehr als 50 unter „Wartet“, bleiben die ältesten unsichtbar (auch eine alte Vorschau-Freigabe); arbeite zuerst die sichtbaren ab, dann rücken die älteren nach, oder bitte Claude, das Limit anzuheben.
|
||||
|
||||
**I3. Neustart und Update nur, wenn kein Bau läuft.** Ein Neustart oder Update stoppt den Dienst, ohne auf die Werkstatt zu warten: ein laufender Bau ist bezahlt, aber verloren, und der Auftrag verbraucht einen Versuch (nach 30 Minuten wird er wieder geöffnet; nach drei Hängern steht ein Eintrag „Bau fehlgeschlagen“ im Pult). Prüfe vorher, dass im Hochhaus weder Bob, Bianca, Ben noch Paul „arbeitet“, oder dass es in `workersJobs` keinen Auftrag der Art `bau` oder `pruefung` mit Status `laeuft` gibt. Meldet die Spur von Paul wiederholt „Zeitlimit beim Screenshot“ und er wird nicht fertig, hilft `docker restart webklar-workers` (erlaubt, wenn `.env` unverändert ist). *Erwartet:* kein Neustart, solange ein Bau läuft. *Wenn nicht:* es ist doch passiert = nichts tun, der Auftrag öffnet sich nach 30 Minuten selbst wieder; erst ein Eintrag „Bau fehlgeschlagen“ braucht dich.
|
||||
|
||||
**I4. Jede Nacht um 03:20 Uhr** entfernt der Dienst abgelaufene Vorschauen (Ordner und Dokumente, nach 60 Tagen) und liegengebliebene Reste (`.tmp-*`, `.old-*`, älter als ein Tag); Interessenten, deren Vorschau abläuft, ohne dass sie gekauft haben, gelten danach als verloren; Vorschauen mit laufendem Kauf bleiben stehen. Im Log steht nur etwas, wenn etwas schiefging (`Vorschau-Aufräumen: …`): keine Zeile = in Ordnung. Datenschutz: P4 speichert Antworttexte; das Löschen nach 90 Tagen kommt erst mit P6, erinnere Claude vor dem 90. Tag nach der ersten gespeicherten Antwort an P6. *Erwartet:* die Zeile aus I2 bleibt leer. *Wenn nicht:* `Vorschau-Aufräumen: …` an Claude (ein Ordner ließ sich nicht entfernen).
|
||||
|
||||
**I5. Meldungen und was sie heißen** (Spur im Hochhaus oder Eintrag im Pult). Kein Befehl; *Erwartet:* selten eine davon.
|
||||
- Rote Zeile oben im Hochhaus „Versand gestoppt: <Grund>. Ein Admin kann ihn in den Einstellungen freigeben.“ und die Mail „[Hustler] Versand gestoppt (Bounces)“ → H5.
|
||||
- „Kaltmails warten: das Antwort-Postfach wird nicht gelesen …“ (höchstens einmal am Tag) und die Mail „[Hustler] Antwort-Postfach nicht lesbar (IMAP-Login)“ → Zugangsdaten prüfen (D2); Antworten laufen weiter, nur Kaltmails (P6) warten.
|
||||
- „Posteingang: Anmeldung fehlgeschlagen, Pause 6 Stunden“ → B10. „Posteingang: Lesestand neu gesetzt (UID-Gültigkeit geändert) …“ → der Anbieter hat das Postfach umgestellt, Mails seit dem letzten Lesen können fehlen: Postfach von Hand ansehen.
|
||||
- „SMTP-Login abgelehnt (…), bis zum nächsten Berliner Tag kein weiterer Versuch“ und die Mail „[Hustler] Versand an Interessenten gestoppt (SMTP-Login)“ → die Zugangsdaten `WORKERS_SMTP_*` prüfen; Aufträge bleiben offen.
|
||||
- Pult „Unklar, ob gesendet“ → im Postfach des Absenders unter „Gesendet“ nachsehen, ob die Mail rausging. Legt dein Anbieter SMTP-Mails nicht unter „Gesendet“ ab: in der Appwrite-Konsole (`woms-database`, Sammlung `workersMessages`) das Dokument mit der Nachrichten-Id aus dem Pult-Text öffnen, die Message-ID aus dem Feld `messageId` im Versandprotokoll des Anbieters suchen oder beim Empfänger nachfragen; im Zweifel nicht noch einmal senden. „Mail konnte nicht gesendet werden“, „Mail-Auftrag fehlgeschlagen“, „Mail nicht gesendet: <Grund>“, „Max konnte keinen regelkonformen Entwurf erstellen“ → du antwortest von Hand (`Als Mensch antworten`) oder verwirfst.
|
||||
- Pult „Unsichere Antwort“, „Antwort konnte nicht eingeordnet werden“, „Antwort ohne Interessent“, „Mail ohne Faden“ (höchstens 10 am Tag), „Adresse nicht auswertbar, bitte prüfen“ → du entscheidest. „Mail UID n nicht verarbeitet, Postfach prüfen“ und „… wurde gekürzt gelesen, Postfach prüfen“ → schau die Mail im Postfach an: es könnte eine Abmeldung oder Beschwerde sein.
|
||||
- Pult „Beschwerde oder rechtliche Drohung“ (dazu die Mail „[Hustler] Beschwerde oder rechtliche Drohung“) → selbst lesen; der Absender ist gesperrt; ohne Rechtsrat nichts senden.
|
||||
- Pult „Bau fehlgeschlagen: <Name>“ und „Vorschau für <Name> nach 3 Runden nicht freigegeben“ → die Vorschau ansehen (Link im Eintrag) und entscheiden: von Hand ansprechen oder verwerfen.
|
||||
- Mails „[Hustler] Budget-Warnung: …“ und „[Hustler] Budget-Stopp: …“ und dieselben Meldungen in Ottos Spur → I1.
|
||||
*Wenn nicht:* eine Meldung, die hier fehlt, mit Wortlaut an Claude.
|
||||
|
||||
### J. Rückweg
|
||||
|
||||
**J1. Sofort stoppen** (verliert nichts). WOMS → Hustler → Hochhaus → „Alles anhalten“ → „Anhalten“. *Erwartet:* Statuszeile „Angehalten: Es wird nichts gesendet und nichts gebaut.“ Dann sendet nichts mehr (auch von Hand nicht: „Hustler ist pausiert.“), und Bauen, Prüfen und Einordnen stehen; Nora liest weiter, feste Regeln (Abmeldung, Abmahnung, Unzustellbar-Bericht, Abwesenheit) wirken sofort, alle anderen Antworten warten bis „Fortsetzen“; Vorschau-Seiten und Abmelde-Links bleiben erreichbar. *Wenn nicht:* Meldung unter dem Knopf lesen, Seite neu laden, Claude.
|
||||
|
||||
**J2. Datenschutz-Schalter auf den notierten Stand** (Wort aus G1; sollen Erstantworten aufhören: `--aus`).
|
||||
```
|
||||
docker exec webklar-workers node scripts/datenschutz-schalter.mjs --aus
|
||||
```
|
||||
*Erwartet:* `Datenschutz-Schalter: aus`. *Wenn nicht:* Fehlermeldung an Claude.
|
||||
|
||||
**J3. P4 ganz zurücknehmen** (nur, wenn **noch keine echte Mail an einen Interessenten** hinausging; sonst läuft P4 weiter und du nutzt J1 und J2: die schon verschickten Vorschau- und Abmelde-Links führten sonst ins Leere und Abmeldungen kämen nicht an; außerdem kennt die `.env`-Sicherung das Abmelde-Geheimnis nicht). Reihenfolge: J1, dann Traefik-Datei weg, Sicherungen zurück, altes Image und alter Stand, Dienst neu.
|
||||
```
|
||||
rm /home/webklar/apps/traefik/dynamic/workers-entwurf.yml && cd /home/webklar/apps && cp -p .env.bak-<Datum>-workers-p4 .env && cp -p docker-compose.yml.bak-<Datum>-workers-p4 docker-compose.yml
|
||||
```
|
||||
```
|
||||
docker tag webklar-workers:vor-p4 webklar-workers:latest && git -C /home/webklar/apps/workers checkout --detach b742e79 && cd /home/webklar/apps && docker compose up -d --no-deps workers
|
||||
```
|
||||
(`b742e79` ist ALT-DIENST aus A2; der Dienst liest die Rollen-Texte aus dem Checkout, darum gehört der alte Stand dazu. Fehlt das Image `vor-p4`: `docker compose build workers` baut den alten Stand.) *Erwartet:* `curl -s https://ticket.webklar.com/api/workers/health` antwortet wie in A1; `docker logs --tail 20 webklar-workers | grep -c 'vorschau listening'` gibt `0`; `curl -sI https://entwurf.project.webklar.com/abc` liefert kein `x-robots-tag: noindex, nofollow` mehr. Vor dem nächsten Update: `git -C /home/webklar/apps/workers checkout main`, sonst scheitert `git pull --ff-only`. *Wenn nicht:* Bau- oder Startfehler an Claude.
|
||||
|
||||
**J4. WOMS zurücknehmen** (nur falls nötig; wie P3 I6 mit **ALT-WOMS** aus E2). Claude führt `git revert --no-edit $(git rev-list --no-merges ALT-WOMS..HEAD)` im Ordner `/home/webklar/apps/ticket.webklar.com/dev-workers` aus, du pushst `git -C /home/webklar/apps/ticket.webklar.com/dev-workers push origin feature/workers:test`. *Erwartet:* die neuen Knöpfe sind weg; gingen P2 und P3 im selben Push live (E), nimmt dieser Rückweg alle drei zurück. Soll nur der Betrieb stoppen, genügen J1 und J2. *Wenn nicht:* Claude Bescheid.
|
||||
|
||||
Was beim Rückweg bleibt: Die neuen Schema-Felder bleiben (sie schaden nicht). Offene Aufträge für Bau, Prüfung, Einordnung und Mails bleiben `offen` und warten (der P3-Dienst holt nur seine eigenen Arten); gebaute Vorschauen bleiben im Volume `workers_data` unter `/data/vorschau`, sind aber nicht mehr erreichbar, und der Aufräumer entfernt sie nach Ablauf, sobald P4 wieder läuft. Mails, die im Absender-Postfach eintreffen, während P4 aus ist, liest P4 beim nächsten Start nach (der Lesestand bleibt im Volume).
|
||||
|
||||
**Fertig, wenn:** B9, B10, C2, D1 bis D5, F1 und G (bis zum Zurücksetzen in G13) ihre „Erwartet“-Zeilen erfüllen. Der Dauerbetrieb (H) ist eine eigene Entscheidung.
|
||||
Reference in new issue
Block a user