From c78ab60c612124bf01d0afa2327b3fafe638aa14 Mon Sep 17 00:00:00 2001 From: c2s Date: Tue, 17 Feb 2026 15:50:52 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=8B=20TODO,=20Security,=20Analytics=20?= =?UTF-8?q?mit=20echtem=20Inhalt=20bef=C3=BCllt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- projekt/TODO.md | 120 ++++++++++++++++++++++++++++++++++- security/Analytics.md | 97 +++++++++++++++++++++++++++- security/SECURITY.md | 144 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 352 insertions(+), 9 deletions(-) diff --git a/projekt/TODO.md b/projekt/TODO.md index e70ed62..5b06e35 100644 --- a/projekt/TODO.md +++ b/projekt/TODO.md @@ -1,5 +1,119 @@ -# TODO +# To-Do-Liste - Payload CMS Multi-Tenant Projekt -> Siehe Projektdatei TODO.md für Details +> **Server:** sv-payload (LXC 700) - 10.10.181.100 +> **Frontend-Tasks:** Siehe `FRONTEND.md` (sv-frontend, LXC 704) -Platzhalter - wird mit Inhalt aus dem Claude Project befüllt. \ No newline at end of file +--- + +## Zusammenfassung: Offene Tasks (Payload-Server) + +### Hohe Priorität +| Status | Task | Bereich | +|--------|------|--------| +| [ ] | SMTP-Credentials in `.env` konfigurieren | E-Mail | + +### Mittlere Priorität +| Status | Task | Bereich | +|--------|------|--------| +| [ ] | Media-Backup zu S3/MinIO | Backup | +| [ ] | CDN-Integration (Cloudflare) | Caching | +| [x] | CI/CD Pipeline erweitern (Lint/Test/Build) | DevOps | +| [x] | Security Scanning (CodeQL, Dependency Audit) | DevOps | +| [x] | Staging-Deployment | DevOps | +| [x] | Memory-Problem lösen (Swap) | Infrastruktur | +| [ ] | PM2 Cluster Mode testen | Infrastruktur | +| [ ] | Payload/Next Releases auf Next.js 16 Support beobachten | Tech Debt | + +### Niedrige Priorität +| Status | Task | Bereich | +|--------|------|--------| +| [ ] | Monitoring: Sentry, Prometheus, Grafana | Monitoring | +| [x] | AuditLogs Retention (90 Tage Cron) | Data Retention | +| [x] | Email-Log Cleanup Cron | Data Retention | +| [x] | Media-Orphan-Cleanup | Data Retention | +| [x] | Consent-Logs Archivierung | Data Retention | +| [ ] | Dashboard-Widget für Email-Status | Admin UX | +| [ ] | TypeScript Strict Mode | Tech Debt | +| [x] | E2E Tests für kritische Flows | Testing | + +### Dokumentation +| Status | Task | +|--------|------| +| [x] | DEPLOYMENT.md erstellen | + +--- + +## Legende + +- [ ] Offen +- [x] Erledigt +- [~] In Bearbeitung +- [!] Blockiert + +--- + +## Offene Aufgaben (Detail) + +### Analytics Integration +- [ ] Umami-Server auf sv-analytics einrichten +- [ ] Website-IDs für alle 4 Tenants erstellen +- [ ] `src/config/analytics.ts` mit Website-IDs +- [ ] `UmamiScript.tsx` implementieren +- [ ] Umami Script in Root Layout einbinden (Multi-Tenant) +- [ ] `useAnalytics.ts` Hook für Custom Events +- [ ] `analytics.server.ts` für Server-Side Events +- [ ] Event-Tracking in Newsletter/CTA integrieren + +### Google Ads Conversion (mit Consent) +- [ ] `GoogleConsentMode.tsx` implementieren +- [ ] Google Consent Mode v2 mit Orestbida Cookie-Banner +- [ ] `useGclid.ts` Hook für GCLID-Erfassung +- [ ] `google-ads.ts` Client-Side Conversion Tracking +- [ ] `google-ads.server.ts` Server-Side Conversion API +- [ ] Enhanced Conversions mit gehashten E-Mails + +### Backup-System +- [ ] Media-Backup zu S3/MinIO +- [ ] Disaster Recovery Plan + +### Monitoring & Logging +- [ ] Sentry Error Tracking +- [ ] Prometheus Metrics +- [ ] Grafana Dashboard + +--- + +## Build & Infrastructure + +- [x] Memory-Problem gelöst (4GB Swap via ZFS ZVOL) +- [ ] PM2 Cluster Mode testen + +--- + +## Testing & CI/CD + +- [x] CI/CD Pipeline (`.github/workflows/ci.yml`) +- [x] Staging-Deployment (`.github/workflows/deploy-staging.yml`) +- [x] E2E Tests (`tests/e2e/`) + +--- + +## Data Retention + +- [x] Automatische Datenbereinigung (`src/lib/retention/`) +- [x] Cron-Job für Email-Log Cleanup (90 Tage) +- [x] AuditLogs Retention Policy (90 Tage) +- [x] Consent-Logs Archivierung (3 Jahre, expiresAt-basiert) +- [x] Media-Orphan-Cleanup + +--- + +## Hinweise + +1. **Tenant-Isolation bei localhost:** API gibt 403 zurück wenn kein Tenant zur Domain passt (gewollt) +2. **GraphQL Playground deaktiviert:** Route entfernt +3. **PM2 Cluster Mode:** Aktuell 1 Instanz, für Skalierung `instances: "max"` setzen + +--- + +*Letzte Aktualisierung: 29.12.2025* diff --git a/security/Analytics.md b/security/Analytics.md index fe19c0c..c9e640b 100644 --- a/security/Analytics.md +++ b/security/Analytics.md @@ -1,5 +1,96 @@ -# Analytics +# Analytics Integration -> Siehe Projektdatei Analytics.md für Details +*Letzte Aktualisierung: 18. Dezember 2025* -Platzhalter - wird mit Inhalt aus dem Claude Project befüllt. \ No newline at end of file +--- + +## Übersicht + +### 1. Umami Analytics (cookieless, ohne Consent) + +- Umami-Server auf sv-analytics (10.10.181.103) +- Website-IDs für alle 4 Tenants +- UmamiScript Komponente in Layout +- useAnalytics Hook für Custom Events +- Server-Side Events für Backend-Actions + +### 2. Google Ads Conversion (mit Consent) + +- GoogleConsentMode Komponente (integriert mit Orestbida) +- useGclid Hook für Attribution +- Client-Side Conversions bei Consent +- Server-Side Conversions immer (gehashte Daten) + +### 3. Cookie Inventory + +- Google Ads Cookies dokumentieren (_gcl_au, _gcl_aw, IDE) + +--- + +## Environment Variables + +### Frontend (.env.local) + +```env +NEXT_PUBLIC_PAYLOAD_URL=https://cms.c2sgmbh.de +NEXT_PUBLIC_API_URL=https://cms.c2sgmbh.de/api +NEXT_PUBLIC_UMAMI_HOST=https://analytics.c2sgmbh.de +NEXT_PUBLIC_TENANT_ID=4 +NEXT_PUBLIC_TENANT_SLUG=c2s +NEXT_PUBLIC_GOOGLE_ADS_ID=AW-XXXXXXXXX +``` + +### Backend (.env) + +```env +UMAMI_HOST=https://analytics.c2sgmbh.de +UMAMI_WEBSITE_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +GOOGLE_ADS_CUSTOMER_ID=1234567890 +GOOGLE_ADS_CONVERSION_ACTION_ID=987654321 +GOOGLE_ADS_API_TOKEN=ya29.xxx +GOOGLE_ADS_DEVELOPER_TOKEN=xxx +``` + +--- + +## Event-Naming-Konvention + +| Event | Name | Data | +|-------|------|------| +| Newsletter Anmeldung | `newsletter_subscribe` | `{ source: string }` | +| Newsletter Bestätigung | `newsletter_confirm` | - | +| Kontaktformular | `contact_form_submit` | `{ form_type: string }` | +| CTA Klick | `cta_click` | `{ cta_name: string, location: string }` | +| Download | `download` | `{ file_name: string, file_type: string }` | +| Funnel-Step | `funnel_step` | `{ funnel: string, step: number }` | +| Scroll-Tiefe | `scroll_depth` | `{ depth_percent: number }` | +| Externer Link | `external_link` | `{ url: string }` | + +--- + +## Dateien zu erstellen + +``` +src/ +├── components/analytics/ +│ ├── UmamiScript.tsx # Umami Tracking Script +│ └── GoogleConsentMode.tsx # Google Consent Mode v2 +├── config/analytics.ts # Website-IDs, Config +├── hooks/ +│ ├── useAnalytics.ts # Client-Side Events +│ └── useGclid.ts # GCLID Erfassung +└── lib/ + ├── analytics.server.ts # Umami Server-Side + ├── google-ads.ts # Google Ads Client + └── google-ads.server.ts # Google Ads Server API +``` + +--- + +## Google Ads Cookies (für Cookie-Inventory) + +| Name | Provider | Kategorie | Dauer | +|------|----------|-----------|-------| +| `_gcl_au` | Google Ads | marketing | 90 Tage | +| `_gcl_aw` | Google Ads | marketing | 90 Tage | +| `IDE` | Google (doubleclick.net) | marketing | 1 Jahr | diff --git a/security/SECURITY.md b/security/SECURITY.md index 8b1c089..6a086f7 100644 --- a/security/SECURITY.md +++ b/security/SECURITY.md @@ -1,5 +1,143 @@ -# Security-Dokumentation +# Security-Richtlinien - Payload CMS Multi-Tenant -> Siehe Projektdatei SECURITY.md für Details +> Letzte Aktualisierung: 29.12.2025 -Platzhalter - wird mit Inhalt aus dem Claude Project befüllt. \ No newline at end of file +## Übersicht + +| Umgebung | URL | TRUST_PROXY | +|----------|-----|-------------| +| Production | https://cms.c2sgmbh.de | `true` (Nginx) | +| Staging | https://pl.porwoll.tech | `true` (Caddy) | + +--- + +## Security-Module + +Alle Security-Funktionen in `src/lib/security/`: + +| Modul | Datei | Zweck | +|-------|-------|-------| +| Rate Limiter | `rate-limiter.ts` | Schutz vor API-Missbrauch | +| IP Allowlist | `ip-allowlist.ts` | IP-basierte Zugriffskontrolle | +| CSRF Protection | `csrf.ts` | Cross-Site Request Forgery Schutz | +| Data Masking | `data-masking.ts` | Sensitive Daten in Logs maskieren | + +### Rate Limiter + +| Name | Limit | Fenster | Verwendung | +|------|-------|---------|------------| +| `publicApiLimiter` | 60 Requests | 1 Minute | Öffentliche API | +| `authLimiter` | 5 Requests | 15 Minuten | Login-Versuche | +| `emailLimiter` | 10 Requests | 1 Minute | E-Mail-Versand | +| `searchLimiter` | 30 Requests | 1 Minute | Suche & Posts-API | +| `formLimiter` | 5 Requests | 10 Minuten | Formular-Submissions | + +Redis-Support: Automatischer Fallback auf In-Memory-Store. + +### IP Allowlist/Blocklist + +> **WICHTIG:** Hinter Reverse-Proxy (Caddy, Nginx) MUSS `TRUST_PROXY=true` gesetzt werden! + +| Variable | Zweck | Format | +|----------|-------|--------| +| `TRUST_PROXY` | Proxy-Header vertrauen | `true` oder leer | +| `BLOCKED_IPS` | Globale Blocklist | IP, CIDR, Wildcard | +| `SEND_EMAIL_ALLOWED_IPS` | E-Mail-Endpoint | IP, CIDR, Wildcard | +| `ADMIN_ALLOWED_IPS` | Admin-Panel | IP, CIDR, Wildcard | +| `WEBHOOK_ALLOWED_IPS` | Webhook-Endpoint | IP, CIDR, Wildcard | + +### CSRF Protection + +Pattern: Double Submit Cookie +Token-Endpoint: `GET /api/csrf-token` + +> **WICHTIG:** In Production MUSS `CSRF_SECRET` oder `PAYLOAD_SECRET` konfiguriert sein. + +### Data Masking + +Automatisch maskierte Felder: password, token, apiKey, secret, credentials, privateKey, smtpPassword + +--- + +## Pre-Commit Hook + +```bash +ln -sf ../../scripts/detect-secrets.sh .git/hooks/pre-commit +``` + +Erkannte Patterns: API Keys, AWS Credentials, Private Keys, Passwörter, SMTP, DB Connection Strings, JWT, Webhook URLs. + +--- + +## CI/CD Security + +| Job | Prüfung | +|-----|--------| +| `secrets` | Gitleaks Secret Scanning | +| `dependencies` | npm audit, Dependency Check | +| `codeql` | Static Code Analysis | +| `security-tests` | 177 Security Unit & Integration Tests | + +--- + +## Test Suite + +```bash +pnpm test:security # Alle Security-Tests +pnpm test:unit # Nur Unit-Tests +``` + +| Test-Datei | Tests | Bereich | +|------------|-------|---------| +| `rate-limiter.unit.spec.ts` | 24 | Limiter, Tracking, TRUST_PROXY | +| `csrf.unit.spec.ts` | 34 | Token, Validierung, Origin | +| `ip-allowlist.unit.spec.ts` | 35 | CIDR, Wildcards, TRUST_PROXY | +| `data-masking.unit.spec.ts` | 41 | Felder, Patterns, Rekursion | +| `security-api.int.spec.ts` | 33 | API-Integration | + +--- + +## Production Checklist + +- [ ] `TRUST_PROXY=true` setzen (Pflicht hinter Reverse-Proxy) +- [ ] `CSRF_SECRET` oder `PAYLOAD_SECRET` setzen +- [ ] `BLOCKED_IPS` für bekannte Angreifer +- [ ] `SEND_EMAIL_ALLOWED_IPS` auf vertrauenswürdige IPs +- [ ] `ADMIN_ALLOWED_IPS` auf Office/VPN-IPs +- [ ] Redis für verteiltes Rate Limiting +- [ ] Pre-Commit Hook aktivieren + +--- + +## Custom Login Route + +Audit-Logging, Rate-Limiting (5/15min), Browser-Redirect, Multi-Content-Type Support. + +Redirect-Validierung: Nur relative Pfade, externe URLs blockiert, Protocol-Handler abgelehnt. + +--- + +## Dateien + +| Pfad | Beschreibung | +|------|-------------| +| `src/lib/security/rate-limiter.ts` | Rate Limiting | +| `src/lib/security/ip-allowlist.ts` | IP-Zugriffskontrolle | +| `src/lib/security/csrf.ts` | CSRF Token | +| `src/lib/security/data-masking.ts` | Data Masking | +| `src/app/(payload)/api/users/login/route.ts` | Custom Login | +| `scripts/detect-secrets.sh` | Pre-Commit Detection | +| `.github/workflows/security.yml` | CI Security | +| `tests/unit/security/` | Unit Tests | +| `tests/int/security-api.int.spec.ts` | Integration Tests | + +--- + +## Änderungshistorie + +| Datum | Änderung | +|-------|----------| +| 29.12.2025 | Custom Login Page Abschnitt entfernt | +| 17.12.2025 | Security-Audit Fixes: TRUST_PROXY, CSRF_SECRET, Tests auf 177 erweitert | +| 08.12.2025 | Security Test Suite (143 Tests) | +| 07.12.2025 | Rate Limiter, CSRF, IP Allowlist, Data Masking |