Zum Inhalt

Client-Onboarding

Diese Seite beschreibt den vollständigen Prozess zum Anlegen eines neuen easySale-Kunden.

Das Onboarding ist vollständig automatisiert über Bash-Skripte im onboarding-cli/-Verzeichnis.

Aktueller Standard: Pull-Modell mit genau einem Firebase-Projekt pro Kunde (Production). create_client.sh erstellt Repo + Basisstruktur und installiert Workflows + DEPLOY_FIREBASE_SERVICE_ACCOUNT, CORE_REPO_PAT, FIREBASE_PROJECT und die Functions-Deploy-Basis. Mobile-Secrets danach über setup_github_secrets.sh --phase=<web|android|ios>.

CLI-Dispatcher: Alle Onboarding-Operationen sind alternativ über onboarding-cli/bin/easysale-cli erreichbar:

./onboarding-cli/bin/easysale-cli --help
./onboarding-cli/bin/easysale-cli client create
./onboarding-cli/bin/easysale-cli client phase web --slug <slug>
./onboarding-cli/bin/easysale-cli client status --slug <slug>

Struktur seit Refactor: Alle Step-Funktionen liegen unter onboarding-cli/lib/steps/ mit sprechenden Dateinamen (keine Nummern-Präfixe mehr). Die Ablauf-Logik von create_client.sh ist in onboarding-cli/lib/phases/p1_backend_web.sh (Phase 1: Backend + Web live) gekapselt. Phasen iOS/Android laufen über setup_github_secrets.sh --phase=<ios|android>.

Team-Shared State (neu): Beim Onboarding wird zusätzlich zu ~/.easysale/onboarding-state/<slug>/state.env eine nicht-sensitive Datei im Client-Repo geschrieben: onboarding/project.env. Dadurch können andere Mitarbeiter nach Repo-Clone Phasen direkt ausführen, auch ohne lokalen Vorlauf-State.

Bestehende Projekte bearbeiten (neu): Der interaktive Modus listet Client-Repos zusätzlich direkt aus GitHub (Tech-Schuppen/easysale-client-*). Wird ein nicht lokal vorhandenes Repo gewählt, klont die CLI es automatisch und lädt den Kontext aus onboarding/project.env oder .firebaserc.

Automatische Owner-Rechte (neu): In Phase 1 werden Eigentümerrechte für die drei Hauptnutzer gesetzt. - Firebase-Projekt: IAM roles/owner - GitHub-Organisation: default_repository_permission=admin (org-weit)


Voraussetzungen

Folgende Tools müssen lokal installiert und konfiguriert sein:

Tool Verwendung
Firebase CLI Firebase-Projekt erstellen, Rules/Functions deployen
GitHub CLI (gh) Repo erstellen, Secrets setzen, Workflows installieren
Flutter SDK App-Konfiguration validieren
Node.js / npm Cloud Functions deployen
gsutil / gcloud CORS auf Firebase Storage setzen

Außerdem benötigt: - Zugang zur GitHub Organisation Tech-Schuppen (Owner) - Firebase Billing-Account (für Cloud Functions) - Apple Developer Account (für iOS) - Google Play Console Zugang (für Android)


Pull-Modell (aktuell): Ein Firebase-Projekt pro Kunde (nur Production), Client pinnt Core-Version selbst und deployed manuell. Kurzanleitung: Neuen Client anlegen (Pull-Modell).

Onboarding starten

cd /path/to/easySale
./onboarding-cli/bin/easysale-cli client create

Das Skript ist interaktiv und fragt alle notwendigen Eingaben ab.
Einzelne Schritte können mit client step <name> ausgeführt werden:

./onboarding-cli/bin/easysale-cli client step icons
./onboarding-cli/bin/easysale-cli client step seed

Schritte im Detail

Das Onboarding besteht aus Repo-Erzeugung plus zentralem Deployment-Setup:

Phase 1: Infrastruktur erstellen

