Update tenant lifecycle tooling and retire docs/process
This commit is contained in:
@@ -18,4 +18,4 @@
|
||||
|
||||
## Operational Notes
|
||||
- Keep changes focused and reversible; document significant behavior shifts in the relevant `docs/*` or PRP files when surfaces change.
|
||||
- When tasks exceed scope, record follow-ups in `docs/process/todo/` rather than expanding the current patch set.
|
||||
- When tasks exceed scope, record follow-ups as bd issues rather than expanding the current patch set.
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
## Operational Notes
|
||||
- Never change production infrastructure or data without explicit human approval.
|
||||
- For releases: use semantic version tags, generate a changelog, and ensure legal pages and migration notes are current.
|
||||
- For issue hygiene: import `docs/process/todo/` items into issues and avoid duplicates.
|
||||
- For issue hygiene: track follow-ups in bd issues and avoid duplicates by checking existing titles.
|
||||
- When ending a session, follow the Landing the Plane checklist in `AGENTS.md`.
|
||||
|
||||
@@ -79,7 +79,7 @@ related:
|
||||
- **Standalone Web**: optional `/help` public site generated from the same Markdown using Vite/React and server-side rendering for SEO.
|
||||
|
||||
## Governance & Backlog
|
||||
- Track work in `docs/process/todo/help.md` (create if needed) and link issues to article slugs.
|
||||
- Track work in bd issues and link them to article slugs.
|
||||
- Add CI checks:
|
||||
- Ensure every `.en.md` file has a matching `.de.md` file with equal `slug`/`version_introduced`.
|
||||
- Validate required front matter keys.
|
||||
|
||||
@@ -27,7 +27,7 @@ related:
|
||||
|
||||
## Optionaler Follow-up
|
||||
- Event als Vorlage duplizieren für zukünftige Produktionen.
|
||||
- Erkenntnisse oder Verbesserungswünsche in `docs/process/todo/` festhalten.
|
||||
- Erkenntnisse oder Verbesserungswünsche als bd-Issue festhalten.
|
||||
|
||||
### Weitere Hilfe
|
||||
Wende dich an success@fotospiel.app oder konsultiere die Legal-Pages-Ressource für Compliance-Formulierungen.
|
||||
|
||||
@@ -28,7 +28,7 @@ Direkt nach dem Zugriff auf einen neuen Kunden oder wenn neue Mitarbeitende eing
|
||||
## Best Practices
|
||||
- Mindestens zwei Owner-Rollen für Redundanz halten.
|
||||
- Branding oder Automationen zuerst im Staging-Kundenkonto testen.
|
||||
- Einladungen im Änderungslog (`docs/process/changes/`) dokumentieren.
|
||||
- Einladungen als bd-Issue dokumentieren.
|
||||
|
||||
### Weitere Hilfe
|
||||
Siehe `event-prep-checklist` für Event-Vorbereitung oder kontaktiere cx-team@fotospiel.app für Onboarding-Support.
|
||||
|
||||
@@ -27,7 +27,7 @@ related:
|
||||
|
||||
## Optional follow-up
|
||||
- Duplicate the event as a template for future productions.
|
||||
- Update `docs/process/todo/` with learnings or improvements for the product team.
|
||||
- Capture learnings or improvements as bd issues for the product team.
|
||||
|
||||
### Need more help?
|
||||
Reach success@fotospiel.app or consult the Legal Pages resource for compliance wording.
|
||||
|
||||
@@ -28,7 +28,7 @@ Right after receiving access to a new customer account or when onboarding new st
|
||||
## Best practices
|
||||
- Keep at least two Owner-level accounts for redundancy.
|
||||
- Use the staging customer account to test branding or automation before touching production.
|
||||
- Document invitations in the change log (`docs/process/changes/`).
|
||||
- Document invitations in a bd issue note.
|
||||
|
||||
### Need more help?
|
||||
See `event-prep-checklist` for event-level prep or contact cx-team@fotospiel.app for onboarding assistance.
|
||||
|
||||
@@ -75,7 +75,7 @@ Dieses Dokument beschreibt, was gesichert werden sollte, wie Backups geprüft we
|
||||
- DB‑Backup einspielen.
|
||||
- Medien‑Backups anbinden.
|
||||
- Eine Handvoll Tenants/Events kompletter durchklicken (Upload, Galerie, Admin‑Funktionen).
|
||||
- Ergebnisse im `docs/process/changes/`‑Ordner dokumentieren (z.B. „DR‑Übung 2026‑Q1“ mit Learnings).
|
||||
- Ergebnisse als bd-Issue dokumentieren (z.B. „DR‑Übung 2026‑Q1“ mit Learnings).
|
||||
|
||||
## 5. Verantwortlichkeiten
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Dieses Runbook beschreibt, wie mit Zahlungsproblemen, Paddle/RevenueCat‑Webhoo
|
||||
- Modelle wie `Tenant`, `Packages`, `tenant_packages`, `event_packages`.
|
||||
- Services/Jobs zur Paket‑Zuweisung, Limit‑Berechnung und Nutzungstracking.
|
||||
|
||||
> Details zur Architektur findest du in den PRP‑Kapiteln (Billing/Freemium) sowie in den TODO‑Dokumenten unter `docs/process/todo/paddle-migration.md` und `docs/process/todo/paddle-catalog-sync.md`.
|
||||
> Details zur Architektur findest du in den PRP‑Kapiteln (Billing/Freemium) sowie in den bd-Issues zur Paddle‑Migration und zum Katalog‑Sync.
|
||||
|
||||
## 2. Typische Problemszenarien
|
||||
|
||||
@@ -55,7 +55,7 @@ Dieses Runbook beschreibt, wie mit Zahlungsproblemen, Paddle/RevenueCat‑Webhoo
|
||||
- Notfall: manuelle Paket‑Anpassung (nur mit klar dokumentierter Begründung):
|
||||
- Paket in `tenant_packages` aktivieren/verlängern und `package_purchases` sauber nachziehen.
|
||||
5. **Dokumentation**
|
||||
- Vorgang im Ticket / `docs/process/changes/*` festhalten, falls wiederkehrend.
|
||||
- Vorgang im Ticket oder als bd-Issue festhalten, falls wiederkehrend.
|
||||
|
||||
> TODO: Ergänze konkrete Tabellen-/Modellnamen und die relevanten Jobs/Artisan Commands, sobald Paddle/RevenueCat Migration finalisiert ist.
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ Dieses Runbook beschreibt praktische Abläufe für Datenschutz‑Anfragen, Daten
|
||||
|
||||
## 5. Verbindung zu Security-Hardening
|
||||
|
||||
Das Security‑Hardening‑Epic (`docs/process/todo/security-hardening-epic.md`) enthält mehrere Workstreams, die DSGVO‑relevant sind:
|
||||
Das Security‑Hardening‑Epic wird in bd-Issues gepflegt und enthält mehrere DSGVO‑relevante Workstreams:
|
||||
|
||||
- Signierte Asset‑URLs statt direkter Storage‑Links.
|
||||
- Verbesserte Token‑/Auth‑Flows.
|
||||
|
||||
@@ -68,7 +68,7 @@ Wenn keine Backups existieren, bleibt nur, die betroffenen Assets sauber als „
|
||||
- **Kapazitätsplanung**
|
||||
- Erkenntnisse über Medienwachstum nutzen, um frühzeitig auf größere Volumes/Buckets oder häufigere Archivierung umzusteigen.
|
||||
- **Dokumentation**
|
||||
- Incident und Maßnahmen in `docs/process/changes/*` dokumentieren.
|
||||
- Incident und Maßnahmen als bd-Issue dokumentieren.
|
||||
- Dieses Playbook aktualisieren, wenn neue Muster entdeckt wurden.
|
||||
|
||||
Dieses Playbook ist eng mit `docs/ops/media-storage-spec.md` und `docs/ops/monitoring-observability.md` verknüpft. Nutze diese Dokumente für Detailinformationen zu Queues, Thresholds und Storage‑Targets.
|
||||
|
||||
@@ -89,7 +89,7 @@ Wenn ein kompletter Tenant versehentlich gelöscht wurde (inkl. Benutzer/Events)
|
||||
- Ehrlich kommunizieren, was passiert ist, was wiederherstellbar ist und welches Risiko ein Restore birgt.
|
||||
- Zeitrahmen und mögliche Einschränkungen klar benennen.
|
||||
- **Intern**
|
||||
- Den gesamten Prozess in einem `docs/process/changes/*`‑Eintrag oder im Ticketing festhalten:
|
||||
- Den gesamten Prozess in einem bd-Issue oder im Ticketing festhalten:
|
||||
- Was, wann, warum schief ging.
|
||||
- Welche Restore‑Schritte durchgeführt wurden.
|
||||
- Welche Verbesserungen künftig notwendig sind (z.B. bessere Schutzmechanismen, zusätzliche Bestätigungen beim Löschen).
|
||||
|
||||
@@ -64,4 +64,4 @@ After enabling push:
|
||||
2. Trigger a host broadcast or upload-queue alert; confirm the browser shows a native notification and that the notification drawer refreshes without polling.
|
||||
3. Temporarily stop the upload workers to create ≥5 pending assets; re-run `storage:check-upload-queues` and verify guests receive the “Uploads werden noch verarbeitet …” message.
|
||||
|
||||
Document any deviations in `docs/process/changes/` for future regressions.
|
||||
Document any deviations in a bd issue note for future regressions.
|
||||
|
||||
@@ -82,7 +82,7 @@ Nur anwenden, wenn klare Freigabe vorliegt und Paddle die Zahlung eindeutig als
|
||||
3. Konsistenz prüfen:
|
||||
- Admin UI für Tenant öffnen und prüfen, ob Limits/Paketstatus jetzt korrekt angezeigt werden.
|
||||
4. Dokumentation:
|
||||
- Den Vorgang im Ticket oder in `docs/process/changes/*` (falls wiederkehrend) dokumentieren.
|
||||
- Den Vorgang im Ticket oder als bd-Issue (falls wiederkehrend) dokumentieren.
|
||||
|
||||
## 6. Kommunikation mit dem Tenant
|
||||
|
||||
@@ -92,4 +92,3 @@ Nur anwenden, wenn klare Freigabe vorliegt und Paddle die Zahlung eindeutig als
|
||||
- Ehrlich kommunizieren, dass laut Zahlungsprovider noch keine endgültige Zahlung vorliegt und welche Optionen es gibt (z.B. neue Zahlung, Klärung mit Bank/Kreditkarte).
|
||||
|
||||
Dieses How‑to sollte dem Support/On‑Call helfen, den gängigsten Billing‑Fehlerfall strukturiert abzuarbeiten. Für tiefere Ursachenanalysen siehe `docs/ops/billing-ops.md`.
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ Nach einem SEV‑1/2 Incident:
|
||||
1. **Fakten sammeln** (Timeline, betroffene Tenants/Events, konkrete Auswirkungen).
|
||||
2. **Ursache** (Root Cause) möglichst präzise identifizieren – auch dann, wenn direkt „nur“ Symptome gefixt wurden.
|
||||
3. **Kurzfristige Maßnahmen** (Hotfixes, Konfig‑Anpassungen, zusätzliche Checks).
|
||||
4. **Langfristige Maßnahmen** – sollten als Epics/Tasks in `docs/process/todo/*` bzw. `docs/process/changes/*` landen (inkl. Link zum Incident).
|
||||
4. **Langfristige Maßnahmen** – als bd-Issues festhalten (inkl. Link zum Incident).
|
||||
5. **Dokumentation aktualisieren**
|
||||
- Relevante Runbooks (dieses Dokument, Public‑API‑Runbook, Storage‑Spec, Billing‑Ops, etc.) mit neuen Learnings ergänzen.
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ Dieses Dokument beschreibt, **wer** im Betrieb wofür zuständig ist und **wie**
|
||||
|
||||
- Verantwortlich für:
|
||||
- Entscheidungen bei Feature‑Flags, Rollbacks, Hotfix‑Releases.
|
||||
- Priorisierung langfristiger Maßnahmen nach Incidents (`docs/process/roadmap.md`, `docs/process/todo/*`).
|
||||
- Priorisierung langfristiger Maßnahmen nach Incidents (bd-Issues als Roadmap/Backlog).
|
||||
- Typische Aufgaben:
|
||||
- Teilnahme an Postmortems.
|
||||
- Freigabe von riskanteren Änderungen (z.B. große Migrations).
|
||||
|
||||
@@ -87,16 +87,12 @@ Zusätzlich gibt es kurze „How‑to“-Runbooks für häufige Supportfälle:
|
||||
|
||||
Der Betreiber muss wissen, welche größeren Änderungen anstehen oder kürzlich live gegangen sind.
|
||||
|
||||
- **Prozess-Hub**
|
||||
- `docs/process/README.md` – erklärt Struktur von `changes/`, `todo/` und `roadmap.md`.
|
||||
- **Roadmap & Epics**
|
||||
- `docs/process/roadmap.md` – Überblick über aktive Epics (z.B. Security Hardening, Paddle‑Migration, Streaming‑Uploads) und kürzlich abgeschlossene Themen.
|
||||
- `docs/process/todo/security-hardening-epic.md` – Security‑Hardening‑Plan mit Bezug zu Ops (Signierte URLs, AV/EXIF, Monitoring‑Workstreams).
|
||||
- Paddle‑Themen: `docs/process/todo/paddle-migration.md`, `docs/process/todo/paddle-catalog-sync.md`.
|
||||
- Aktive Epics und offene Arbeitspakete werden in bd gepflegt (`bd list --status=open`, `bd ready`).
|
||||
- **Changes & Retro-Notizen**
|
||||
- `docs/process/changes/*` – Session‑Notizen, Refactor‑Pläne und Lessons Learned (z.B. Checkout‑Refactor, Registrierung‑Fixes).
|
||||
- Lessons Learned, Follow-ups und Incident-Maßnahmen werden als bd-Issues oder Issue-Notizen festgehalten.
|
||||
|
||||
Als Betreiber lohnt es sich, bei größeren Deployments kurz in `roadmap.md` und den passenden `changes/*` zu schauen, um Seiteneffekte zu antizipieren.
|
||||
Als Betreiber lohnt es sich, vor größeren Deployments die offenen bd-Issues zu prüfen, um Seiteneffekte zu antizipieren.
|
||||
|
||||
## 7. Tests, Qualität & Releases
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# Process & Planning Hub
|
||||
|
||||
This directory centralizes living planning artefacts that previously sat in scattered folders.
|
||||
|
||||
## Structure
|
||||
|
||||
- `changes/` — dated session logs, retro notes, and ad-hoc findings. Drop a new Markdown file per session (`YYYY-MM-DD-topic.md`) and reference it from epics when relevant.
|
||||
- `todo/` — backlog of active epics or initiatives. Each file focuses on a single problem space (e.g. `security-hardening-epic.md`) and contains goals, status, and actionable checklists.
|
||||
- `roadmap.md` — top-level view that summarizes what is in progress, what is queued up next, and which epics have been completed recently.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. After every planning or incident-review session, capture the outcome in `changes/`.
|
||||
2. Update the relevant `todo/*.md` files with new tasks, decisions, or links back to change logs.
|
||||
3. Keep `roadmap.md` in sync with the current quarter’s priorities so product/ops can scan it quickly.
|
||||
4. When an initiative is completed and no longer useful operationally, move its Markdown file to `docs/archive/` to keep the active backlog lightweight.
|
||||
|
||||
> Tip: Link to concrete specs (PRP chapters, ops runbooks) from each epic so contributors know where implementation details live.
|
||||
@@ -1,16 +0,0 @@
|
||||
# Session Changes — 2025-09-08
|
||||
|
||||
Summary
|
||||
- Split PRP into docs/prp/* and added addendum + ADR for Tenant Admin PWA.
|
||||
- Guest PWA: routes/components scaffold, bottom nav, header + settings sheet, theme toggle; polling hooks; upload (client compress <1.5 MB), offline queue + BG sync; gallery filters + lightbox; likes API/UI; SW runtime cache.
|
||||
- Super Admin (Filament 4): resources for Tenants, Events, Photos, Legal Pages; dashboard widgets; photo moderation; event toggle; join link + self‑hosted QR.
|
||||
- CSV imports + templates for Emotions and Tasks with de/en localization; forms updated to JSON casts.
|
||||
- Backend public API: stats/photos with ETag/304; upload endpoint; photo like.
|
||||
- Tenant Admin PWA: auth shell (token), events list/create/edit, event detail (stats, QR, invite), photo moderation.
|
||||
- Migrations: tenants table; users.tenant_id/role; events.tenant_id; model casts/relations added.
|
||||
- Artisan: media:backfill-thumbnails; tenant:add-dummy; tenant:attach-demo-event.
|
||||
|
||||
Notes
|
||||
- Security hardening intentionally minimal per instruction (token login for tenant admin).
|
||||
- QR codes generated server-side via simple-qrcode.
|
||||
- No secrets committed. Local gogs.ini used only for pushing to Gogs.
|
||||
@@ -1,40 +0,0 @@
|
||||
# Registrierungs-Fixes: Redirect, Error-Clearing und Role-Handling (2025-10-02)
|
||||
|
||||
## Problem-Beschreibung
|
||||
- **Redirect-Fehler**: Bei erfolgreicher Registrierung (free oder paid Package) wurde onSuccess in Register.tsx ausgelöst, aber kein Redirect zu /dashboard oder /buy-packages/\{id\} erfolgte. Ursache: Backend Inertia::location (302) wurde von Inertia mit preserveState: true ignoriert, da SPA-State erhalten blieb.
|
||||
- **Persistente Errors**: Server-Errors (z.B. invalid email) verschwanden nicht bei Korrektur-Input; nur Passwort-Match hatte client-side Clear.
|
||||
- **Role-Assignment**: Default 'user' für new Users; Upgrade zu 'tenant_admin' bei free Package (sofort im Controller), paid (nach Webhook-Payment).
|
||||
- **Weitere Bugs**: Tenant::create 'name' falsch ($request->name statt first+last_name); Linter/TS Errors (Return-Types, router.visit unknown).
|
||||
|
||||
## Fixes
|
||||
### Backend (MarketingRegisterController.php)
|
||||
- **JSON-Response für Redirect**: Ersetzt Inertia::location durch response()->json(['success' => true, 'redirect' => $url]) für free (Zeile 141) und paid (Zeile 133). Kompatibel mit Inertia onSuccess (page.props.success/redirect prüfen).
|
||||
- **Tenant Name Fix**: 'name' => $request->first_name . ' ' . $request->last_name (Zeile 71); slug entsprechend angepasst.
|
||||
- **Role-Logic**: 'role' => 'user' in User::create (Zeile 66); für free: Update zu 'tenant_admin' nach TenantPackage::create (Zeile 129), Re-Login (Zeile 130). Für paid: Kein Upgrade bis Webhook (Paddle).
|
||||
- **Return-Type**: store() zu JsonResponse (Zeile 44); use JsonResponse hinzugefügt (Zeile 22).
|
||||
|
||||
### Frontend (Register.tsx)
|
||||
- **onSuccess-Handling**: Prüfe page.props.success && router.visit(page.props.redirect as string) (Zeile 66-68); Fallback zu data.package_id ? `` `/buy-packages/\${data.package_id}` `` : '/dashboard' (Zeile 71-75); console.log für Debug (Zeile 67, 74).
|
||||
- **Error-Clearing**: Erweitert onChange für alle Inputs (first_name Zeile 123, last_name 148, email 173, address 198, phone 223, username 248): if (e.target.value.trim() && errors[field]) setError(field, ''); für privacy_consent (Zeile 325): if (checked) setError('privacy_consent', ''); Passwort behält Match-Check (Zeile 277, 305).
|
||||
- **General Errors Key**: nutze `<div key={"general-errors-" + Object.keys(errors).join('-')}>` (Zeile 347) für Re-Render bei Error-Änderungen.
|
||||
|
||||
### Tests (RegistrationTest.php)
|
||||
- **JSON-Asserts**: assertJsonStructure(['success', 'redirect']) und assertJson(['success' => true]) in test_registration_creates_user_and_tenant (Zeile 37-39) und test_registration_without_package (Zeile 78-80).
|
||||
- **Neuer Test**: test_registration_with_paid_package_returns_json_redirect (Zeile 132): assertStringContainsString('buy-packages', redirect); role 'user' (kein Upgrade).
|
||||
- **Validation/Email**: Unverändert, assertSessionHasErrors (Zeile 107).
|
||||
|
||||
## Verification
|
||||
- **Backend**: php artisan test --filter RegistrationTest; prüfe JSON-Response in Browser-Network-Tab (POST /register -> 200 JSON).
|
||||
- **Frontend**: Registrierung mit free: Redirect zu /verification.notice; paid: zu /buy-packages/10; Errors clear bei Input (z.B. invalid email -> input valid -> error gone).
|
||||
- **Role**: DB-Check: free -> 'tenant_admin', paid -> 'user' (Upgrade via Webhook).
|
||||
- **Linter/TS**: Keine Errors; Intelephense fixed durch JsonResponse use und as string cast.
|
||||
|
||||
## PRP-Update (docs/prp/13-backend-authentication.md)
|
||||
- Hinzugefügt: Section "Role Flow in Registration": Default 'user'; Upgrade 'tenant_admin' bei free Package (Controller); paid via Webhook (Stripe invoice.paid, Paddle IPN); JSON-Success für Inertia-Forms (preserveState + onSuccess visit).
|
||||
|
||||
## Best Practices
|
||||
- Inertia-Forms: Bei preserveState JSON-Response für custom Redirects verwenden, statt location() (vermeidet State-Ignorieren).
|
||||
- Error-Clearing: Client-side onChange clear für UX (non-empty Input); Keys für conditional Elements (Re-Render).
|
||||
- GDPR: Privacy-Consent required; no PII in Logs.
|
||||
|
||||
Date: 2025-10-02
|
||||
@@ -1,39 +0,0 @@
|
||||
# Checkout Refactor TODOs (2025-10-05)
|
||||
|
||||
## Scope
|
||||
- Marketing checkout only; guest and admin PWAs stay untouched.
|
||||
- Replace existing marketing purchase wizard and supporting auth/payment endpoints.
|
||||
|
||||
## Action Items
|
||||
|
||||
### Wizard Foundations
|
||||
- [x] Rebuild the package step with a side panel for comparable packages and reset payment state when the selected package changes (see `resources/js/pages/marketing/checkout/steps/PackageStep.tsx`).
|
||||
- [x] Redesign the payment step: Stripe and Paddle happy path, failure, retry; add subscription handling for reseller plans. *(Stripe intent lifecycle + Paddle subscription flow now share status alerts, retry logic, and plan gating in `PaymentStep.tsx`.)*
|
||||
- [x] Update the confirmation step and surface the admin link inside `resources/js/pages/Profile/Index.tsx`. *(Handled via `ConfirmationStep.tsx` + wizard callbacks redirecting to `/settings/profile` and `/event-admin`.)*
|
||||
|
||||
### Authentication & Profile Data
|
||||
- [x] Refactor `resources/js/pages/auth/LoginForm.tsx` and `RegisterForm.tsx` to hit the correct routes, surface inline validation errors, and provide success callbacks.
|
||||
- [x] Add optional comfort login: Google sign-in and enrichment of missing registration fields via the payment provider, combining the prior step 2/3 concept.
|
||||
|
||||
### Backend Alignment
|
||||
- [x] Implement a dedicated `CheckoutController` plus marketing API routes, migrating any remaining checkout logic out of the marketing controller. *(Controller + routes now live in `app/Http/Controllers/CheckoutController.php` / `routes/web.php`.)*
|
||||
- [x] Audit existing marketing payment flows (`resources/js/pages/marketing/PurchaseWizard.tsx`, `PaymentForm.tsx`) and plan removals or migration. *(Legacy components removed; new wizard replaces them.)*
|
||||
|
||||
### Quality & Rollout
|
||||
- [x] Expand automated coverage: Playwright end-to-end scenarios for auth, payment success/failure, Google login; PHPUnit and webhook tests for new checkout endpoints. *(Feature + unit suites cover Stripe intents, Paddle webhooks, Google comfort login; Playwright CTA smoke in place—full payment journey available behind the `checkout` tag.)*
|
||||
- [x] Update docs (PRP, docs/process/changes) and plan a feature-flag rollout for the new wizard.
|
||||
|
||||
## Notes
|
||||
- Wizard auth now uses `/checkout/login` and `/checkout/register` JSON endpoints handled by `CheckoutController`.
|
||||
- Ensure payment step parity during migration so existing paid funnels do not regress prior to feature flag activation.
|
||||
- 2025-10-05: Checkout wizard skeleton created (`resources/js/pages/marketing/checkout/*`); awaiting payment/Auth wiring and backend API handoff.
|
||||
- 2025-10-05: Payment architecture blueprint authored in docs/prp/marketing-checkout-payment-architecture.md.
|
||||
- 2025-10-05: checkout_sessions migration + service scaffolding committed (app/Models/CheckoutSession.php, app/Services/Checkout/*, config/checkout.php).
|
||||
|
||||
### Payment Integration Plan
|
||||
- [x] Define provider-agnostic payment state machine (intent creation, approval, capture, failure). See docs/prp/marketing-checkout-payment-architecture.md.
|
||||
- [x] Scaffold checkout_sessions migration + service layer per docs/prp/marketing-checkout-payment-architecture.md.
|
||||
- [x] Implement Stripe PaymentIntent endpoint returning `client_secret` scoped to wizard session. *(Covered by `CheckoutController::createPaymentIntent`.)*
|
||||
- [x] Implement Paddle order creation/capture endpoints with metadata for tenant/package. *(Routes now exposed in `routes/web.php`; controller derives tenant context for authenticated users.)*
|
||||
- [x] Add webhook handling matrix for Stripe invoice/payment events and Paddle subscription lifecycle.
|
||||
- [x] Wire payment step UI to new endpoints with optimistic and retry handling. *(See `PaymentStep.tsx` for Stripe intent loading + Paddle order/subscription creation and capture callbacks.)*
|
||||
@@ -1,22 +0,0 @@
|
||||
# Paddle SDK Migration to v1 Server SDK
|
||||
|
||||
## Summary
|
||||
Migrated from deprecated `paypal/paypal-checkout-sdk` to `paypal/paypal-server-sdk ^1.0+` in PaddleController.php. The new SDK uses a Builder pattern for requests and dedicated Controllers for API calls, based on OAuth2 Client Credentials.
|
||||
|
||||
## Changes
|
||||
- **Composer**: Removed `paypal/paypal-checkout-sdk`; retained/updated `paypal/paypal-server-sdk`.
|
||||
- **Imports**: Replaced old classes (PaddleHttpClient, OrdersCreateRequest, etc.) with new (PaypalServerSdkClientBuilder, OrderRequestBuilder, OrdersController, etc.).
|
||||
- **Constructor**: Updated to use `PaypalServerSdkClientBuilder` with `ClientCredentialsAuthCredentialsBuilder` and Environment (Sandbox/Production based on config/services.php).
|
||||
- **createOrder**: Now uses `OrdersController->createOrder` with `OrderRequestBuilder` for intent, purchase units (AmountWithBreakdownBuilder), custom_id, and application_context.
|
||||
- **captureOrder**: Now uses `OrdersController->captureOrder`; extracts custom_id from response->result->purchaseUnits for DB creation (PackagePurchase/TenantPackage).
|
||||
- **createSubscription**: Now uses `SubscriptionsController->createSubscription` with `SubscriptionRequestBuilder` for plan_id, subscriber (NameBuilder), custom_id, and application_context.
|
||||
- **Tests**: Updated tests/Feature/PurchaseTest.php to mock new SDK classes (e.g., OrdersController, SubscriptionsController) and responses; preserved test logic for flows, errors, idempotency.
|
||||
- **Documentation**: Updated docs/prp/08-billing.md to reflect new SDK usage, flow, and migration notes.
|
||||
|
||||
## Testing
|
||||
- Unit/Feature Tests: All Paddle-related tests pass with mocks simulating new API responses (statusCode 201, result structure).
|
||||
- Integration: Verified with Sandbox keys; simulated orders/subscriptions create DB entries correctly; error handling intact.
|
||||
- No Breaking Changes: Existing webhook logic and completePurchase calls unaffected; custom_id metadata preserved.
|
||||
|
||||
## Rationale
|
||||
The old SDK is deprecated and not recommended by Paddle. The new v1 Server SDK aligns with modern standards, improves security (OAuth2), and supports future features. Migration maintains backward compatibility for frontend and DB logic.
|
||||
@@ -1,86 +0,0 @@
|
||||
# Tenant Admin PWA — Onboarding + Management Fusion
|
||||
|
||||
## Context
|
||||
- Goal: Merge the immersive onboarding / ordering flow from the legacy Capacitor app with the new `/event-admin` management experience inside Laravel.
|
||||
- Desired outcome: Tenants land in a polished, mobile-first “welcome†journey when they first log in, complete package purchase + event setup, then switch to the operational dashboard once active.
|
||||
|
||||
## TODOs
|
||||
1. **Audit Legacy Assets**
|
||||
- Inventory screens/components from `fotospiel-tenant-app/tenant-admin-app` worth porting (intro carousel, package picker, CTA cards, animations, themed styles).
|
||||
- Document any dependencies (Framework7, custom icons, animation libs) and decide whether to port or recreate with our current Tailwind/React stack.
|
||||
|
||||
2. **Bootstrap Welcome Route Namespace**
|
||||
- Create `/event-admin/welcome/*` routes inside the Laravel tenant PWA.
|
||||
- Establish shared layout primitives (full-height hero, gradient backgrounds, swipeable steps) to match native feel.
|
||||
|
||||
3. **Port UI Steps**
|
||||
- Recreate the storytelling sequence (Brand intro → How it works → Package selection → Order CTA → First-event setup).
|
||||
- Hook actions into existing APIs (packages, checkout, event creation) and leverage current auth context.
|
||||
|
||||
4. **Lifecycle Routing Logic**
|
||||
- Add guard that directs tenants with no events / onboarding incomplete to the welcome flow after login.
|
||||
- Provide quick access from dashboard back into the guided flow when creating additional events.
|
||||
|
||||
5. **Capacitor/TWA Packaging Prep**
|
||||
- Ensure the merged `/event-admin` build is PWA-complete (manifest, offline) for future store submission.
|
||||
- Plan thin Capacitor wrapper reuse; retire the legacy repo after migration.
|
||||
|
||||
6. **Documentation & Hand-off**
|
||||
- Update PRP (tenant admin specs + onboarding) to reflect the unified experience.
|
||||
- Record component inventory and routing rules so future agents can extend both modes consistently.
|
||||
|
||||
## Component Audit — 2025-10-10
|
||||
|
||||
### Legacy Welcome & Story Shell
|
||||
- **Hero experience**: `App.tsx` renders a premium hero card with eyebrow, script headline, and dual CTA buttons (`/create-event`, `/tutorial`) layered on a soft gradient background with Framework7 cards and brand fonts.
|
||||
- **Feature highlights**: A three-card grid introduces guest gallery, timeline/tasks, and invites; badges flag free or included items for unauthenticated vs. subscribed tenants.
|
||||
- **Quick actions**: Responsive button stack that shifts based on auth state (`demo event`, `tutorial`, `events`, `login`) providing an immediate action list after the hero.
|
||||
- **Credits strip**: (Legacy) removed in favor of package/add-on status cards.
|
||||
|
||||
### Monetisation & Ordering
|
||||
- **IAP store** (`pages/IAPStorePage.tsx`): Uses `@revenuecat/purchases-capacitor` for offerings, purchase status banners, and analytics tracking; cards highlight price, credit count, and subscription state. Needs Paddle parity discussion before porting.
|
||||
- **Credits context** (`contexts/AuthContext.tsx`): Persists tokens and credit balances via Capacitor Preferences and refresh logic; emits helper APIs `purchasePackage`, `getCreditsBalance`.
|
||||
|
||||
### Event Creation Wizard
|
||||
- **Multi-step flow** (`pages/CreateEventWizard.tsx`): Three validated steps (Basics, Event type & mood, Confirmation) with segmented chips, animated progress bar, and analytics events (`trackEvent`). Integrates `EventService` for API calls and includes next/back navigation with swipe gestures.
|
||||
- **Mood board**: Step includes card gallery, tags, and dynamic feature chips to capture desired vibes—helpful reference for onboarding's storytelling portion.
|
||||
|
||||
### Theme & Visual System
|
||||
- **Design tokens** (`styles/tokens.css`): Brand palette, typography stack (Playfair Display, Montserrat, Lora, Great Vibes), spacing, radius, and shadow definitions exported as CSS variables.
|
||||
- **Framework7 overrides** (`styles/theme.css`, `styles/fonts.css`): Maps tokens onto Framework7 CSS variables to achieve native-feel bars, cards, and typography.
|
||||
- **Assets** (`src/assets/fonts/*`): Self-hosted font files referenced by tokens; need a Tailwind-friendly strategy (e.g., CSS `@font-face` via Vite) if we replicate the look.
|
||||
|
||||
### Supporting Utilities
|
||||
- **Services**: `services/AuthService.ts`, `services/EventService.ts`, `services/analytics.ts` provide OAuth PKCE glue, event CRUD helpers, and event tracking (mixpanel-like contract).
|
||||
- **i18n** (`src/i18n`): React context-based i18next with `en`/`de` copies for all hero/wizard strings; reuse dictionary keys where possible during port to keep translations aligned.
|
||||
|
||||
**Porting Recommendation**
|
||||
- Rebuild the hero, feature cards, quick actions, and wizard using Tailwind + shadcn components inside Laravel PWA while reusing copy/structure.
|
||||
- Lift design tokens into a Tailwind preset or CSS module so new welcome surfaces keep the premium typography without forcing Framework7 runtime.
|
||||
- Treat RevenueCat-specific logic as optional: plan abstraction so Paddle packages in Laravel can slot in later if we skip native IAPs initially.
|
||||
|
||||
## Proposed Laravel PWA Welcome Primitives
|
||||
- **`TenantWelcomeLayout`**: Full-height, gradient-backed shell with centered content column, safe-area padding, and optional bottom action rail. Applies the legacy token palette via Tailwind CSS variables and toggles between light/dark.
|
||||
- **`WelcomeHero`**: Composable hero card exposing slots for eyebrow, headline, script subtitle, and dual CTA buttons. Ships with animation hooks (e.g., `framer-motion`/CSS fade) but degrades gracefully.
|
||||
- **`WelcomeStepCard`**: Step wrapper with built-in progress indicator, icon slot, and scroll snap. Intended for storytelling slides (`How it works`, `Why Fotospiel`) before handing off to form-based steps.
|
||||
- **`OnboardingCTAList`**: Responsive button group mirroring legacy quick actions; renders stacked buttons on mobile and inline actions on larger breakpoints. Consumes tenant/auth context to toggle copy.
|
||||
- **`OnboardingHighlightsGrid`**: Reusable grid for feature cards (icon, title, badge, copy) using existing shadcn `Card` primitives to reproduce the premium look without Framework7.
|
||||
- **`OnboardingProgressProvider`**: Lightweight Zustand or React context store that tracks completion state (welcome_seen, package_selected, event_created) for guards and resume logic.
|
||||
- **Theming bridge**: Introduce `tenant-admin.css` (or Tailwind preset) that re-exports critical tokens (`--tenant-primary`, serif display font) so the welcome experience and management dashboard share a palette while staying Tailwind-native.
|
||||
|
||||
These primitives live under `resources/js/admin/onboarding/` and integrate with current router constants (`ADMIN_BASE_PATH`). They should support lazy-loading so existing dashboard bundle size remains manageable.
|
||||
|
||||
## Progress
|
||||
- **Inline Checkout**: Die Order-Summary-Seite unterstützt jetzt Stripe-Kartenzahlungen (Payment Element) und Paddle (Orders API) direkt aus dem Onboarding heraus. Free-Packages lassen sich ohne Umweg aktivieren.
|
||||
- Dashboard bewirbt die Welcome Journey (Actions + Hero Card) und leitet Tenants ohne Events weiterhin auf `/event-admin/welcome` um, während Fortschritt persistiert wird.
|
||||
- Playwright-Skelett `tests/e2e/tenant-onboarding-flow.test.ts` angelegt und via `npm run test:e2e` ausführbar; Tests sind vorerst deaktiviert, bis Seed-Daten + Auth-Helper zur Verfügung stehen.
|
||||
- Welcome Landing, Packages, Summary und Event-Setup sind zweisprachig (DE/EN) via react-i18next; LanguageSwitcher im Dashboard & Welcome-Layout steuert die Locale.
|
||||
|
||||
## Status — verbleibende Arbeiten
|
||||
- Paddle-Testabdeckung (Playwright/RTL) und Error-UX gehören noch in die Roadmap, ebenso wie End-to-End-Validierung auf Staging.
|
||||
|
||||
## Notes
|
||||
- Keep current management modules untouched until welcome flow is ready; ship incrementally behind feature flag if needed.
|
||||
- Reuse new API helpers, QueryClient, and constants to avoid divergence between flows.
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# Coupon Ops Enhancements (2025-11-08)
|
||||
|
||||
## Summary
|
||||
- Added `CouponRedemptionService` + Paddle webhook hooks so successful/failed redemptions are logged and counted.
|
||||
- Exposed `/api/v1/marketing/coupons/preview` with per-IP rate limiting, structured logging, and localized responses.
|
||||
- Marketing funnel + checkout wizard auto-prefill coupons from `?coupon=` links and persist selections through Paddle checkout.
|
||||
- Super Admin dashboard now shows a "Coupon performance (30d)" widget with recent usage + discount totals.
|
||||
- New artisan command `php artisan coupons:export` exports the last N days of redemptions to CSV for finance/reporting.
|
||||
|
||||
## Follow-ups
|
||||
- Wire coupon analytics into the Matomo dashboard once new segments are defined.
|
||||
- Expand fraud tooling with IP/device reputation once we roll out the affiliate program.
|
||||
@@ -1,50 +0,0 @@
|
||||
# Security Review Kickoff — 2025-12-08
|
||||
|
||||
## Context
|
||||
- Started structured security review spanning marketing/public API, Guest PWA, Event Admin, payments/webhooks, and media pipeline/storage.
|
||||
- Needed a tracking checklist plus logging conventions for findings and follow-ups.
|
||||
|
||||
## Actions
|
||||
- Added review plan with scope, workstreams, and checklists: `docs/process/todo/security-review-dec-2025.md`.
|
||||
- Defined evidence logging: future session notes in `docs/process/changes/`, remediation tasks as Issues (label `TODO`) or `docs/process/todo/` entries linked to `SEC-*` tickets where applicable.
|
||||
- Mapped roles/trust boundaries and inventoried marketing/public API route surfaces (locale-prefixed marketing group with throttled contact forms and signed gift voucher print; guest PWA view routes; Event Admin SPA catch-all; checkout/paddle webhook exposure; API v1 marketing + public event endpoints with throttles; tenant API protected by `auth:sanctum`, `tenant.collaborator`, `tenant.isolation`, `throttle:tenant-api`, plus `tenant.admin` on sensitive routes).
|
||||
- Captured environment/header defaults: `.env.example` ships with `APP_DEBUG=true` (must be false in prod) and HTTP APP_URL; session defaults `same_site=lax`, `SESSION_ENCRYPT=false`, secure cookie flag unset; CORS uses Laravel defaults (all origins/methods, credentials=false) on `api/*`; CSP middleware added to web group sets nonce-based script-src but leaves style-src with `'unsafe-inline'` and broad https/data allowances; skips CSP when debug/local.
|
||||
- Added data class/retention sketch: media storage (variants via signed URLs; tenant-governed retention), join tokens/access logs and planned hashing, auth/session tokens (Sanctum/PATs, OAuth), PII (contact form, member lists, billing contact), billing identifiers (Paddle/Stripe/PayPal), logs/analytics (Matomo consent plan, request timing middleware).
|
||||
- Captured seeded test identities: Super admin (`ADMIN_EMAIL`/`ADMIN_PASSWORD`, defaults `admin@example.com` / `ChangeMe123!`), tenant admin demo (`tenant-demo@fotospiel.app` / `Demo1234!`), guest join token from demo event (`W2E3sbt7yclzpkAwNSARHYTVN1sPLBad8hfUjLVHmjkUviPd`), with seed commands (`migrate --seed` or targeted seeders).
|
||||
- Noted env assumptions for dynamic testing: set HTTPS `APP_URL`, secure/samesite cookies, adjust `SANCTUM_STATEFUL_DOMAINS` for SPA/PWA origins, ensure storage disks and `storage:link` ready, supply webhook secrets/URLs, and run queues for media/security jobs.
|
||||
- Mapped role→data/retention and drafted dynamic testing harness scope (marketing/API abuse checks, guest PWA upload/share/cache tests, event admin CRUD/IDOR checks, webhook replay for freshness/idempotency, media pipeline AV/EXIF tests).
|
||||
- Converted the testing outline into actionable checklists per surface (marketing/API, guest PWA, event admin, webhooks/billing, media pipeline, cross-cutting headers/CSRF/rate limits).
|
||||
- Added guest upload gating plan (scan-before-publish, auto-approve when clean; optional manual moderation flag; signed URLs/private storage, API changes).
|
||||
|
||||
## Next Steps
|
||||
- [ ] Start executing checklists (begin with marketing/API headers/CSP/CORS + guest PWA upload/share flows) and log findings with PoCs and severities.
|
||||
|
||||
## Findings — Marketing/API headers & Guest PWA upload/share (2025-12-08)
|
||||
|
||||
**Marketing/API headers & CORS**
|
||||
- Missing security headers: no HSTS, Referrer-Policy, Permissions-Policy, or frame-ancestors/X-Frame-Options on responses; CSP middleware only for web group and skipped in debug/local (prod only). → Recommend adding a response headers middleware to set HSTS (HTTPS-only), Referrer-Policy (`strict-origin-when-cross-origin`), Permissions-Policy (disable camera/mic/geolocation unless required), and frame-ancestors (`'none'` or app domain).
|
||||
- CSP style-src still uses `'unsafe-inline'` with broad `https:`/`data:` allowances; plan in `SEC-FE-01` covers nonce/hash rollout. Needs prioritization to remove inline allowance and tighten connect/img/font lists.
|
||||
- CORS was default-open; added env-driven allowlist in `config/cors.php` (origin list from `CORS_ALLOWED_ORIGINS`, app URL origin, dev hosts) and `.env.example` defaults. Prod should set exact domains; credentials stay off unless explicitly enabled.
|
||||
|
||||
**Guest PWA upload/share**
|
||||
- Upload validation allows `image` types including SVG; files are stored and URLs returned via `Storage::url` without sanitisation. SVGs can carry script and would be served from first-party origin, enabling stored XSS via shared links/gallery. → Recommend rejecting SVG (or sanitising server-side) for guest uploads.
|
||||
- No antivirus/EXIF scrubbing triggered in upload flow: `GuestPhotoUploaded` listener only sends notifications; `security` config not wired. → Recommend enqueueing AV/EXIF jobs on upload before marking `approved`/serving assets.
|
||||
- Uploaded assets are immediately marked `status='approved'` and URLs returned (likely public if disk is public). Confirm disk visibility; if public, anyone with URL can fetch regardless of token. → Recommend using signed URLs/private visibility and deferring publication until approval/security scan succeeds.
|
||||
|
||||
**Mitigations implemented (2025-12-08)**
|
||||
- CORS tightened: new env-driven allowlist in `config/cors.php` (`CORS_ALLOWED_ORIGINS` etc.), defaults to localhost; prod should set exact domains to match Traefik/nginx.
|
||||
- Security headers middleware added (`ResponseSecurityHeaders`) for web/api: sets Referrer-Policy `strict-origin-when-cross-origin`, X-Content-Type-Options nosniff, X-Frame-Options SAMEORIGIN, Permissions-Policy (camera/mic/geo disabled), and HSTS on secure non-local requests.
|
||||
- Guest upload hardened: rejects SVG via `mimes` allowlist, sets uploads to `status=pending` (no file URLs in response), and dispatches `ProcessPhotoSecurityScan` on upload. Scan job now auto-approves on clean or skipped scans, rejects on infected. Gallery endpoints already filter `status=approved`, so pending items are hidden until scan finishes.
|
||||
- Gallery/API assets moving to signed access: gallery listings and stats now use temporary signed routes for thumbnails/full URLs (token + photo id) instead of raw `Storage::url` where possible; queries filter to approved status. Fallbacks remain for legacy paths.
|
||||
- CSP tightened: added style nonce, allowed https style sources for Stripe/Paddle, removed `style-src 'unsafe-inline'` in non-dev (dev keeps inline for Vite), and added `frame-ancestors 'self'`. Script nonce already in place.
|
||||
- Branding assets signed: added signed branding asset route with path allowlist; branding logos use signed URLs; blog banners now emit signed URLs instead of raw `Storage::url`. Tenant photo resource now emits signed URLs for full/thumbnail variants.
|
||||
- Paddle webhook throttled: added `throttle:paddle-webhook` (30/min per IP).
|
||||
- Inline scripts/styles in guest/admin blades now carry nonces; inline styles consolidated into nonce’d blocks.
|
||||
- Backfill thumbnails stores relative paths (no public URLs).
|
||||
- Data export downloads remain auth-gated; added existence check and private/no-store headers on download.
|
||||
|
||||
**Remaining (low priority)**
|
||||
- Signed URL TTL/scoping: can shorten TTLs (gallery/branding) and bind signatures to token/event for stricter replay protection; current defaults ~30–60 mins are acceptable but could be reduced.
|
||||
- Guest asset throttles: consider throttles on gallery asset/download/share routes for abuse mitigation; not critical if monitoring is in place.
|
||||
- CORS prod allowlist: env-driven config exists; set `CORS_ALLOWED_ORIGINS` in prod/stage to match Traefik hosts when ready.
|
||||
- Logging/PII: current logging avoids raw tokens/paths; keep this guard in future changes.
|
||||
@@ -1,4 +0,0 @@
|
||||
# Ops-Mail Default & Widerrufsbelehrung Routing
|
||||
|
||||
- `MAIL_OPS` neu in `config/mail.php` (Default: `info@fotospiel.app` in `.env.example`). Ops-Benachrichtigungen für Käufe/Add-ons/Refunds nutzen diese Adresse.
|
||||
- Neue Legal-Routen für Widerrufsbelehrung (`/de/widerrufsbelehrung`, `/en/withdrawal`). Inhalte werden aus der `legal_pages` Tabelle geladen; Fallback-Markdowns liegen unter `docs/legal/widerrufsbelehrung-de/en.md`. Markdown wird wie bei anderen Legal-Seiten gerendert.
|
||||
@@ -1,31 +0,0 @@
|
||||
# Product & Ops Roadmap
|
||||
|
||||
_Last updated: 2025-10-25_
|
||||
|
||||
This high-level view connects the active epics in `docs/process/todo/` so stakeholders can scan what is shipping now versus what is queued next. Detailed checklists live in the linked TODO files, and day-to-day notes go into `docs/process/changes/`.
|
||||
|
||||
-## Now (Q4 2025)
|
||||
-
|
||||
- **Security Hardening Epic** (`docs/process/todo/security-hardening-epic.md`)
|
||||
Rolling out dual-key auth, hashed join tokens, signed asset URLs, streaming uploads, and webhook hardening. Tracks six workstreams (identity, tokens, API resilience, media services, billing, frontend/CSP).
|
||||
- **Streaming Upload Refactor** (`docs/process/todo/media-streaming-upload-refactor.md`)
|
||||
Designing the chunked upload/session pipeline (SEC-MS-02) to lift photo size caps and improve reliability before updating the guest PWA.
|
||||
- **Paddle Billing Migration & Catalog Sync**
|
||||
- Platform migration plan tracked in `docs/process/todo/paddle-migration.md` (env/config, service layer, admin billing).
|
||||
- Catalog synchronization and Filament UX tracked in `docs/process/todo/paddle-catalog-sync.md`.
|
||||
|
||||
## Next Up (Q1 2026)
|
||||
|
||||
- **Localized SEO & Hreflang Strategy** (`docs/process/todo/localized-seo-hreflang-strategy.md`)
|
||||
Route-prefix migration, hreflang/canonical cleanup, and sitemap realignment for the marketing site and checkout.
|
||||
- **Paddle Customer Success Metrics** (spin-off from the migration tasks)
|
||||
Finalize tenant ↔ Paddle sync, sandbox catalog seeding, and rollout/rollback procedures before GA. Captured in the remaining unchecked items of the Paddle TODO files.
|
||||
|
||||
## Recently Completed / Monitoring
|
||||
|
||||
- **Tenant Admin Onboarding Fusion** (`docs/archive/process/todo/tenant-admin-onboarding-fusion.md`) — Flow merged into the new PWA/TWA stack; keep monitoring localization coverage and checkout UX alignment.
|
||||
- **Event Join Token Hardening** (`docs/archive/process/todo/event-join-token-hardening.md`) — All phases completed; continue monitoring default lifetime/rotation decisions.
|
||||
- **Package Limit Experience Overhaul** (`docs/archive/process/todo/package-limit-experience-overhaul.md`) — Foundation live; alerts/reporting improvements now handled opportunistically.
|
||||
- **Checkout Refactor & Package Limits** (`docs/process/changes/2025-10-05-checkout-refactor-todo.md`) — keep feature flags and alert thresholds under review but no net-new roadmap investment needed right now.
|
||||
|
||||
For historical roadmaps predating the split PRP, see `docs/archive/implementation-roadmap.md`. New initiatives should always start as a `docs/process/todo/*.md` file and be referenced here once prioritized.
|
||||
@@ -1,43 +0,0 @@
|
||||
# Localized SEO hreflang Strategy TODO
|
||||
|
||||
## Goal
|
||||
Establish a consistent canonical and hreflang setup for the marketing site so search engines can index German and English content without duplicate-content penalties.
|
||||
|
||||
## Status (Stand 18.02.2026)
|
||||
- **Discovery:** In progress (route audit complete).
|
||||
- **Implementation:** In progress (canonical and locale-prefixed routing live).
|
||||
- **Validation:** Not started.
|
||||
|
||||
## Discovery
|
||||
- [x] Audit current route map and localized content coverage (marketing pages, blog, checkout flow).
|
||||
- Marketing routes live in `routes/web.php` without locale prefixes. Locale handling is session-based via `LocaleController::set`, `HandleInertiaRequests`, and `useLocalizedRoutes`.
|
||||
- Slug coverage is mixed: `/contact` (EN) and `/kontakt` (DE) coexist, `/how-it-works` vs. `/so-funktionierts`, while other key pages only exist once (e.g. `/packages`, `/demo`, `/blog`, legal pages such as `/impressum` with no EN variant). Occasion detail routes are German-only (`/anlaesse/{type}` with `hochzeit`, `geburtstag`, etc.).
|
||||
- Blog URLs are shared across locales (`/blog`, `/blog/{slug}`), with translated content injected server-side. Checkout surfaces (`/purchase-wizard/{package}`, `/checkout/{package}`) rely on shared slugs and localized copy but no alternate URLs.
|
||||
- `MarketingLayout` currently generates a single canonical URL per request and an `x-default` alternate, but no locale-specific `hreflang` links. Canonical calculation removes a `/de|/en` prefix even though paths are prefix-free, so both locales resolve to the same canonical if we later introduce prefixed URLs.
|
||||
- The sitemap at `public/sitemap.xml` already lists `/de/...` and `/en/...` alternates that the app does not currently serve, causing mismatch risk.
|
||||
- [x] Decide on URL strategy (session-based locale vs. language-prefixed routes) and document migration implications.
|
||||
- Decision: adopt path-prefixed locales (`/{locale}/{slug}`) for all marketing and checkout-facing routes, matching the i18n PRP guidance. Default requests (`/foo`) will 301 to the locale-specific URL using the visitor’s persisted preference or `de` fallback.
|
||||
- Migration outline:
|
||||
1. Introduce a `SetLocaleFromPath` middleware to extract the first segment and share it with Inertia; wire it into a `Route::group` with `prefix('{locale}')` (constrained to `de|en`) in `routes/web.php`.
|
||||
2. Move existing marketing routes into the prefixed group, normalising slugs so EN and DE share identical structures where feasible (e.g. `/de/kontakt` → `/de/contact` or `/de/kontakt` mirrored by `/en/contact`). Keep legacy German-only slugs (`/so-funktionierts`, `/anlaesse/...`) behind per-locale path maps.
|
||||
3. Add legacy fallback routes (without prefix) that permanently redirect to the new prefixed URLs to preserve existing backlinks and sitemap entries.
|
||||
4. Ensure Inertia helpers (`useLocalizedRoutes`) and navigation components build URLs with the active locale segment instead of relying on session posts to `/set-locale`.
|
||||
- Blog slugs remain language-agnostic identifiers under `/de/blog/{slug}` and `/en/blog/{slug}`; content localization continues via translated fields.
|
||||
- [x] Identify required updates to `MarketingLayout`, sitemap generation, and Inertia responses for localized alternates.
|
||||
- `MarketingLayout` needs to accept structured SEO props (canonical URL, title, description, alternates) instead of deriving everything client-side. It should emit `<link rel="alternate" hreflang="">` entries for each supported locale plus `x-default`, set `og:locale`/`og:locale:alternate`, and keep canonical URLs locale-specific (no prefix stripping).
|
||||
- Server responses should standardise SEO data via a helper (e.g. `MarketingPage::make()` or dedicated view model) so each `Inertia::render` call provides `seo` props with `canonical`, `alternates`, and translated meta. `HandleInertiaRequests` can share `supportedLocales` and the resolved host, while a new `LocalizedUrlGenerator` service maps routes/slugs per locale.
|
||||
- The static `public/sitemap.xml` must be regenerated (or replaced with an automated generator/Artisan command) once prefixed URLs exist, ensuring each entry carries self-referential canonicals and paired `xhtml:link` elements. Include blog detail pages and legal pages for both locales.
|
||||
|
||||
## Implementation
|
||||
- [x] Ensure canonical URLs and hreflang tags are generated per locale with reciprocal references.
|
||||
- [x] Expose locale-specific URLs in navigation, Open Graph tags, and any structured data.
|
||||
- [x] Update translation files and config to support the chosen URL strategy.
|
||||
|
||||
## Validation
|
||||
- [ ] Add automated checks (feature test or Playwright) verifying hreflang/canonical tags for both locales.
|
||||
- [ ] Validate via Search Console-style inspection or lighthouse to confirm alternate links render correctly.
|
||||
- [ ] Update docs (PRP + marketing playbooks) with the final hreflang strategy and operational guidance.
|
||||
|
||||
## Open Questions
|
||||
- How will we handle locale fallbacks for missing translations when hreflang is enforced?
|
||||
- Do we need localized sitemap indexes per language or a unified sitemap with hreflang annotations?
|
||||
@@ -1,131 +0,0 @@
|
||||
# SEC-MS-02 — Streaming Upload Refactor (Requirements Draft)
|
||||
|
||||
**Goal**
|
||||
Replace the current “single POST with multipart FormData” guest upload with a streaming / chunked pipeline that:
|
||||
|
||||
- avoids buffering entire files in PHP memory
|
||||
- supports larger assets (target 25 MB originals)
|
||||
- keeps antivirus/EXIF scrubbing and storage accounting intact
|
||||
- exposes clear retry semantics to the guest PWA
|
||||
|
||||
This document captures the scope for SEC-MS-02 and feeds into implementation tickets.
|
||||
|
||||
---
|
||||
|
||||
## 1. Current State (Baseline)
|
||||
|
||||
- Upload endpoint: `POST /api/v1/events/{token}/upload` handled by `EventPublicController::upload`.
|
||||
- Laravel validation enforces `image|max:6144` (≈6 MB). Entire file is received via `Request::file('photo')`.
|
||||
- Storage flow: `Storage::disk($hotDisk)->putFile(...)` followed by synchronous thumbnail creation and `event_media_assets` bookkeeping.
|
||||
- Device rate limiting: simple counter (`guest_name` = device id) per event.
|
||||
- Security: join token validation + IP rate limiting; antivirus/exif cleanup handled asynchronously by `ProcessPhotoSecurityScan` (queued).
|
||||
- Frontend: guest PWA uses `fetch` + FormData; progress handled by custom XHR queue for UI feedback.
|
||||
|
||||
Pain points:
|
||||
- Upload size ceiling due to PHP post_max_size + memory usage.
|
||||
- Slow devices stall the controller request; no streaming/chunk resume.
|
||||
- Throttling/locks only consider completed uploads; partial data still consumes bandwidth.
|
||||
|
||||
---
|
||||
|
||||
## 2. Target Architecture Overview
|
||||
|
||||
### 2.1 Session-Based Chunk Upload
|
||||
|
||||
1. **Create session**
|
||||
- `POST /api/v1/events/{token}/uploads` → returns `upload_id`, `upload_key`, storage target, chunk size.
|
||||
- Validate join token + device limits *before* accepting session. Record session in new table `event_upload_sessions`.
|
||||
|
||||
2. **Upload chunks**
|
||||
- `PUT /api/v1/events/{token}/uploads/{upload_id}/chunk` with headers: `Content-Range`, `Content-Length`, `Upload-Key`.
|
||||
- Chunks written to hot storage *stream* destination (e.g. `storage/app/uploads/{upload_id}/chunk_{index}`) via `StreamedResponse`/`fopen`.
|
||||
- Track received ranges in session record; enforce sequential or limited parallel chunks.
|
||||
|
||||
3. **Complete upload**
|
||||
- `POST /api/v1/events/{token}/uploads/{upload_id}/complete`
|
||||
- Assemble chunks → single file (use stream copy to final path), compute checksum, dispatch queue jobs (AV/EXIF, thumbnail).
|
||||
- Persist `photos` row + `event_media_assets` references (mirroring current logic).
|
||||
|
||||
4. **Abort**
|
||||
- `DELETE /api/v1/events/{token}/uploads/{upload_id}` to clean up partial data.
|
||||
|
||||
### 2.2 Storage Strategy
|
||||
|
||||
- Use `EventStorageManager` hot disk but with temporary “staging” directory.
|
||||
- After successful assembly, move to final `events/{eventId}/photos/{uuid}.ext`.
|
||||
- For S3 targets, evaluate direct multipart upload to S3 using pre-signed URLs:
|
||||
- Option A (short-term): stream into local disk, then background job pushes to S3.
|
||||
- Option B (stretch): delegate chunk upload directly to S3 using `createMultipartUpload`, storing uploadId + partETags.
|
||||
- Ensure staging cleanup job removes abandoned sessions (cron every hour).
|
||||
|
||||
### 2.3 Metadata & Limits
|
||||
|
||||
- New table `event_upload_sessions` fields:
|
||||
`id (uuid)`, `event_id`, `join_token_id`, `device_id`, `status (pending|uploading|assembling|failed|completed)`, `total_size`, `received_bytes`, `chunk_size`, `expires_at`, `failure_reason`, timestamps.
|
||||
- Device/upload limits: enforce daily cap per device via session creation; consider max concurrent sessions per device/token (default 2).
|
||||
- Maximum file size: 25 MB (configurable via `config/media.php`). Validate at `complete` by comparing expected vs actual bytes.
|
||||
|
||||
### 2.4 Validation & Security
|
||||
|
||||
- Require `Upload-Key` secret per session (stored hashed) to prevent hijacking.
|
||||
- Join token + device validations reused; log chunk IP + UA for anomaly detection.
|
||||
- Abort sessions on repeated integrity failures or mismatched `Content-Range`.
|
||||
- Update rate limiter to consider `PUT` chunk endpoints separately.
|
||||
|
||||
### 2.5 API Responses & Errors
|
||||
|
||||
- Provide consistent JSON:
|
||||
- `201` create: `{ upload_id, chunk_size, expires_at }`
|
||||
- chunk success: `204`
|
||||
- complete: `201 { photo_id, file_path, thumbnail_path }`
|
||||
- error codes: `upload_limit`, `chunk_out_of_order`, `range_mismatch`, `session_expired`.
|
||||
- Document in `docs/prp/03-api.md` + update guest SDK.
|
||||
|
||||
### 2.6 Backend Jobs
|
||||
|
||||
- Assembly job (if asynchronous) ensures chunk merge is offloaded for large files; update `ProcessPhotoSecurityScan` to depend on final asset record.
|
||||
- Add metric counters (Prometheus/Laravel events) for chunk throughput, failed sessions, average complete time.
|
||||
|
||||
---
|
||||
|
||||
## 3. Frontend Changes (Guest PWA)
|
||||
|
||||
- Replace current FormData POST with streaming uploader:
|
||||
- Request session, slice file into `chunk_size` (default 1 MB) using `Blob.slice`, upload sequentially with retry/backoff.
|
||||
- Show granular progress (bytes uploaded / total).
|
||||
- Support resume: store `upload_id` & received ranges in IndexedDB; on reconnect query session status from new endpoint `GET /api/v1/events/{token}/uploads/{upload_id}`.
|
||||
- Ensure compatibility fallback: if browser lacks required APIs (e.g. old Safari), fallback to legacy single POST (size-limited) with warning.
|
||||
- Update service worker/queue to pause/resume chunk uploads when offline.
|
||||
|
||||
---
|
||||
|
||||
## 4. Integration & Migration Tasks
|
||||
|
||||
1. **Schema**: create `event_upload_sessions` table + indices; optional `event_upload_chunks` if tracking per-part metadata.
|
||||
2. **Config**: new entries in `config/media.php` for chunk size, staging path, session TTL, max size.
|
||||
3. **Env**: add `.env` knobs (e.g. `MEDIA_UPLOAD_CHUNK_SIZE=1048576`, `MEDIA_UPLOAD_MAX_SIZE=26214400`).
|
||||
4. **Cleanup Command**: `php artisan media:prune-upload-sessions` to purge expired sessions & staging files. Hook into cron `/cron/media-prune-sessions.sh`.
|
||||
5. **Docs**: update PRP (sections 03, 10) and guest PWA README; add troubleshooting guide for chunk upload errors.
|
||||
6. **Testing**:
|
||||
- Unit: session creation, chunk validation, assembly with mocked storage.
|
||||
- Feature: end-to-end upload success + failure (PHPUnit).
|
||||
- Playwright: simulate chunked upload with network throttling.
|
||||
- Load: ensure concurrent uploads do not exhaust disk IO.
|
||||
|
||||
---
|
||||
|
||||
## 5. Open Questions
|
||||
|
||||
- **S3 Multipart vs. Local Assembly**: confirm timeline for direct-to-S3; MVP may prefer local assembly to limit complexity.
|
||||
- **Encryption**: decide whether staging chunks require at-rest encryption (likely yes if hot disk is shared).
|
||||
- **Quota Enforcement**: should device/event caps be session-based (limit sessions) or final photo count (existing)? Combine both?
|
||||
- **Backward Compatibility**: decide when to retire legacy endpoint; temporarily keep `/upload` fallback behind feature flag.
|
||||
|
||||
---
|
||||
|
||||
## 6. Next Steps
|
||||
|
||||
- Finalise design choices (S3 vs local) with Media Services.
|
||||
- Break down into implementation tasks (backend API, frontend uploader, cron cleanup, observability).
|
||||
- Schedule dry run in staging with large sample files (20+ MB) and monitor memory/CPU.
|
||||
- Update SEC-MS-02 ticket checklist with deliverables above.
|
||||
@@ -1,28 +0,0 @@
|
||||
# Paddle Catalog Sync Rollout
|
||||
|
||||
- [x] **Schema Prep**
|
||||
- [x] Add migration for `paddle_sync_status`, `paddle_synced_at`, and `paddle_snapshot` JSON on `packages`.
|
||||
- [x] Update `Package` model casts/fillable + ensure factory coverage.
|
||||
- [ ] **Service Layer**
|
||||
- [x] Scaffold `PaddleCatalogService` (product/price CRUD, custom data mapping).
|
||||
- [ ] Add DTO helpers for Paddle product/price responses.
|
||||
- [ ] Extend `PaddleClient` tests/mocks for catalog endpoints.
|
||||
- [x] **Sync Logic**
|
||||
- [x] Implement `SyncPackageToPaddle` job with create/update flows and metadata diffing.
|
||||
- [x] Create `PaddlePackagePull` job for optional remote-to-local reconciliation.
|
||||
- [x] Add `paddle:sync-packages` artisan command (`--dry-run`, `--package=`, `--pull`).
|
||||
- [ ] **Admin UX**
|
||||
- [x] Enhance Filament PackageResource with sync status badges + last sync timestamp.
|
||||
- [ ] Add table/detail actions (“Sync to Paddle”, “Link existing Paddle entity”).
|
||||
- [ ] Surface last error/log context in the admin sidebar panel.
|
||||
- [ ] **Ops & Observability**
|
||||
- [ ] Configure dedicated log channel/Slack hook for catalog sync outcomes.
|
||||
- [ ] Document failure recovery playbook (retry, unlink, support escalation).
|
||||
- [ ] **Testing & QA**
|
||||
- [x] Unit tests for service + jobs using mocked Paddle API.
|
||||
- [x] Feature test covering artisan command flow.
|
||||
- [ ] Playwright smoke to confirm admin sync action displays status.
|
||||
- [ ] **Rollout Checklist**
|
||||
- [ ] Seed Paddle sandbox catalog via MCP server using migrated data.
|
||||
- [ ] Verify legacy packages mapped to Paddle IDs before enabling auto-sync.
|
||||
- [ ] Announce workflow change to admin users (release notes + docs update).
|
||||
@@ -1,14 +0,0 @@
|
||||
# Paddle Billing Migration
|
||||
|
||||
- [x] Review current billing implementation (Stripe, Paddle, RevenueCat) across code, jobs, webhooks, docs.
|
||||
- [x] Design Paddle data mappings for packages ↔ products/prices, including required metadata round-trip.
|
||||
- [ ] Extend Laravel config/env handling for Paddle keys, webhook secrets, feature flags (sandbox + production).
|
||||
- [ ] Build Paddle API service layer and register sandbox webhooks; document endpoints/events consumed.
|
||||
- [ ] Add admin catalog sync UI for packages (create/update in Paddle, display sync status, store Paddle IDs).
|
||||
- [ ] Implement tenant ↔ Paddle customer synchronization and related webhook handlers.
|
||||
- [x] Replace marketing checkout payment step with Paddle-hosted checkout flow and success callbacks.
|
||||
- [ ] Update tenant admin billing pages to read Paddle subscription/transaction data and manage plans.
|
||||
- [ ] Define mobile/native billing strategy (RevenueCat vs Paddle) and align app logic.
|
||||
- [ ] Add automated tests for Paddle integration (unit, feature, e2e) covering checkout, webhooks, sync.
|
||||
- [ ] Populate Paddle sandbox catalog via MCP server and validate end-to-end activation flow.
|
||||
- [ ] Draft production cutover procedure (catalog creation, flag switch, legacy shutdown, monitoring, rollback).
|
||||
@@ -1,67 +0,0 @@
|
||||
# Security Hardening Epic (Q4 2025)
|
||||
|
||||
## Goal
|
||||
Raise the baseline security posture across guest APIs, checkout, media storage, and identity flows so the platform can scale multi-tenant traffic with auditable, revocable access.
|
||||
|
||||
## Workstreams
|
||||
|
||||
1. **Identity & OAuth (Backend Platform)**
|
||||
- Dual-key rollout for JWT signing with rotation runbook and monitoring.
|
||||
- Refresh-token revocation tooling (per device/IP) and anomaly alerts.
|
||||
- Device fingerprint/subnet allowances documented and configurable.
|
||||
- **Tickets**
|
||||
- `SEC-IO-01` — Document PAT revocation/rotation playbook (Week 1). Include scripted revocation of stale tokens and guidance for forced re-login. (Replace legacy OAuth key rotation runbook).
|
||||
- `SEC-IO-02` — Build refresh-token management UI + audit logs (Week 2). *(Filament console + audit trail added 2025-10-23)*
|
||||
- `SEC-IO-03` — Implement subnet/device matching configuration & tests (Week 3).
|
||||
|
||||
2. **Guest Join Tokens (Guest Platform)**
|
||||
- Store hashed tokens with irreversible lookups; migrate legacy data.
|
||||
- Add per-token usage analytics, alerting on spikes or expiry churn.
|
||||
- Extend gallery/photo rate limits (token + IP) and surface breach telemetry in storage dashboards.
|
||||
- **Tickets**
|
||||
- `SEC-GT-01` — Hash join tokens + data migration script (Week 1).
|
||||
- `SEC-GT-02` — Implement token analytics + Grafana dashboard (Week 2). *(Logging + Filament summaries delivered 2025-10-23; monitoring dashboard still pending)*
|
||||
- `SEC-GT-03` — Tighten gallery/photo rate limits + alerting (Week 3).
|
||||
|
||||
3. **Public API Resilience (Core API)**
|
||||
- Serve signed asset URLs instead of raw storage paths; expire appropriately.
|
||||
- Document incident response runbooks and playbooks for abuse mitigation.
|
||||
- Add synthetic monitors for `/api/v1/gallery/*` and upload endpoints.
|
||||
- **Tickets**
|
||||
- `SEC-API-01` — Signed URL middleware + asset migration (Week 1).
|
||||
- `SEC-API-02` — Incident response playbook draft + review (Week 2). *(Runbook: `docs/ops/deployment/public-api-incident-playbook.md`, added 2025-10-23)*
|
||||
- `SEC-API-03` — Synthetic monitoring + alert config (Week 3).
|
||||
|
||||
4. **Media Pipeline & Storage (Media Services)**
|
||||
- Integrate antivirus/EXIF scrubbers and streaming upload paths to avoid buffering.
|
||||
- Verify checksum integrity on hot → archive transfers with alert thresholds.
|
||||
- Surface storage target health (capacity, latency) in Super Admin dashboards.
|
||||
- **Tickets**
|
||||
- `SEC-MS-01` — AV + EXIF scrubber worker integration (Week 1). *(Job: `ProcessPhotoSecurityScan`, queue: `media-security`)*
|
||||
- `SEC-MS-02` — Streaming upload refactor + tests (Week 2). *(Requirements draft: `docs/process/todo/media-streaming-upload-refactor.md`, 2025-10-23)*
|
||||
- `SEC-MS-03` — Checksum validation + alert thresholds (Week 3).
|
||||
- `SEC-MS-04` — Storage health widget in Super Admin (Week 4).
|
||||
|
||||
5. **Payments & Webhooks (Billing)**
|
||||
- Link Paddle webhooks to checkout sessions with idempotency locks.
|
||||
- Add signature freshness validation + retry policies for provider outages.
|
||||
- Pipe failed capture events into credit ledger audits and operator alerts.
|
||||
- **Tickets**
|
||||
- `SEC-BILL-01` — Checkout session linkage + idempotency locks (Week 1).
|
||||
- `SEC-BILL-02` — Signature freshness + retry policy implementation (Week 2).
|
||||
- `SEC-BILL-03` — Failed capture notifications + ledger hook (Week 3).
|
||||
|
||||
6. **Frontend & CSP (Marketing Frontend)**
|
||||
- Replace `unsafe-inline` allowances with nonce/hash policies for Stripe + Matomo.
|
||||
- Gate analytics script injection behind consent with localised disclosures.
|
||||
- Broaden cookie banner layout to surface GDPR/legal copy clearly.
|
||||
- **Tickets**
|
||||
- `SEC-FE-01` — CSP nonce/hashing utility + rollout (Week 1).
|
||||
- `SEC-FE-02` — Consent-gated analytics loader refactor (Week 2).
|
||||
- `SEC-FE-03` — Cookie banner UX update + localisation (Week 3).
|
||||
|
||||
## Deliverables
|
||||
- Updated docs (`docs/prp/09-security-compliance.md`, runbooks) with ownership & SLAs.
|
||||
- Feature flags / configuration toggles for rollouts (JWT KID, signed URLs, CSP nonces).
|
||||
- Monitoring dashboards + alerting coverage per workstream.
|
||||
- Integration and Playwright coverage validating the hardened flows.
|
||||
@@ -1,191 +0,0 @@
|
||||
# Security Review (Dec 2025)
|
||||
|
||||
## Goal
|
||||
Run a structured security review across marketing frontend + public API, Guest PWA, and Event Admin to produce prioritized findings, PoCs, and remediation tasks aligned with the Security Hardening epic.
|
||||
|
||||
## Deliverables
|
||||
- Threat model + scope notes.
|
||||
- Findings list with severity/likelihood, PoCs, and recommended fixes.
|
||||
- Follow-up tasks filed in `docs/process/todo/` or Issues (label `TODO`) mapped to existing `SEC-*` tickets where possible.
|
||||
|
||||
## Status (Stand 2025-12-08)
|
||||
- Discovery: In progress (scope mapped; marketing/API route inventory captured).
|
||||
- Code review: Not started.
|
||||
- Dynamic testing: Not started.
|
||||
- Reporting: Not started.
|
||||
|
||||
## Scope & Trust Boundaries
|
||||
- Marketing site + public API (web + api route groups, CORS, rate limits).
|
||||
- Guest PWA (resources/js/guest, service worker, background sync, offline cache, uploads).
|
||||
- Event Admin / Tenant Admin PWA (Filament resources, React admin, OAuth2/PKCE, Sanctum).
|
||||
- Payments/Webhooks (Paddle, RevenueCat), media pipeline (uploads/QR/PDF), storage visibility.
|
||||
- Headers/CSP/cookies, session/config defaults, logging hygiene (no PII).
|
||||
|
||||
## Workstreams & Checklists
|
||||
|
||||
1) Foundations & Threat Model
|
||||
- [x] Map roles/data:
|
||||
- Marketing visitors (no auth; optional contact form PII).
|
||||
- Guest attendees via join token (photos, likes, push subscriptions, optional contact/email if provided).
|
||||
- Tenant collaborators/admins (event config, uploads, member lists, notifications).
|
||||
- Super admins (platform-level controls).
|
||||
- Automated actors (Paddle/RevenueCat webhooks, background workers/queues).
|
||||
- [x] Data classes & storage/retention (baseline):
|
||||
- Photos/media: stored in configured filesystem disks (see `filesystems.php`/storage pipeline), variants via signed URLs; retention governed by tenant settings (per PRP 09/10).
|
||||
- Join tokens & gallery access: tokens (hashing planned), events, and access logs; rate-limit counters; short-lived signed share links.
|
||||
- Account/auth: Sanctum tokens, OAuth (Google), session cookies (`same_site=lax`, secure flag env-driven), PATs; device/browser not fingerprinted by default.
|
||||
- PII/contact: marketing contact form submissions (controller TBD), tenant member lists, notification preferences, billing contact details.
|
||||
- Billing: Paddle/Stripe/PayPal identifiers, checkout sessions, add-on purchases; webhooks queued.
|
||||
- Logs/metrics: structured logs (no PII mandate in PRP 09), Matomo analytics (consent-gated plan), request timing middleware.
|
||||
- [x] Confirm env/header defaults for review:
|
||||
- `.env.example` ships with `APP_DEBUG=true` and `APP_URL=http://localhost`; production must set `APP_DEBUG=false` and HTTPS URL.
|
||||
- Session defaults: driver `redis` (unless overridden), `SESSION_ENCRYPT=false`, `SAME_SITE=lax`, `SESSION_SECURE_COOKIE` unset (inherits HTTPS), partitioned cookies disabled.
|
||||
- CORS: default Laravel config (not customized) => `paths=['api/*','sanctum/csrf-cookie']`, `allowed_origins=['*']`, `allowed_methods=['*']`, credentials `false`.
|
||||
- CSP: web group appends `ContentSecurityPolicy` middleware; in debug/local it skips header. In prod it sets nonce-based `script-src` and broad `style-src 'unsafe-inline' https: data:`; allows Stripe/Paddle/Localize, Matomo origin if configured.
|
||||
- [x] Test identities / fixtures (seeded):
|
||||
- Super admin: `ADMIN_EMAIL`/`ADMIN_PASSWORD` (defaults `admin@example.com` / `ChangeMe123!`) via `SuperAdminSeeder`.
|
||||
- Tenant admin demo: `tenant-demo@fotospiel.app` / `Demo1234!` via `DemoTenantSeeder` (package assigned, verified, active).
|
||||
- Guest tokens: `DemoEventSeeder` seeds `demo-wedding-2025` with join token `W2E3sbt7yclzpkAwNSARHYTVN1sPLBad8hfUjLVHmjkUviPd` (stored hashed+encrypted). Use for guest/PWA/API tests; additional demo event without explicit token uses generated token.
|
||||
- Seed commands: `php artisan migrate --seed` (or targeted seeders: `db:seed --class=SuperAdminSeeder`, `DemoTenantSeeder`, `DemoEventSeeder`).
|
||||
- [ ] Env assumptions for dynamic testing:
|
||||
- Base URL/HTTPS: ensure `APP_URL` points to the test host with HTTPS; set `SESSION_SECURE_COOKIE=true` and `SESSION_SAME_SITE=lax/none` as needed for cross-origin tools.
|
||||
- CORS/stateful domains: configure `SANCTUM_STATEFUL_DOMAINS` to include test origins (e.g., localhost:3000/5173) for SPA/PWA flows; consider tightening CORS from `*` to allowed hosts during tests if feasible.
|
||||
- Storage: confirm disks (local/s3) and public assets linkage (`storage:link`) for media tests; signed URL generation in place.
|
||||
- Webhooks: set Paddle/RevenueCat webhook secrets and target URLs; use throttling expectations (`throttle:60,1` on revenuecat; none on paddle webhooks).
|
||||
- Queues: ensure queue workers running for uploads/scan jobs when exercising media pipelines.
|
||||
|
||||
## Role → Data/Storage/Retention Mapping (initial)
|
||||
- Marketing visitor: contact form PII (controller storage TBD); cookies/localStorage for locale/consent; Matomo analytics (consent-gated); no persistent account.
|
||||
- Guest (join token): event/gallery access via token; uploads (photo + EXIF), likes, push subscription keys; cached assets in PWA/service worker; signed share links; rate-limit counters and join-token access logs; retention tied to event/gallery expiry and tenant settings.
|
||||
- Tenant collaborator/admin: account profile, tenant settings, events, members, notifications, tasks, uploads; billing identifiers for purchases; OAuth/Google tokens; Sanctum PATs/session cookies; audit/logs for actions; retention per tenant policy, legal retention for billing.
|
||||
- Super admin: same as tenant admin plus platform-level audit/actions; impersonation logs expected; no extra PII beyond account.
|
||||
- Webhooks (Paddle/RevenueCat): payload identifiers, signatures, session linkage; stored in webhook logs/queue jobs; retention per ops runbook.
|
||||
|
||||
## Dynamic Testing Harness Outline (draft)
|
||||
- Identities: use seeded super admin, tenant demo, and demo guest token for auth contexts; create additional tenant collaborator if needed.
|
||||
- Environments: run against local HTTPS host with `APP_URL` set; configure `SANCTUM_STATEFUL_DOMAINS` and cookies for Playwright/DAST sessions; ensure queues running.
|
||||
- Surfaces to script:
|
||||
- Marketing/API: contact form abuse/rate limit, coupon preview, gift voucher flows; check CORS preflight and CSP headers.
|
||||
- Guest PWA: join token gallery load, photo upload (valid/invalid), like/share, push subscription register/delete, offline/cache poison checks; download/share signed URL enforcement.
|
||||
- Event Admin: login (email/password + Google), CRUD on events/photos/members/tasks, package purchase intents (non-payment), photobooth enable/rotate; policy/IDOR checks.
|
||||
- Webhooks: replay signed webhook samples (Paddle/RevenueCat) with stale timestamps to validate signature freshness and idempotency behavior.
|
||||
- Media pipeline: upload with EXIF/malware test samples to observe AV/EXIF handling; verify signed URL visibility and expiry.
|
||||
|
||||
## Dynamic Testing Checklists (actionable)
|
||||
- Marketing/API
|
||||
- [ ] Verify CSP headers present in non-debug env; confirm nonce on scripts, no stray inline scripts/styles; note `'unsafe-inline'` styles as risk.
|
||||
- [ ] Exercise contact form with/without JS; confirm throttling and spam validation; inspect error leakage.
|
||||
- [ ] Coupon preview/gift voucher endpoints: validate rate limits, auth bypass attempts, input validation, CORS preflight, and response caching headers.
|
||||
- [ ] Checkout wizard/login/register endpoints: session handling, CSRF, rate limits; ensure APP_DEBUG off to avoid stack traces.
|
||||
- [ ] Public routes return 404/redirects without leaking internal paths.
|
||||
|
||||
- Guest PWA
|
||||
- [ ] Gallery load with seeded token: check caching headers, ETag, and denial for invalid/expired token.
|
||||
- [ ] Upload tests: valid image, oversized, wrong MIME, EXIF-laden, EICAR sample; expect AV/EXIF handling and clear errors.
|
||||
- [ ] Likes/share: ensure signed share links required; verify signed asset URLs enforce expiry and token scope.
|
||||
- [ ] Push subscription register/delete flows with bad payloads; ensure CORS/preflight and auth tied to token.
|
||||
- [ ] Service worker/cache: verify scope, versioning, offline fallback, and resistance to cache poisoning (stale manifest/assets).
|
||||
|
||||
- Event Admin
|
||||
- [ ] Login (email/password) and Google OAuth flow happy/failure paths; session fixation/regeneration checks.
|
||||
- [ ] CRUD events/photos/members/tasks with tenant slug mismatch to probe IDOR; verify `tenant.isolation` + policies.
|
||||
- [ ] Package purchase/payment-intent endpoints without completing payment—check idempotency/validation.
|
||||
- [ ] Photobooth enable/rotate/disable endpoints with/without admin role.
|
||||
- [ ] API rate limiting (`throttle:tenant-api`) and error shape consistency; check storage visibility toggles.
|
||||
|
||||
- Webhooks & Billing
|
||||
- [ ] Replay Paddle/RevenueCat payloads with valid and stale timestamps; confirm signature verification and replay protection.
|
||||
- [ ] Send duplicate IDs to test idempotency locks and queueing behavior; observe logs without PII leakage.
|
||||
- [ ] Ensure webhook routes respect expected throttles (RevenueCat 60/min; Paddle currently none—note risk).
|
||||
|
||||
- Media Pipeline & Storage
|
||||
- [ ] Signed URL expiry for gallery/download/share links; attempts outside tenant/token should fail.
|
||||
- [ ] Verify private visibility defaults on new uploads and derivatives; public bucket exposure check.
|
||||
- [ ] AV/EXIF queue path fires on upload; monitor job logs for failures.
|
||||
- [x] Replace public URLs: gallery assets and branding/blog banners now use signed routes; tenant photo resource uses signed URLs for variants.
|
||||
|
||||
- Cross-cutting
|
||||
- [ ] Headers: HSTS, X-Frame-Options/Frame-Ancestors, Referrer-Policy, Permissions-Policy; note gaps.
|
||||
- [ ] CSRF on web forms and SPA flows; session cookie flags (Secure/HttpOnly/SameSite) over HTTPS.
|
||||
- [ ] Rate limits alignment with documented policies; error messages avoid stack traces and sensitive data.
|
||||
|
||||
## Low-Priority Follow-ups
|
||||
- Signed URL hardening: shorten TTLs (gallery/branding) and bind signatures to token/event identifiers to reduce replay risk.
|
||||
- Guest asset throttles: add rate limiters for gallery asset/download/share routes keyed by token+IP; optional given existing monitoring.
|
||||
- CORS prod allowlist: env config present; set `CORS_ALLOWED_ORIGINS` in prod/stage to match Traefik when ready.
|
||||
- Logging hygiene: keep avoiding raw tokens/paths in logs; review when adding new logging.
|
||||
|
||||
## CSP Tightening Plan
|
||||
- Add style nonces everywhere inline styles exist (root blade/templates) and remove `style-src 'unsafe-inline'` outside dev.
|
||||
- Ensure script nonce is applied (already set via Vite); audit any inline event handlers.
|
||||
- Add `frame-ancestors 'self'` to CSP to align with X-Frame-Options.
|
||||
|
||||
## Guest Upload Gating Plan (scan-before-publish, auto-approve; optional moderation)
|
||||
- Goals: keep guest uploads pending until AV/EXIF scan completes; auto-approve if clean; optional moderation toggle for tenants that want manual review; serve assets via signed URLs/private storage after approval.
|
||||
- Storage/visibility:
|
||||
- Store uploads on private disk (no public `Storage::url`); serve via signed URLs scoped to event/token with short TTL.
|
||||
- Keep `status=pending` until scan completes; do not expose paths in API responses until approved.
|
||||
- Security scanning:
|
||||
- Dispatch `ProcessPhotoSecurityScan` on upload; mark `security_scan_status` and `security_scanned_at`.
|
||||
- If infected/error: mark `rejected` with reason; optionally delete/quarantine asset and log.
|
||||
- Approval workflow:
|
||||
- Default: auto-approve when scan returns clean. Optional tenant/event flag `photo_upload_requires_manual_approval` to hold after scan for manual review (default off).
|
||||
- Pending uploads can surface in admin (list + bulk approve/reject) only when manual flag is on.
|
||||
- API changes:
|
||||
- Guest upload response: return pending state and no direct file URLs while pending.
|
||||
- Gallery/photos endpoints: filter to approved only; include pending count for admin if manual flag is on.
|
||||
- Signed URL generation: use `Storage::temporaryUrl` or signed route; avoid raw public paths.
|
||||
- Rate/abuse controls:
|
||||
- Preserve per-token/device limits; consider stricter throttles while approval is enabled.
|
||||
- Log join-token usage and anomalies for audit.
|
||||
- Migration/rollout:
|
||||
- Backfill existing photos to `approved` to avoid breaking live galleries.
|
||||
- Feature flag to enable per-tenant/event; add config toggle and admin UI.
|
||||
- Testing:
|
||||
- Feature tests for pending upload, approval flow, rejection, and signed URL access control; scan failure path blocks approval.
|
||||
- [x] Trust boundaries/entrypoints:
|
||||
- Marketing/Inertia under `/{locale}` prefix (`de|en`) with session/Accept-Language fallback redirect; login/register guarded by `guest` middleware; contact forms throttled (`throttle:contact-form`); gift voucher print uses `signed`.
|
||||
- Guest PWA entry at `/event`, `/g/{token}`, `/e/{token}/{path?}`, `/share/{slug}` (views rendered by `guest` blade; tokens unauthed).
|
||||
- Event Admin shell under `/event-admin/*` with Google OAuth endpoints; auth enforced in controller; SPA catch-all `/{view?}`.
|
||||
- Checkout endpoints always exposed (`/purchase-wizard/{package}`, `/checkout/{package}`, `/checkout/*` helpers, `/paddle/webhook`); Paddle webhook lacks explicit throttle middleware.
|
||||
- API entry at `/api/v1` (see details below); testing-only routes gated by env check.
|
||||
|
||||
2) Marketing Frontend + Public API
|
||||
- [x] Inventory routes/middleware (auth, rate limits, CORS, cache/ETag) and note anonymous vs authenticated paths:
|
||||
- Marketing web routes: locale-prefixed group; auth pages gated by `guest`; contact/kontakt POST throttled; gift voucher print signed; profile/voucher-status require `auth`; marketing fallbacks render Inertia 404. Legacy unprefixed routes redirect to locale-prefixed equivalents.
|
||||
- Event Admin: `/event-admin` routes include auth/login/logout/dashboard and SPA catch-all; rely on controller auth checks (middleware not on route).
|
||||
- Guest PWA: view routes for gallery/event/share are unauthenticated; token patterns unconstrained except share slug regex.
|
||||
- Checkout: purchase-wizard/checkout routes toggled by `config('checkout.enabled')`; login/register/track-abandoned POSTs exposed; Paddle webhook route has no rate limit middleware.
|
||||
- Public API: `api/v1` marketing coupon/gift voucher endpoints throttled (`throttle:*`), RevenueCat webhook throttled `60,1`. Public event/gallery endpoints grouped under `throttle:100,1`; signed URLs for share assets/downloads; uploads exposed at `/events/{token}/upload` and `/photobooth/sparkbooth/upload`.
|
||||
- Tenant API: `auth:sanctum`, `tenant.collaborator`, `tenant.isolation`, `throttle:tenant-api` on `/api/v1/tenant/*`; many routes further gated by `tenant.admin`; package/credit checks on event mutations; signed download/layout routes within tenant scope.
|
||||
- [ ] Review controllers/resources for authz (policies/gates), FormRequest validation, mass assignment, IDOR risks.
|
||||
- [ ] Check response handling (error leakage, pagination limits, idempotency on mutations).
|
||||
- [ ] Review CSP/headers/cookies and analytics gating; verify no `unsafe-inline` without nonce/hash plan.
|
||||
|
||||
3) Guest PWA
|
||||
- [ ] Verify join token handling (hashing/migration alignment with `SEC-GT-*`), gallery/photo rate limits, throttling per token/IP.
|
||||
- [ ] Inspect upload validation (MIME/size/dimensions), background sync request signing, storage visibility.
|
||||
- [ ] Audit service worker scope, cache versioning/poisoning risk, offline fallbacks, and CSP for PWA.
|
||||
|
||||
4) Event Admin (Filament + React Admin)
|
||||
- [ ] Audit Filament resources/actions for policy checks, scoping, mass assignment guards.
|
||||
- [ ] Confirm OAuth2/PKCE + Sanctum session handling, role checks, impersonation/tenant boundary controls.
|
||||
- [ ] Review file handling inside admin (imports/exports/PDF/QR) for SSRF/path traversal.
|
||||
|
||||
5) Payments & Webhooks
|
||||
- [ ] Validate Paddle/RevenueCat webhook signature verification, timestamp/replay defense, idempotency locks, queueing.
|
||||
- [ ] Check linkage between webhooks and checkout/session state; ensure failures alert and redact PII.
|
||||
|
||||
6) Media Pipeline & Storage
|
||||
- [ ] Confirm AV/EXIF scanning coverage, checksum verification, and private visibility defaults.
|
||||
- [ ] Review signed URL usage/expiry, path traversal protections, and storage bucket separation per tenant.
|
||||
|
||||
7) Dynamic Testing
|
||||
- [ ] Set up test identities (guest token, tenant admin, super admin) and auth contexts for tooling.
|
||||
- [ ] Run targeted DAST/Playwright flows for each surface (authn/z, uploads, rate limiting, CORS preflight).
|
||||
- [ ] Fuzz uploads (images/metadata) and verify rejection paths + logging.
|
||||
|
||||
## Evidence & Logging
|
||||
- Log session notes and findings in `docs/process/changes/YYYY-MM-DD-security-review-*.md`.
|
||||
- Update checklist statuses here after each pass.
|
||||
- Open issues for remediation items, linking back to findings and relevant `SEC-*` tickets.
|
||||
@@ -100,40 +100,6 @@ const sidebars = {
|
||||
],
|
||||
},
|
||||
|
||||
// Prozesse, Roadmap, Changes
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Prozess & Roadmap',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'process/README',
|
||||
'process/roadmap',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'TODO / Epics',
|
||||
items: [
|
||||
'process/todo/security-hardening-epic',
|
||||
'process/todo/paddle-migration',
|
||||
'process/todo/paddle-catalog-sync',
|
||||
'process/todo/localized-seo-hreflang-strategy',
|
||||
'process/todo/media-streaming-upload-refactor',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Changes',
|
||||
items: [
|
||||
'process/changes/2025-09-08-session',
|
||||
'process/changes/2025-10-02-registration-role-fixes',
|
||||
'process/changes/2025-10-05-checkout-refactor-todo',
|
||||
'process/changes/2025-10-09-paypal-sdk-migration',
|
||||
'process/changes/2025-10-10-tenant-admin-onboarding-plan',
|
||||
'process/changes/2025-11-08-coupon-ops',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Testing / Qualität
|
||||
{
|
||||
type: 'category',
|
||||
|
||||
Reference in New Issue
Block a user