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.sherstellt Repo + Basisstruktur und installiert Workflows +DEPLOY_FIREBASE_SERVICE_ACCOUNT,CORE_REPO_PAT,FIREBASE_PROJECTund die Functions-Deploy-Basis. Mobile-Secrets danach übersetup_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 voncreate_client.shist inonboarding-cli/lib/phases/p1_backend_web.sh(Phase 1: Backend + Web live) gekapselt. Phasen iOS/Android laufen übersetup_github_secrets.sh --phase=<ios|android>.Team-Shared State (neu): Beim Onboarding wird zusätzlich zu
~/.easysale/onboarding-state/<slug>/state.enveine 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 ausonboarding/project.envoder.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¶
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):
CORS manuell neu setzen¶
Prod-Daten nach Dev synchronisieren¶
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.