Schritt Name Beschreibung
01 Prerequisites Prüft alle Voraussetzungen (Tools, Zugänge)
02 Collect Inputs Fragt: Kundenname, Slug, Apps (ERP/Shop/beide), Environments
03 Client Structure Erstellt Verzeichnisstruktur im Client-Repo
04 Flutter ERP Richtet ERP Flutter-App ein (pubspec, firebase config)
05 Flutter Shop Richtet Shop Flutter-App ein (pubspec, firebase config)
06 VS Code Erstellt Multi-Root Workspace .code-workspace und launch.json
07 GitHub Repo Erstellt easysale-client-<slug> bei Tech-Schuppen
07a GitHub Repo Owners Setzt Admin-Rechte für Kern-Team auf dem neuen Client-Repo
08 App Icons Generiert App-Icons aus Kundenmaterial
09 Resend Email Konfiguriert Transaktions-E-Mail via Resend API
10 Firebase Project Erstellt Firebase-Projekt(e) (Dev + Prod)
10a Firebase Project Owners Setzt IAM Owner-Rechte für Kern-Team auf dem Firebase-Projekt
11 Firebaserc Erstellt .firebaserc mit Projekt-Aliases
12 Deploy Rules Merged Core + Client Firestore/Storage Rules und deployed
13 Deploy CORS Setzt CORS-Konfiguration auf Firebase Storage
14 Deploy Functions Merged Core + Client Functions und deployed
15 Cloud Tasks Richtet Cloud Tasks Queue ein
16 Deploy Hosting Baut Web-App und deployed auf Firebase Hosting
17 Admin Users Erstellt initiale Admin-Benutzer in Firebase Auth
18 App Store Config Konfiguriert Android (Play Console) + iOS (App Store Connect)
19 Legal Settings Setzt AGBs, Datenschutzerklärung, Impressum
20 Seed from Website Importiert initiale Stammdaten (optional)
21 Finalize GitHub Pusht alle Änderungen, erstellt initialen Release

Phase 2: Deployment-Setup

Schritt Name Beschreibung
01 Install Workflows Kopiert client-release.yml, client-ci.yml, client-release-handbook.yml
02 Android Secrets Keystore + Android-Secrets im Environment production setzen (prüft zuerst bestehende Repo-Secrets; fehlende Keystore-Passwörter/Alias werden lokal unter ~/.easysale/onboarding-state/<slug>/ gecached und bei Folge-Läufen wiederverwendet)
03 iOS App ID Bundle ID, Capabilities und Provisioning Profile im Apple Portal vorbereiten
04 iOS Secrets Zertifikat, Profile und App Store Connect Secrets setzen
05 Firebase Configs ERP_FIREBASE_CONFIG, SHOP_FIREBASE_CONFIG, ANDROID_SHOP_GOOGLE_SERVICES_JSON, IOS_SHOP_GOOGLE_SERVICE_INFO_PLIST setzen
06 Service Account Deploy-SA erstellen, DEPLOY_FIREBASE_SERVICE_ACCOUNT setzen, Secret-Manager-Basis vorbereiten
07 Release Preflight CORE_REPO_PAT validieren und FIREBASE_PROJECT setzen

Ergebnis

Nach dem erfolgreichen Onboarding existiert:

GitHub: Tech-Schuppen/easysale-client-<slug>
├── erp/                        ← Flutter ERP (Web + Mobile)
│   ├── pubspec.yaml            ← Git-Dependency auf Core-Tag
│   └── assets/firebase_config/ ← Firebase-Konfiguration
├── shop/ (optional)            ← Flutter Shop App
├── firebase/                   ← Optional: Client-spezifische Rules/Functions
├── .firebaserc                 ← Firebase-Projekt-Aliases
└── .github/
    └── workflows/
  ├── client-release.yml          ← manueller Web/Android/iOS/Firebase Release
  ├── client-ci.yml               ← Checks im Client-Repo
  └── client-release-handbook.yml ← Handbook-Deploy

Firebase Console:
└── <slug>-prod  ← Produktiv-Projekt

