390 lines
18 KiB
Markdown
390 lines
18 KiB
Markdown
# DOGFATHER UNIVERSE — Interner Bereich (Cloudflare Worker + D1)
|
|
|
|
Setzt das Anforderungsdokument **„Geschützter Zugang, Rollen und Benutzerverwaltung"**
|
|
(`Geschuetzter_Zugang_Rollen_Benutzerverwaltung.pdf`) vollständig um: Session-basierte Anmeldung,
|
|
verschlüsselte (aber für Dogi jederzeit einsehbare) Zugangscodes, frei konfigurierbare Rollen mit
|
|
granularen Rechten, individuelle Ausnahmen pro Person, Aktivitätsprotokoll, Login-Lockout.
|
|
|
|
Kosten: läuft im kostenlosen Cloudflare-Tier (Workers Free, D1 Free, KV Free reichen locker).
|
|
|
|
## ✅ Bereits deployed
|
|
|
|
- **Interner Worker:** https://dogfather-universe-postfach.dogfather1608.workers.dev (Health-Check: `/health`)
|
|
- **D1-Datenbank:** `dogfather-universe-db`
|
|
- Website (`postfach.html`, `zugaenge.html`, `assets/js/*.js`) zeigt bereits auf diese URL.
|
|
|
|
Die Schritte unten sind nur nötig, falls der Worker mal neu aufgesetzt werden muss.
|
|
|
|
## Architektur
|
|
|
|
```
|
|
src/worker.js Router — verteilt Requests an die Handler unten
|
|
src/lib/crypto.js SHA-256-Hashing, AES-256-GCM-Verschlüsselung, ID/Token-Erzeugung
|
|
src/lib/auth.js Login-Prüfung, Sessions, Rate-Limiting/Lockout
|
|
src/lib/permissions.js Vollständiger Permission-Katalog aus dem Anforderungsdokument
|
|
src/lib/audit.js Aktivitätsprotokoll schreiben (nie mit Codes!)
|
|
src/lib/http.js CORS/JSON-Helfer
|
|
src/routes/auth.js Login/Logout
|
|
src/routes/users.js Zugänge und Teammitglieder (inkl. Code-Funktionen, NUR Owner)
|
|
src/routes/roles.js Rollen erstellen/umbenennen/löschen
|
|
src/routes/applications.js Bewerbungen: Status, Zuweisung, Notizen, Antwortentwürfe
|
|
src/routes/audit.js Aktivitätsprotokoll auslesen
|
|
migrations/0001_init.sql D1-Schema (users, roles, sessions, audit_log, applications, ...)
|
|
```
|
|
|
|
## Das Kernprinzip (aus dem Anforderungsdokument)
|
|
|
|
> Nur der Hauptadministrator sieht jederzeit alle vollständigen Zugangscodes und nur der
|
|
> Hauptadministrator darf sie erstellen, ändern, kopieren, zurücksetzen oder sperren.
|
|
|
|
Technisch umgesetzt:
|
|
|
|
- **Owner-Code** = das `POSTFACH_CODE`-Secret. Kein Datenbankeintrag, kann nicht gelöscht/verändert
|
|
werden außer von Dogi selbst per `wrangler secret put`.
|
|
- **Team-Codes** werden **zweifach** gespeichert:
|
|
- `code_hash` (SHA-256, nicht umkehrbar) — für den schnellen Login-Vergleich.
|
|
- `code_enc` (AES-256-GCM, umkehrbar) — nur damit kann der Owner sich den Klartext-Code später
|
|
wieder anzeigen lassen. Der Schlüssel dafür liegt ausschließlich im `ENCRYPTION_KEY`-Secret.
|
|
- **Code anzeigen** verlangt zusätzlich eine Re-Authentifizierung (Owner-Code erneut eingeben),
|
|
bevor der Klartext entschlüsselt und zurückgegeben wird.
|
|
- Folgende Aktionen sind **fest an `isOwner === true` gebunden** und erscheinen nirgends als
|
|
wählbare Berechtigung: Code anzeigen/kopieren/erstellen/ändern/zurücksetzen, den eigenen
|
|
Owner-Zugang bearbeiten, die Owner-Rolle löschen/einschränken, jemanden zum Owner machen.
|
|
|
|
## Voraussetzungen
|
|
|
|
- Ein (kostenloser) Cloudflare-Account
|
|
- Node.js installiert (für `npx wrangler`)
|
|
|
|
## Deploy von Grund auf (falls je nötig)
|
|
|
|
Alles im Ordner `cloudflare-worker/` ausführen:
|
|
|
|
```bash
|
|
cd cloudflare-worker
|
|
|
|
# 1. Bei Cloudflare einloggen
|
|
npx wrangler login
|
|
|
|
# 2. D1-Datenbank anlegen
|
|
npx wrangler d1 create dogfather-universe-db
|
|
# -> "database_id" aus der Ausgabe in wrangler.toml eintragen
|
|
|
|
# 3. Schema anlegen
|
|
npx wrangler d1 execute dogfather-universe-db --remote --file=migrations/0001_init.sql
|
|
|
|
# 4. KV-Namespace anlegen (nur noch für den Live-Status-Schalter genutzt)
|
|
npx wrangler kv namespace create BEWERBUNGEN
|
|
# -> "id" aus der Ausgabe in wrangler.toml eintragen
|
|
|
|
# 5. Owner-Code festlegen (dein persönlicher Hauptadministrator-Zugang)
|
|
npx wrangler secret put POSTFACH_CODE
|
|
|
|
# 6. Verschlüsselungs-Schlüssel für Team-Codes festlegen (32 zufällige Bytes, base64)
|
|
# z.B. erzeugen mit: node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
|
npx wrangler secret put ENCRYPTION_KEY
|
|
|
|
# 7. (Optional) Bewerbungen zusätzlich automatisch als Ticket bei
|
|
# Ticketanizer anlegen (dort in Discord sichtbar) — siehe Abschnitt
|
|
# "Bewerbungen als Ticketanizer-Tickets" unten. Ohne diesen Schritt
|
|
# läuft alles wie gehabt, es fehlt nur das automatische Ticket.
|
|
|
|
# 8. Deployen
|
|
npx wrangler deploy
|
|
```
|
|
|
|
## Bewerbungen als Ticketanizer-Tickets
|
|
|
|
Jede eingehende Bewerbung wird zusätzlich zur Speicherung in der eigenen
|
|
Datenbank als **echtes Ticket** bei Ticketanizer angelegt — im passenden
|
|
Bereich (Modi/Scout/Creator/Kooperation), exakt wie auf der Website getrennt.
|
|
Das läuft über die offizielle Ticketanizer-Inbound-Ticket-API
|
|
(`POST https://api.ticketanizer.com/v1/tickets`), kein Discord-Bot-Code nötig.
|
|
|
|
### Einrichtung (einmalig, ca. 2 Minuten)
|
|
|
|
1. Im Ticketanizer-Dashboard: **API & Webhooks → API-Keys → Key erstellen**
|
|
(Name z.B. "DOGFATHER UNIVERSE Homepage"). Den Key **sofort kopieren** —
|
|
wird meist nur einmal im Klartext angezeigt.
|
|
2. Als Secret im Worker hinterlegen:
|
|
|
|
```bash
|
|
npx wrangler secret put TICKETANIZER_API_KEY
|
|
```
|
|
|
|
3. Danach einmal `npx wrangler deploy`.
|
|
|
|
Die Zuordnung Bewerbungsbereich → Ticketanizer-Panel ist fest in
|
|
`src/lib/ticketanizer.js` (`PANEL_IDS`) hinterlegt, abgelesen aus dem
|
|
Ticketanizer-Dashboard unter **Panels**:
|
|
|
|
| Bewerbung auf der Website | Ticketanizer-Panel | panel_id |
|
|
|---|---|---|
|
|
| Modi | Modi-Bewerbung | 4 |
|
|
| Kooperation | Kooperationsbewerbung | 5 |
|
|
| Scout | Scout-Bewerbung | 6 |
|
|
| Creator | Manager-Bewerbung | 7 |
|
|
|
|
Ändert sich ein Panel (neu angelegt, andere ID), einfach die Zahlen in
|
|
`PANEL_IDS` in `src/lib/ticketanizer.js` anpassen und neu deployen.
|
|
|
|
### Wichtig
|
|
|
|
- **Ticketanizer ist rein informativ, kein Ausfallpunkt.** Fehlt der API-Key
|
|
oder ist Ticketanizer kurz nicht erreichbar, wird die Bewerbung trotzdem
|
|
ganz normal in der eigenen Datenbank gespeichert — nur das Zusatz-Ticket
|
|
entfällt dann.
|
|
- Der Key steht **nie** im Code oder in `wrangler.toml` (die ist eingecheckt),
|
|
sondern ausschließlich verschlüsselt bei Cloudflare — genau wie
|
|
`POSTFACH_CODE` und `ENCRYPTION_KEY`.
|
|
- Ändern/Ersetzen des Keys: `wrangler secret put TICKETANIZER_API_KEY` erneut
|
|
ausführen, überschreibt den alten Wert.
|
|
- Es wird bewusst nur Schritt 1 der Ticketanizer-API genutzt (Ticket
|
|
eröffnen). Das Nachladen von Staff-Antworten (Schritt 3, "pollen") ist
|
|
hier nicht eingebaut, da eine Bewerbung ein einmaliger Vorgang ist und
|
|
kein dauerhaft laufender Chat.
|
|
- **Wichtige Einschränkung (2026-08-01 festgestellt):** Über die Inbound-
|
|
Ticket-API angelegte Tickets landen bei Ticketanizer nur in der
|
|
**Web-Inbox** (eigene Weboberfläche, siehe Dashboard → "Inbox") und lösen
|
|
lediglich einen Rollen-Ping im Log-Kanal aus — es entsteht **kein**
|
|
echter, sichtbarer Ticket-Kanal in Discord (auch nicht nach manuellem
|
|
"Übernehmen" in der Inbox). Deshalb zusätzlich der Discord-Webhook-Weg
|
|
weiter unten, der die Bewerbung garantiert sichtbar direkt in den
|
|
passenden Kanal postet.
|
|
|
|
## Bewerbungen direkt in Discord-Kanälen (Webhooks)
|
|
|
|
Zusätzlich zu Ticketanizer wird jede Bewerbung als formatierte Nachricht
|
|
(Embed) direkt per normalem Discord-Webhook in den passenden Kanal gepostet —
|
|
das ist der Weg, der garantiert sichtbar in Discord ankommt (siehe
|
|
Einschränkung oben).
|
|
|
|
### Kanal-Zuordnung (von Dogi aus Discord kopiert, 2026-08-01)
|
|
|
|
| Bewerbung auf der Website | Discord-Kanal | Secret |
|
|
|---|---|---|
|
|
| Modi | `#modi-bewerbung` | `DISCORD_WEBHOOK_MODI` |
|
|
| Kooperation | `#kooperations-bewerbung` | `DISCORD_WEBHOOK_KOOPERATION` |
|
|
| Scout **und** Creator | `#scout-bewerbung` (gemeinsam) | `DISCORD_WEBHOOK_SCOUT_MANAGER` |
|
|
|
|
### Einrichtung (pro Kanal ca. 1 Minute)
|
|
|
|
1. Im jeweiligen Discord-Kanal: Kanal bearbeiten → **Integrationen** →
|
|
**Webhooks** → **Neuer Webhook** → **Webhook-URL kopieren**.
|
|
2. Als Secret hinterlegen:
|
|
|
|
```bash
|
|
npx wrangler secret put DISCORD_WEBHOOK_MODI
|
|
npx wrangler secret put DISCORD_WEBHOOK_KOOPERATION
|
|
npx wrangler secret put DISCORD_WEBHOOK_SCOUT_MANAGER
|
|
```
|
|
|
|
3. Danach einmal `npx wrangler deploy`.
|
|
|
|
Genau wie bei Ticketanizer: **rein informativ, kein Ausfallpunkt.** Fehlt
|
|
eine Webhook-URL oder ist Discord kurz nicht erreichbar, wird die Bewerbung
|
|
trotzdem ganz normal gespeichert. Die Zuordnung Typ → Webhook steht in
|
|
`src/lib/discord-webhooks.js` (`WEBHOOK_ENV_KEYS`).
|
|
|
|
## Wer den Owner-Code kennen darf
|
|
|
|
Nur du. Er ist dein Hauptadministrator-Zugang — sieht ausnahmslos alles, kann Zugänge/Rollen/Codes
|
|
verwalten. Ändern: `wrangler secret put POSTFACH_CODE` erneut ausführen.
|
|
|
|
## Zugänge und Teammitglieder verwalten
|
|
|
|
Auf `zugaenge.html` (verlinkt von `postfach.html`, wenn du als Owner eingeloggt bist):
|
|
|
|
- **Neue Zugänge erstellen** — Name, Benutzername, E-Mail, Rolle, Gültigkeit, Notiz. Code manuell
|
|
festlegen oder automatisch sicher generieren lassen. Wird **einmalig** im Klartext angezeigt —
|
|
danach nur noch über „Code anzeigen" (mit Re-Auth) abrufbar.
|
|
- **Rollen frei erstellen** — jedes einzelne Recht per Checkbox an-/abschaltbar (Bewerbungsbereiche,
|
|
Bearbeitung, Antworten, Notizen, Teamverwaltung, Einstellungen). Die Code-Funktionen tauchen dort
|
|
bewusst nirgends auf.
|
|
- **Individuelle Ausnahmen pro Person** — zusätzlich zur Rolle einzelne Rechte gezielt erlauben
|
|
oder entziehen.
|
|
- **Delegierbare Teilfunktion:** Personen mit dem Recht „Neue Benutzer vorbereiten" können einen
|
|
Entwurf anlegen (Name, Benutzername, Rolle) — der Zugang bleibt inaktiv, bis du ihn im Bereich
|
|
„Zugänge" mit „Freigeben & Code erstellen" final aktivierst.
|
|
- **Pro Person:** Code anzeigen/kopieren/neu erstellen (nur Owner), Sperren/Entsperren, alle
|
|
Sitzungen beenden (nur Owner), Rolle ändern, Rechte verwalten, vollständig löschen (nur Owner).
|
|
|
|
## Sicherheitsmaßnahmen
|
|
|
|
- Nach 5 falschen Codes pro Client 15 Minuten Sperre (`login_attempts`-Tabelle).
|
|
- Sessions: 30 Minuten Inaktivitäts-Timeout, 12 Stunden absolute Höchstdauer.
|
|
- Zugangscodes erscheinen **niemals** im Aktivitätsprotokoll, im Quelltext oder in Fehlermeldungen.
|
|
- CORS ist aktuell offen (`*`) — sobald die finale Domain feststeht, in `src/lib/http.js` →
|
|
`corsHeaders()` auf die echte Domain einschränken.
|
|
|
|
## Supporter-Abo (Dogfather) — Setup
|
|
|
|
Setzt `Dogfather_VanVan_Supporter_Abo.odt` um: eigener, öffentlicher
|
|
Supporter-Bereich mit PayPal-Abo (4,99 €/Monat), 30-Monats-Prämienzyklus
|
|
(Hasen-Teddys → Tasse & Autogrammkarte → Hoodie) und wechselnden
|
|
Kollektionen. **Wichtig: Das Abo selbst gehört nur Dogfather** — die
|
|
Teddy-Kollektion/Sammlerstücke entstehen in Kooperation mit VanVan, aber
|
|
das Abonnement ist NICHT gemeinsames Branding (klargestellt 03.08.2026).
|
|
Code ist **vollständig fertig implementiert**, kann aber
|
|
erst wirklich Geld verarbeiten bzw. E-Mails verschicken, sobald folgende
|
|
zwei externe Dienste eingerichtet sind — beides Dinge, die **nur der
|
|
Website-Betreiber selbst** einrichten kann (eigene Identität/Bankkonto):
|
|
|
|
```
|
|
src/lib/supporter-cycle.js Reine Rechenlogik: 30-Monats-Zyklus/Meilensteine
|
|
src/lib/supporter-auth.js Registrierung/Login (E-Mail-Code, eigene Sessions)
|
|
src/lib/supporter-mail.js Transaktions-E-Mails (Resend-Adapter)
|
|
src/lib/paypal.js PayPal Subscriptions API + Webhook-Signaturprüfung
|
|
src/routes/supporter.js Öffentlicher Supporter-Bereich (Profil/Prämien/Archiv)
|
|
src/routes/supporter-paypal.js Abo starten/kündigen + Webhook-Verarbeitung
|
|
src/routes/supporter-admin.js Interner Administrationsbereich (Abonnentenübersicht etc.)
|
|
migrations/0003_supporter_abo.sql D1-Schema (komplett getrennt vom Team-Zugangssystem)
|
|
```
|
|
|
|
### 1) D1-Migration ausführen (einmalig)
|
|
|
|
```bash
|
|
npx wrangler d1 execute dogfather-universe-db --remote --file=migrations/0003_supporter_abo.sql
|
|
```
|
|
|
|
### 2) PayPal-Business-Konto + Abo-Plan einrichten
|
|
|
|
1. PayPal-Business-Konto anlegen (falls noch nicht vorhanden): https://www.paypal.com/business
|
|
2. Developer-App anlegen: https://developer.paypal.com/dashboard/applications → **Create App**
|
|
(zuerst im **Sandbox**-Modus testen, siehe unten).
|
|
3. Ein Produkt anlegen (Katalog-Produkt, Typ "Service") mit dem Namen
|
|
**„Dogfather Supporter-Abo"**.
|
|
4. Einen Abo-Plan zu diesem Produkt anlegen: 4,99 € / Monat, EUR, monatliche
|
|
automatische Verlängerung, **keine** Testphase, **keine** Einrichtungsgebühr.
|
|
5. Einen Webhook anlegen, Ziel-URL:
|
|
`https://dogfather-universe-postfach.dogfather1608.workers.dev/supporter/paypal-webhook`
|
|
Mindestens folgende Ereignisse abonnieren: `BILLING.SUBSCRIPTION.ACTIVATED`,
|
|
`BILLING.SUBSCRIPTION.UPDATED`, `BILLING.SUBSCRIPTION.CANCELLED`,
|
|
`BILLING.SUBSCRIPTION.SUSPENDED`, `BILLING.SUBSCRIPTION.EXPIRED`,
|
|
`PAYMENT.SALE.COMPLETED`, `PAYMENT.SALE.DENIED`, `PAYMENT.SALE.REFUNDED`,
|
|
`PAYMENT.SALE.REVERSED`.
|
|
|
|
Aus diesen Schritten bekommst du 4 Werte, die als Secrets gesetzt werden
|
|
(NIE im Code, NIE im Repo):
|
|
|
|
```bash
|
|
npx wrangler secret put PAYPAL_CLIENT_ID
|
|
npx wrangler secret put PAYPAL_CLIENT_SECRET
|
|
npx wrangler secret put PAYPAL_PLAN_ID
|
|
npx wrangler secret put PAYPAL_WEBHOOK_ID
|
|
```
|
|
|
|
Und in `wrangler.toml` unter `[vars]` (unkritisch, kein Geheimnis):
|
|
|
|
```toml
|
|
PAYPAL_ENV = "sandbox" # später auf "live" umstellen, siehe Abschnitt 7 des Auftrags
|
|
```
|
|
|
|
**Erst vollständig in der Sandbox testen** (eigenes Sandbox-Business- und
|
|
Sandbox-Privatkonto unter https://developer.paypal.com/dashboard/accounts),
|
|
danach `PAYPAL_ENV` auf `"live"` umstellen und Schritte 2-5 mit den echten
|
|
Live-Zugangsdaten wiederholen. Solange die Secrets fehlen, antworten alle
|
|
PayPal-Endpunkte kontrolliert mit `PAYPAL_NOT_CONFIGURED` statt abzustürzen.
|
|
|
|
**Zahlarten-Abdeckung (03.08.2026 ergänzt):** Das Frontend nutzt jetzt die
|
|
offiziellen PayPal Smart Payment Buttons (`abonnieren.html`) statt einer
|
|
reinen Weiterleitung — dadurch zeigt PayPal automatisch ALLE für die
|
|
jeweilige Käuferin/den jeweiligen Käufer verfügbaren, in Deutschland
|
|
gängigen Zahlarten an (PayPal-Guthaben/-Bankkonto, Kreditkarte auch als
|
|
Gast ohne eigenes PayPal-Konto). Das ist bewusst PayPal selbst überlassen
|
|
(kein eigenes Karten-/SEPA-/Klarna-Backend nötig) — das Geld landet dabei
|
|
immer direkt auf **deinem eigenen** PayPal-Business-Konto (dieselben
|
|
`PAYPAL_CLIENT_ID`/`PAYPAL_PLAN_ID` wie oben). Es ist keine zusätzliche
|
|
Einstellung nötig — welche Zahlarten genau angezeigt werden, entscheidet
|
|
PayPal automatisch je nach Land/Konto deiner Supporter.
|
|
|
|
### 3) "Mit Google anmelden" einrichten (optional, aber empfohlen)
|
|
|
|
Zusätzlich zum E-Mail-Code-Login gibt es jetzt einen "Mit Google anmelden"-
|
|
Button (professionellerer, schnellerer Login — Google hat die E-Mail-Adresse
|
|
bereits selbst bestätigt, kein Extra-Code nötig). Komplett optional: ohne
|
|
`GOOGLE_CLIENT_ID` bleibt der Button einfach ausgeblendet, der normale
|
|
E-Mail-Code-Login funktioniert unverändert.
|
|
|
|
1. https://console.cloud.google.com/apis/credentials öffnen (kostenloses
|
|
Google-Konto reicht, keine Kreditkarte nötig).
|
|
2. Falls noch nicht vorhanden: **OAuth-Zustimmungsbildschirm** einmalig
|
|
einrichten (App-Name z.B. "Dogfather Supporter-Abo", externe Nutzer).
|
|
3. **Anmeldedaten erstellen → OAuth-Client-ID → Webanwendung.**
|
|
4. Unter **Autorisierte JavaScript-Quellen** deine echte Domain eintragen
|
|
(sobald vorhanden) sowie zum Testen
|
|
`https://dogfather-universe.dogfather1608.workers.dev`.
|
|
5. Die erzeugte Client-ID (endet auf `.apps.googleusercontent.com`) als
|
|
Secret setzen:
|
|
|
|
```bash
|
|
npx wrangler secret put GOOGLE_CLIENT_ID
|
|
```
|
|
|
|
Kein Client-Secret nötig — die Anmeldung läuft komplett über Googles
|
|
"Sign In With Google"-Button im Browser, der Worker prüft das dabei
|
|
ausgestellte Token nur gegen Googles öffentlichen `tokeninfo`-Endpunkt.
|
|
|
|
### 4) E-Mail-Versand einrichten (Resend, kostenloser Tier reicht)
|
|
|
|
Ohne E-Mail-Versand können sich Supporter nicht registrieren/einloggen
|
|
(E-Mail-Bestätigung/Login-Code). Benötigt außerdem eine **eigene, per
|
|
SPF/DKIM verifizierte Domain** (auf `*.workers.dev` allein funktioniert
|
|
zuverlässiger E-Mail-Versand nicht).
|
|
|
|
1. Account auf https://resend.com anlegen (kostenlos bis 3.000 E-Mails/Monat).
|
|
2. Eigene Domain hinzufügen und die angezeigten DNS-Einträge setzen.
|
|
3. API-Key erstellen.
|
|
|
|
```bash
|
|
npx wrangler secret put RESEND_API_KEY
|
|
```
|
|
|
|
Und in `wrangler.toml` unter `[vars]`:
|
|
|
|
```toml
|
|
RESEND_FROM = "Dogfather Team <[email protected]>"
|
|
```
|
|
|
|
### 5) Deployen
|
|
|
|
```bash
|
|
npx wrangler deploy
|
|
```
|
|
|
|
### 6) Berechtigung für den Administrationsbereich vergeben
|
|
|
|
Auf `zugaenge.html` einer Rolle (oder dir selbst als Owner, der hat ohnehin
|
|
alles) die neuen Rechte **„Supporter-Abonnenten ansehen"**, **„Supporter-
|
|
Prämien & Versand verwalten"** und **„Supporter-Kollektionen verwalten"**
|
|
zuweisen (Gruppe „Supporter-Abo" in der Rechteverwaltung).
|
|
|
|
### Verbindliche Prämienlogik (nicht verändern, Abschnitt 11-13 des Auftrags)
|
|
|
|
| Erfolgreich bezahlte Monate (im laufenden Zyklus) | Prämie |
|
|
|---|---|
|
|
| 6 | Kleiner Hasen-Teddy |
|
|
| 12 | Mittelgroßer Hasen-Teddy |
|
|
| 18 | Großer Hasen-Teddy |
|
|
| 24 | Tasse & Autogrammkarte |
|
|
| 30 | Exklusiver Hoodie — Zyklus abgeschlossen |
|
|
| 31+ | Neuer 30-Monats-Zyklus, neue Kollektion, Fortschritt bei 0 (Gesamt-Mitgliedschaftsdauer bleibt erhalten) |
|
|
|
|
Testzahlungen (Sandbox) zählen **nie** als echter Monat. Jedes
|
|
PayPal-Ereignis wird per `paypal_event_id` genau einmal verarbeitet
|
|
(keine doppelte Anrechnung bei erneuter Zustellung).
|
|
|
|
### Bewusst noch nicht gebaut (nächste Ausbaustufe, nicht Teil der Abnahmekriterien)
|
|
|
|
Abschnitt 20 des Auftrags ("Zusätzliche Vorteile") beschreibt optionale
|
|
Bonus-Features — Abstimmungen, Downloads, Supporter-Wand, Jubiläums-
|
|
Videobotschaften. Die Datenbankstruktur lässt Raum dafür, sie sind aber
|
|
bewusst **nicht** Teil dieser ersten Ausbaustufe, da sie in den
|
|
"Verbindlichen Abnahmekriterien" (Abschnitt 34) nicht gefordert sind.
|
|
|
|
## Wartung
|
|
|
|
- Bewerbungen/Zugänge/Rollen: alles über `zugaenge.html` bzw. `postfach.html` als Owner.
|
|
- Direktzugriff auf die Datenbank bei Bedarf:
|
|
`npx wrangler d1 execute dogfather-universe-db --remote --command="SELECT ..."`
|