docs: Doku-Abgleich mit origin/main (Stand 2026-10-16)
Docker-Images bauen und veroeffentlichen / lint (push) Successful in 1m30s
Docker-Images bauen und veroeffentlichen / typecheck (push) Successful in 1m48s
Docker-Images bauen und veroeffentlichen / test (push) Successful in 1m33s
Docker-Images bauen und veroeffentlichen / build-and-push (push) Successful in 7m20s
Docker-Images bauen und veroeffentlichen / lint (push) Successful in 1m30s
Docker-Images bauen und veroeffentlichen / typecheck (push) Successful in 1m48s
Docker-Images bauen und veroeffentlichen / test (push) Successful in 1m33s
Docker-Images bauen und veroeffentlichen / build-and-push (push) Successful in 7m20s
README mit Projektstand (Links auf Issues #33, #32), fehlenden Befehlen und CI-Gate. BETRIEB: sha-gepinnte Manifeste, DB-Sicherung, Rollout per set image, Label-Selector im pg_dump-Befehl, Storage Box. k8s/README: Schritt 09, Warnung vor delete namespace. TESTS, OFFENE-PUNKTE, ARCHITEKTUR (ADR-8, ADR-9) aktualisiert; Kommentare in .env.example und Worker-CronJob korrigiert. Refs #31 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
9785eb221f
commit
8a85bfaed4
8 files changed
+85
-33
No files matched your search
@@ -92,3 +92,15 @@ Der gehostete Checkout bildet den Ablauf vollständig ab: Betrag, Ablaufzeit, da
|
||||
## ADR-7: Adminbereich
|
||||
|
||||
Better Auth übernimmt E-Mail und Passwort, Registrierung ist ausgeschaltet. Konten entstehen nur über die Kommandozeile, TOTP-2FA ist Pflicht. Rate Limits der Anmeldung liegen in PostgreSQL, Passwörter werden gegen Datenlecks geprüft. Jede Seite, jede Server-Action und der CSV-Export prüfen Sitzung und 2FA selbst. Der Proxy leitet nur vorab um. Alle Buchungs-, Zahlungs- und Konfigurationsaktionen landen im AuditLog.
|
||||
|
||||
## ADR-8: Kontaktformular „Erstgespräch“ (seit 06.10.2026)
|
||||
|
||||
- Eigener Abschnitt nach den Fragen (Anker `#erstgespraech`, `POST /api/contact`). Pflicht sind Name, E-Mail, Telefon (seit 07.10.2026, gleiche Regel wie bei der Buchung) und die Bestätigung der Datenschutzhinweise; Erreichbarkeit und Nachricht sind optional.
|
||||
- Kein eigenes Datenmodell: Die Anfrage geht als E-Mail über den transaktionalen Postausgang an die Veranstalter-E-Mail aus dem Admin, ersatzweise `ADMIN_NOTIFY_EMAIL`. Ohne Empfänger lehnt das Formular ab.
|
||||
- Bewusst keine automatische Bestätigungsmail an die angegebene Adresse, damit das Formular nicht zum Versand an Dritte missbraucht werden kann.
|
||||
- Schutz wie bei der Buchung: nur JSON von der eigenen Seite, Rate Limit 5 Anfragen je Stunde und IP, Honeypot-Feld gegen Bots, doppeltes Absenden in derselben Minute ergibt eine Mail.
|
||||
|
||||
## ADR-9: Client-IP und Rate Limits (seit 12.10.2026)
|
||||
|
||||
- Rate Limits liegen in PostgreSQL (`RateLimitBucket`, gehashter IP-Schlüssel, Aufräumen nach einem Tag durch den Worker). IPv6-Adressen zählen je /64-Netz.
|
||||
- Die Client-IP ist die Gegenstelle laut Traefik (letzter `X-Forwarded-For`-Eintrag). `CF-Connecting-IP` gilt nur als öffentliche Unicast-Adresse, `X-Real-IP` ohne `X-Forwarded-For` nur außerhalb der Produktion. Better Auth bekommt die IP ausschließlich über den serverseitig gesetzten Header `x-artista-client-ip`; ein vom Browser mitgeschickter Wert wird verworfen.
|
||||
+22
-12
@@ -2,16 +2,18 @@
|
||||
|
||||
## 1. Images bauen
|
||||
|
||||
**Automatisch (Gitea Actions):** `.gitea/workflows/docker-build.yml` baut bei jedem Push auf `main`, bei Tags `v*` oder manuell per „Run workflow“ beide Images und pusht sie in die Gitea-Registry:
|
||||
**Automatisch (Gitea Actions):** `.gitea/workflows/docker-build.yml` läuft bei jedem Push auf `main`, bei Tags `v*` oder manuell per „Run workflow“. Zuerst prüfen drei Jobs auf dem isolierten Runner (`ci-isolated`, ohne Docker-Socket) den Code: `lint` (inklusive `pnpm audit --prod --audit-level high`), `typecheck` und `test` (mit PostgreSQL 18.6 als Service). Nur wenn alle drei grün sind, baut `build-and-push` auf dem Runner `docker-builder` beide Images und pusht sie in die Gitea-Registry:
|
||||
|
||||
- `main` ergibt die Tags `latest` und `sha-<kurz>`
|
||||
- `v0.1.0` ergibt zusätzlich den Tag `0.1.0`
|
||||
|
||||
Einmalig einrichten:
|
||||
- ein Personal Access Token mit Scope `package` als Repo-Secret `REGISTRY_TOKEN` hinterlegen (Repo-Einstellungen → Actions → Secrets)
|
||||
- einen Runner mit dem Label `docker-builder` bereitstellen (wie bei Wabenhain)
|
||||
- Runner mit den Labels `ci-isolated` (Prüfungen) und `docker-builder` (Image-Build) bereitstellen; im EnCry-Cluster sind beide vorhanden
|
||||
|
||||
Die Manifeste in `k8s/` nutzen den Tag `latest`. Für feste Versionen dort `:latest` durch z. B. `:0.1.0` ersetzen (`git tag v0.1.0 && git push origin v0.1.0`).
|
||||
Die Manifeste in `k8s/` sind auf einen CI-Build gepinnt (`sha-<commit>`, Platzhalter `sha-REPLACE_ME` im Repo), nicht auf `latest`. Ausgerollt wird mit `kubectl set image`, siehe Abschnitt 3 und [k8s/README.md](../k8s/README.md).
|
||||
|
||||
Scheitert `build-and-push` beim Push mit `500 … cannot allocate memory`, lag das bisher an der Gitea-Registry, wenn gleichzeitig ein anderes Repo pushte. Dann den Lauf neu starten, sobald der andere Build fertig ist.
|
||||
|
||||
**Manuell:**
|
||||
|
||||
@@ -29,24 +31,32 @@ Der Build braucht Internet für `next/font` (Schriften werden eingebettet), aber
|
||||
- der Worker-CronJob, nötig für Reservierungsfreigabe, Abgleich der Folgeraten und Mail-Wiederholung
|
||||
- ConfigMap
|
||||
- zwei NetworkPolicies (Schutz der Rate Limits und der Datenbank)
|
||||
- der Sicherungs-CronJob `artista-db-backup` (täglicher `pg_dump`, Abschnitt 7)
|
||||
|
||||
Eine eigene Sicherung im Cluster gibt es nicht, die SMB-Freigabe wird auf dem NAS gesichert.
|
||||
**Schritt für Schritt zum Kopieren: [k8s/README.md](../k8s/README.md).** Die Manifeste liegen flach in `k8s/` (`00-namespace` bis `09-db-backup-cronjob`, Namensschema wie bei Wabenhain) und werden in dieser Reihenfolge einzeln angewendet. Die Secrets kommen aus `k8s/02-secret.yaml.example` und werden nicht eingecheckt. Pod Security: Erzwungen wird `baseline`, damit der Zertifikats-Solver von cert-manager starten kann. `restricted` wird nur gemeldet, die eigenen Pods erfüllen es.
|
||||
|
||||
**Schritt für Schritt zum Kopieren: [k8s/README.md](../k8s/README.md).** Die Manifeste liegen flach in `k8s/` (`00-namespace` bis `08-networkpolicy`, Namensschema wie bei Wabenhain) und werden in dieser Reihenfolge einzeln angewendet. Die Secrets kommen aus `k8s/02-secret.yaml.example` und werden nicht eingecheckt. Pod Security: Erzwungen wird `baseline`, damit der Zertifikats-Solver von cert-manager starten kann. `restricted` wird nur gemeldet, die eigenen Pods erfüllen es.
|
||||
Im EnCry-Cluster liegen die SMB-Freigaben auf der Hetzner Storage Box, nicht auf einem lokalen NAS; „NAS“ meint im Folgenden diese Freigabe. Im Namespace `artista` läuft außerdem Artista-Telefonie (eigenes Repo `Artista-TeleTracking`). Sie nutzt eine eigene Datenbank `telefonie` in derselben PostgreSQL-Instanz `artista-modelcamp-postgres`. Wer die Instanz oder den Namespace anfasst, trifft beide Anwendungen.
|
||||
|
||||
Zu PostgreSQL:
|
||||
- **PostgreSQL auf SMB ist eine bewusste Ausnahme.** SMB garantiert Sperren und fsync nicht in jedem Fall wie ein lokales Dateisystem. Bei einem NAS- oder Netzwerkausfall während Schreibvorgängen kann die Datenbank beschädigt werden.
|
||||
- **Gemildert** wird das durch `hard`, `cache=strict`, SMB-Verschlüsselung (`seal`) und ein 120 Sekunden langes, sauberes Herunterfahren. Die Rechte setzen die `mountOptions`, weil `fsGroup` auf SMB nicht wirkt: Postgres `uid=70`, `0700`; Medien `uid=1001`, nur lesbar.
|
||||
- **Sicherung:** Die NAS-Sicherung ist für die laufende Datenbank nur mit **atomaren Snapshots** der Freigabe (Btrfs/ZFS) konsistent. Zusätzlicher Schutz bei Bedarf: gelegentlich einen `pg_dump` ziehen (Abschnitt 7).
|
||||
- **Sicherung:** Eine Kopie der Freigabe ist für die laufende Datenbank nur mit **atomaren Snapshots** (Btrfs/ZFS) konsistent. Deshalb zieht der CronJob `artista-db-backup` jede Nacht einen `pg_dump` (Abschnitt 7).
|
||||
- **Nach SMB-Unterbrechungen** melden lang laufende Postgres-Prozesse gelegentlich `could not seek to end of file … Bad file descriptor`. Abhilfe: `kubectl -n artista rollout restart sts/artista-modelcamp-postgres` (fährt sauber herunter).
|
||||
|
||||
## 3. Update ausrollen
|
||||
|
||||
App, Migration und Worker immer mit demselben Tag `sha-<commit>` aus der CI ausrollen (genauer Befehl in [k8s/README.md](../k8s/README.md), Abschnitt „Bei einem neuen Image“):
|
||||
|
||||
```bash
|
||||
kubectl -n artista rollout restart deploy/artista-modelcamp-app
|
||||
TAG=sha-<commit>
|
||||
kubectl -n artista set image deployment/artista-modelcamp-app migrate=git.encry.de/nick.rosenloecher/artista-modelcamp-tools:$TAG app=git.encry.de/nick.rosenloecher/artista-modelcamp:$TAG
|
||||
kubectl -n artista set image cronjob/artista-modelcamp-worker worker=git.encry.de/nick.rosenloecher/artista-modelcamp-tools:$TAG
|
||||
kubectl -n artista rollout status deploy/artista-modelcamp-app
|
||||
kubectl -n artista logs deploy/artista-modelcamp-app -c migrate # Migrationsausgabe
|
||||
```
|
||||
|
||||
Ein `rollout restart` allein holt kein neues Image, weil die Manifeste auf einen festen Tag zeigen.
|
||||
|
||||
Jeder neue App-Pod migriert per initContainer zuerst die Datenbank. Scheitert das, startet der Pod nicht, und die alten Pods laufen weiter.
|
||||
|
||||
Migrationen sind vorwärtskompatibel zu schreiben (erst Spalten ergänzen, später entfernen), damit alte und neue Pods während des Rollouts parallel laufen können.
|
||||
@@ -85,10 +95,10 @@ Ein fehlgeschlagener Lauf erscheint als fehlgeschlagener Job (`kubectl -n artist
|
||||
|
||||
## 7. Sicherung und Wiederherstellung
|
||||
|
||||
- **Sicherung:** Die NAS-Sicherung der SMB-Freigabe übernimmt das Speichersystem. Für PostgreSQL gilt das nur mit atomaren Snapshots, siehe Abschnitt 2. Im Cluster läuft kein Backup-Job.
|
||||
- **Logischer Dump** (empfohlen vor Updates und vor dem Live-Verkauf):
|
||||
- **Täglicher Dump im Cluster:** Der CronJob `artista-db-backup` (`k8s/09-db-backup-cronjob.yaml`) läuft um 02:25 Uhr (Zeitzone des Clusters) und schreibt `pg_dump -Fc` der Datenbank `artista` in die PVC `artista-db-backup` (StorageClass `smb-backup`, Ordner `Backups/artista/` auf der Storage Box). Aufbewahrung: 14 Tage täglich (`daily/`), 8 Wochen sonntags (`weekly/`). Die Datenbank `telefonie` derselben Instanz ist darin nicht enthalten. Stand prüfen: `kubectl -n artista get cronjob artista-db-backup` und `kubectl -n artista get jobs | grep artista-db-backup`.
|
||||
- **Logischer Dump von Hand** (zusätzlich vor Updates und vor dem Live-Verkauf):
|
||||
```bash
|
||||
POD=$(kubectl -n artista get pod -l app.kubernetes.io/name=artista-modelcamp-postgres -o name | head -1)
|
||||
POD=$(kubectl -n artista get pod -l app=artista-modelcamp-postgres -o name | head -1)
|
||||
kubectl -n artista exec $POD -- pg_dump -U artista -d artista --format=custom > artista-$(date +%F).dump
|
||||
```
|
||||
- **Wiederherstellen:**
|
||||
@@ -96,8 +106,8 @@ Ein fehlgeschlagener Lauf erscheint als fehlgeschlagener Job (`kubectl -n artist
|
||||
2. Einspielen: `kubectl -n artista exec -i $POD -- pg_restore -U artista -d artista --clean --if-exists < artista-YYYY-MM-DD.dump`
|
||||
3. App wieder hochskalieren (der initContainer migriert dabei), Worker fortsetzen.
|
||||
4. Abgleich: Zahlungen, die nach dem Sicherungszeitpunkt eingingen, im Stripe-Dashboard prüfen. Stripe stellt Webhooks bis zu drei Tage erneut zu (Dashboard → Webhooks → „Erneut senden“).
|
||||
- **Medien:** liegen im SMB-Ordner `modelcamp-media` und sind in der NAS-Sicherung enthalten.
|
||||
- **Wiederherstellung üben:** mindestens einmal vor dem Live-Verkauf in einen Test-Namespace.
|
||||
- **Medien:** liegen im SMB-Ordner `modelcamp-media`; gesichert sind sie nur über die Sicherung der Freigabe selbst.
|
||||
- **Wiederherstellung üben:** mindestens einmal vor dem Live-Verkauf in einen Test-Namespace. Das ist noch nicht geschehen.
|
||||
|
||||
## 8. Stornierung und Erstattung
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Noch benötigte Inhalte und Freigaben
|
||||
|
||||
Stand 01.10.2026. Bereits bestätigt und per Migration `20261001120000_camp_2027_bestaetigt` eingetragen (im Admin änderbar):
|
||||
Stand 16.10.2026. Dieselben Punkte stehen mit Verweis auf die Detail-Issues in der Gitea-Sammelliste [#32 „Inhaber-Aufgaben“](https://git.encry.de/Nick.Rosenloecher/Artista-Filmcamp/issues/32).
|
||||
|
||||
Bereits bestätigt und per Migration `20261001120000_camp_2027_bestaetigt` bzw. `20261002090000_termin_mai_2027` eingetragen (im Admin änderbar). Damit sind im Admin die Freigaben Termin, Ort, Unterkunft und Platzzahl gesetzt, sofern sie dort niemand zurückgenommen hat:
|
||||
|
||||
- Termin 03.05. bis 09.05.2027 (laut Wochenplan vom 02.10.2026), Villa La Chiesina, Arcidosso (Toskana)
|
||||
- Unterbringung: eigenes Bett im geteilten Zimmer, keine Einzelzimmer
|
||||
@@ -9,7 +11,7 @@ Stand 01.10.2026. Bereits bestätigt und per Migration `20261001120000_camp_2027
|
||||
- Tagesablauf aller sieben Tage, Bustransfer ab und bis Florenz, Verpflegung (Frühstück, Snacks, Abendessen)
|
||||
- Early Bird 01.11. bis 31.12.2026, ohne Anzeige eines Verkaufsstarts
|
||||
|
||||
Solange die mit **(Freigabe)** markierten Punkte fehlen, bleibt der Live-Verkauf serverseitig gesperrt. Der aktuelle Stand steht im Admin-Dashboard unter „Fehlt für den Live-Verkauf“.
|
||||
Solange die mit **(Freigabe)** markierten Punkte fehlen, bleibt der Live-Verkauf serverseitig gesperrt. Der aktuelle Stand steht im Admin-Dashboard unter „Fehlt für den Live-Verkauf“. Sind alle Freigaben erteilt und ist der Live-Verkauf eingeschaltet, startet der Verkauf sofort zum Early-Bird-Preis; die Early-Bird-Phase läuft vom 01.11. bis 31.12.2026.
|
||||
|
||||
## Inhalte
|
||||
|
||||
@@ -40,7 +42,8 @@ Solange die mit **(Freigabe)** markierten Punkte fehlen, bleibt der Live-Verkauf
|
||||
|
||||
## Betrieb
|
||||
|
||||
- Stripe-Konto live verifiziert, Webhook-Endpunkte (Test und Live) mit Secrets angelegt.
|
||||
- SMTP-Anbieter sowie SPF, DKIM und DMARC der Absenderdomain.
|
||||
- Domain, TLS und StorageClasses im Cluster (siehe docs/BETRIEB.md).
|
||||
- Wiederherstellung aus der Sicherung einmal geübt.
|
||||
- Stripe-Konto live verifiziert, Webhook-Endpunkte (Test und Live) mit Secrets angelegt, Billing-Einstellungen für Folgeraten gesetzt (docs/BETRIEB.md, Abschnitt 4).
|
||||
- SMTP-Anbieter sowie SPF, DKIM und DMARC der Absenderdomain; Veranstalter-E-Mail oder `ADMIN_NOTIFY_EMAIL` gesetzt, sonst lehnt das Formular „Erstgespräch“ Anfragen ab.
|
||||
- Erledigt: Domain `modelcamp.artistasphotography.de`, TLS über cert-manager, SMB-Speicher und die StorageClass `smb-backup` im Cluster.
|
||||
- Wiederherstellung aus der Sicherung einmal geübt (noch offen).
|
||||
- Optional: Google-Rezensionen (`GOOGLE_PLACES_API_KEY`, `GOOGLE_PLACE_ID` im Secret); ohne Werte bleibt der Abschnitt ausgeblendet.
|
||||
+11
-6
@@ -1,10 +1,14 @@
|
||||
# Tests und Abnahme
|
||||
|
||||
Stand 27.09.2026. Alle aufgeführten Läufe sind lokal ausgeführt und bestanden.
|
||||
Stand 16.10.2026. Die Abschnitte unten sind chronologisch gewachsen; der aktuelle Stand steht hier oben.
|
||||
|
||||
**Aktuell:** `pnpm test` umfasst 10 Testdateien (rund 130 Tests; 132 beim lokalen Lauf am 14.10.2026 zu Commit `f29dbcf`, seither kam mit `9785eb2` ein Regressionstest hinzu). Seit `0421d7d` (14.10.2026) laufen `lint` mit `pnpm audit`, `typecheck` und `test` bei jedem Push auf `main` in der CI; der Test-Job nutzt PostgreSQL 18.6 als Service (`TEST_DATABASE_URL`). Letzter CI-Lauf (`9785eb2`, 15.10.2026): lint, typecheck und test grün, nur der Image-Build schlug fehl (Issue #20). Die Playwright-Tests (`pnpm test:e2e`, 3 Tests je Profil) laufen nur lokal.
|
||||
|
||||
Seit dem ersten Stand hinzugekommene Testdateien: `client-ip.test.ts` (Client-IP hinter Traefik und Cloudflare, IPv6 je /64, Proxy um NextRequest), `contact.integration.test.ts` (Formular „Erstgespräch“), `email-outbox.integration.test.ts` (Postausgang, endgültige und vorübergehende SMTP-Fehler), `review-format.test.ts` (Google-Rezensionen).
|
||||
|
||||
## Automatisierte Tests
|
||||
|
||||
`pnpm test` umfasst 72 Tests in 6 Dateien. Sie laufen gegen eine echte, frisch gestartete PostgreSQL-18-Instanz, damit Zeilensperren und Trigger mitgetestet werden.
|
||||
Stand 27.09.2026: `pnpm test` umfasste 72 Tests in 6 Dateien. Sie laufen gegen eine echte, frisch gestartete PostgreSQL-18-Instanz, damit Zeilensperren und Trigger mitgetestet werden.
|
||||
|
||||
| Geschäftsrisiko | Datei |
|
||||
|---|---|
|
||||
@@ -33,7 +37,7 @@ Stand 27.09.2026. Alle aufgeführten Läufe sind lokal ausgeführt und bestanden
|
||||
|
||||
Bildschirmfotos aller drei Größen wurden visuell geprüft.
|
||||
|
||||
Letzter Lauf 01.10.2026 nach Einbau von Team, Villa-Bildern und bestätigtem Termin: 81/81 Unit- und Integrationstests, 9/9 E2E-Tests, Produktionsbuild grün. Team und Unterkunft wurden zusätzlich per Bildschirmfoto auf Smartphone (390 px) und Desktop (1440 px) geprüft. Mit Termin 08.05.2027 fällt die letzte Rate auf den 08.04.2027.
|
||||
Letzter Lauf 01.10.2026 nach Einbau von Team, Villa-Bildern und bestätigtem Termin: 81/81 Unit- und Integrationstests, 9/9 E2E-Tests, Produktionsbuild grün. Team und Unterkunft wurden zusätzlich per Bildschirmfoto auf Smartphone (390 px) und Desktop (1440 px) geprüft. Mit dem damaligen Termin 08.05.2027 fiel die letzte Rate auf den 08.04.2027; seit dem Termin 03.05.2027 (Migration vom 02.10.2026) ist es der 03.04.2027.
|
||||
|
||||
Hinweis: Läuft der Testserver nicht unter der Adresse aus `APP_URL`, lehnt der Same-Origin-Schutz die Preisabfrage ab (403). Dann hängt der Buchungsdialog bei „Preise werden geladen …“. Server deshalb mit passender `APP_URL` starten, z. B. `APP_URL=http://localhost:3005 PORT=3005 pnpm start` und `E2E_BASE_URL=http://localhost:3005 pnpm test:e2e`.
|
||||
|
||||
@@ -53,7 +57,8 @@ Lauf 06.10.2026 nach Umstellung der Folgeraten auf Stripe Billing (inkl. Anhalte
|
||||
|
||||
## Nicht ausgeführt / Einschränkungen
|
||||
|
||||
- **Echte Stripe-Testbuchung** gegen die Stripe-API: Ein Stripe-Testschlüssel lag nicht vor. Die Stripe-Logik ist gegen eine Attrappe mit Stripe-Semantik getestet (Idempotenz, Session-Zustände, Rechnungen des Ratenplans), die Webhook-Signatur mit der echten Stripe-Bibliothek. Mit Schlüssel: Anleitung in der README (`stripe listen`, Testkarten).
|
||||
- **Docker-Image und Cluster:** Auf dem Entwicklungsrechner gibt es kein Docker und keinen Cluster-Zugang. Das Dockerfile ist nicht gebaut und nicht im Cluster ausgerollt. Geprüft sind der Standalone-Build und das Rendern der Manifeste.
|
||||
- **SMTP-Versand:** nur über den Datei-Testausgang geprüft.
|
||||
- **Vollständige Stripe-Testbuchung** über die Oberfläche bis zum Webhook: In der Testsuite läuft die Stripe-Logik gegen eine Attrappe mit Stripe-Semantik (Idempotenz, Session-Zustände, Rechnungen des Ratenplans), die Webhook-Signatur mit der echten Stripe-Bibliothek. Gegen die echte Stripe-Test-API geprüft ist bisher nur der Ratenplan (`StripeGateway` mit Testuhr, Lauf vom 06.10.2026). Ein dokumentierter Durchlauf Buchung → Checkout → Webhook → Bestätigungsmail auf dem Cluster fehlt (Issue #27). Anleitung lokal in der README (`stripe listen`, Testkarten).
|
||||
- **Docker-Image und Cluster:** Seit dem 27.09.2026 baut die CI beide Images; die Seite läuft im Cluster (zuletzt belegt ausgerollt: `sha-5a88f3d`, 13.10.2026). Eine automatisierte Prüfung nach dem Rollout gibt es nicht; der Monitoring-Dienst Gatus im Cluster prüft die Erreichbarkeit.
|
||||
- **SMTP-Versand:** im Repo nur über den Datei-Testausgang geprüft. Ob im Cluster ein echter SMTP-Zugang eingetragen ist, ist hier nicht dokumentiert.
|
||||
- **E2E-Tests** laufen nicht in der CI.
|
||||
- **Referenzseite:** nur über eine Textzusammenfassung ausgewertet (siehe ARCHITEKTUR.md).
|
||||
Reference in new issue
Block a user