GitHub Actions:
└── `client-release.yml` fuehrt vor jedem Deploy einen harten Secret-/Variable-/Repo-Zugriffs-Preflight aus

Nachträgliche Konfiguration

Service Account Berechtigungen reparieren

Den Onboarding-Step erneut ausführen (idempotent, setzt alle IAM-Rollen + actAs-Berechtigungen für den GitHub-Deploy-SA):

./onboarding-cli/bin/easysale-cli client step firebase_project --slug <slug>

CORS manuell neu setzen

onboarding-cli/lib/ops/deploy_cors.sh <firebase-project-id>

Prod-Daten nach Dev synchronisieren

# Im Client-Repo:
gh workflow run sync-prod-to-dev.yml

Migration Bestandskunden vor 2026-06-01: ERP auf eigene Hosting-Site

Bis 2026-06-01 hat 16_deploy_hosting.sh ERP auf die Firebase-Default-Site (<project>.web.app) deployt. Seit dem Fix nutzt ERP eine eigene Site (<project>-erp.web.app), passend zur reCAPTCHA-Whitelist in 16_app_check.sh.

Bestandskunden, die vor diesem Datum aufgesetzt wurden, müssen einmalig migriert werden — sonst lehnt App Check alle Tokens ab (Domain-Mismatch zwischen reCAPTCHA-Whitelist <project>-erp.web.app und tatsächlich genutzter Default-Site).

# Pro Environment (dev/staging/prod) ausführen:
PROJECT_ID="<client>-prod"   # bzw. -dev / -staging

# 1. Neue ERP-Site anlegen
firebase hosting:sites:create "${PROJECT_ID}-erp" --project "$PROJECT_ID"

# 2. Target umhängen
cd <client-repo>/firebase
firebase target:apply hosting erp "${PROJECT_ID}-erp" --project "$PROJECT_ID"

# 3. Redeploy
cd <client-repo>
./deploy_hosting.sh <env>

# 4. Optional: Alte Default-Site deaktivieren (verhindert SEO-Indexierung leerer Seiten)
firebase hosting:disable --site "$PROJECT_ID" --project "$PROJECT_ID"

Migration Bestandskunden vor 2026-06-01: Storage-CORS für -erp Domain + localhost

Storage-CORS hatte vor 2026-06-01 weder die neue -erp.web.app Domain noch localhost in der Whitelist. Symptom: Bilder werden hochgeladen (Upload geht ohne Preflight), lassen sich aber im ERP nicht anzeigen (GET wird vom Browser CORS-geblockt).

# Im Core-Repo (regeneriert cors_core.<env>.json + cors_extra.<env>.json):
./onboarding-cli/bin/easysale-cli client step firebase_project --slug <slug>

# CORS auf den Bucket schieben (deploy_cors verifiziert Origins am Ende):
onboarding-cli/lib/ops/deploy_cors.sh <slug> <env>

Manuelle Verifikation (sollte access-control-allow-origin Header liefern):

PID="<client>-prod"
for ORIGIN in "https://${PID}-erp.web.app" "http://localhost:8080"; do
  echo "→ $ORIGIN"
  curl -sS -I -X OPTIONS \
    "https://firebasestorage.googleapis.com/v0/b/${PID}.firebasestorage.app/o" \
    -H "Origin: $ORIGIN" \
    -H "Access-Control-Request-Method: GET" \
    | grep -i "access-control-allow-origin" || echo "  ❌ kein Header"
done


Konfigurierbare Client-Einstellungen

Folgende Aspekte können durch das Client-Repo ohne Core-Änderungen angepasst werden:

Bereich Mechanismus Details
UI-Overrides ClientConfig Klasse Farben, Texte, Feature-Flags
Model-Erweiterungen CustomDataMixin Zusätzliche Felder
BLoC-Overrides Vererbung Eigene Business Logic
Firestore Rules _extra Merge Zusätzliche Sicherheitsregeln
Cloud Functions Merge-at-Deploy Eigene Cloud-Jobs/Triggers

Siehe Client Override System für Details.