Konzept: Weitere Core/Client Erweiterungs-Patterns¶
Stand: März 2026
Status: Entwurf
Bereits umgesetzt¶
| Bereich | Pattern | Beschreibung |
|---|---|---|
| Flutter/Dart | Git-Dependency + ClientConfig | Core-Packages via pubspec.yaml, 50+ Override-Punkte |
| Firestore Rules | _core + _extra Merge |
Core-Regeln + Client-Erweiterungen, gemerged beim Deploy |
| Storage Rules | _core + _extra Merge |
Identisch zu Firestore Rules |
| Firestore Indexes | _core + _extra Merge |
JSON-Array-Merge via Node.js |
| Cloud Functions | Merge-at-Deploy | Core + Client Jobs/Connectors/Triggers in einer Codebase |
| CI/CD | Reusable Workflows + Pull-Modell | Core stellt client-build-*.reusable.yml / client-deploy-*.reusable.yml bereit; Clients ziehen Updates via core:upgrade |
Vorschlag 1: Unified Deploy Script (deploy_all.sh)¶
Problem¶
Aktuell existieren 3 separate Deploy-Scripts im Client-Repo:
deploy_rules.sh → Firebase Rules + Indexes
deploy_functions.sh → Cloud Functions (Merge-at-Deploy)
deploy_cors.sh → CORS auf Storage Bucket
Plus Hosting-Deploy in auto-deploy.yml (CI) oder manuell via Firebase CLI. Bei einem vollständigen Redeploy muss man alles einzeln ausführen und die Reihenfolge kennen.
Lösung¶
Ein deploy_all.sh das alle Schritte orchestriert:
Ablauf:
1. Rules deployen (deploy_rules.sh)
2. CORS deployen (deploy_cors.sh)
3. Functions deployen (deploy_functions.sh)
4. Hosting deployen (flutter build web + firebase deploy --only hosting)
Vorteile:
- Ein Befehl für alles → weniger Fehler
- Richtige Reihenfolge garantiert (Rules vor Functions, da Triggers auf Rules-Änderungen reagieren können)
- Skip-Flags für partielle Deploys
- Ideal nach Core-Update: ./deploy_all.sh gemuesebau-steiner-dev
Aufwand: Gering (~80 Zeilen Bash)
Priorität: ⭐⭐⭐ Hoch
Vorschlag 2: CI/CD Workflow als Reusable Workflow¶
Status: ✅ Umgesetzt (siehe Tabelle oben).
Core stellt Reusable Workflows bereit (
client-build-{web,android,ios}.reusable.yml,client-deploy-{web,android,ios}.reusable.yml,ci-test-flutter.reusable.yml). Client-Repos rufen sie viaworkflow_callaus ihren Orchestratoren auf (client-auto-build.yml,promote-to-prod.yml,client-ci.yml).Trigger-Modell: Pull. Clients holen Core-Updates per
core:upgrade-Befehl; keinrepository_dispatchvom Core mehr. Spezifikation: Release-Gesamtkonzept.
Vorschlag 3: CORS _core + _extra Merge¶
Problem¶
Aktuell pflegt jeder Client seine CORS-Konfiguration komplett selbst (firebase/cors.dev.json, firebase/cors.prod.json). Wenn Core neue Response-Headers oder Methoden hinzufügt, müssen alle Clients manuell aktualisiert werden.
Ist-Zustand¶
// Client cors.dev.json — vollständig self-managed
[{
"origin": ["http://localhost:8080", "https://gemuesebau-steiner-dev.web.app", ...],
"method": ["GET", "HEAD", "PUT", "POST", "DELETE", "OPTIONS"],
"responseHeader": ["Content-Type", "Authorization", "X-Requested-With"],
"maxAgeSeconds": 3600
}]
Lösung: Merge-Pattern wie bei Rules¶
Client-Struktur:
firebase/
cors_core.dev.json ← Wird beim Core-Update automatisch aktualisiert
cors_core.prod.json ← Wird beim Core-Update automatisch aktualisiert
cors_extra.dev.json ← Client-spezifische Erweiterungen
cors_extra.prod.json ← Client-spezifische Erweiterungen
cors.dev.json ← GENERIERT (gitignored)
cors.prod.json ← GENERIERT (gitignored)
Core liefert Standard-Config:
// cors_core.dev.json
[{
"origin": ["http://localhost:8080", "http://localhost:8081"],
"method": ["GET", "HEAD", "PUT", "POST", "DELETE", "OPTIONS"],
"responseHeader": ["Content-Type", "Authorization", "X-Requested-With", "Accept", "Origin"],
"maxAgeSeconds": 3600
}]
Client fügt nur eigene Origins hinzu:
// cors_extra.dev.json
{
"extraOrigins": [
"https://gemuesebau-steiner-dev.web.app",
"https://gemuesebau-steiner-dev.firebaseapp.com"
]
}
Merge-Logik (in deploy_cors.sh):
# Core-Origins + Client-Origins zusammenführen
node -e "
const core = require('./$CORS_CORE');
const extra = require('./$CORS_EXTRA');
core[0].origin = [...core[0].origin, ...(extra.extraOrigins || [])];
if (extra.extraHeaders) core[0].responseHeader.push(...extra.extraHeaders);
console.log(JSON.stringify(core, null, 2));
" > "$CORS_OUTPUT"
Vorteile: - Core kann Methods/Headers aktualisieren → alle Clients bekommen es - Client muss nur seine eigenen Hosting-URLs pflegen - Gleicher Pattern wie Rules → vertrautes Konzept
Aufwand: Gering (~30 Zeilen Merge-Logik)
Priorität: ⭐⭐ Mittel
Vorschlag 4: Feature-Flag Defaults aus dem Core¶
Problem¶
firebase_config_*.json (pro Client/Environment) enthält Feature-Flags. Aktuell definiert jeder Client alle Features selbst. Wenn Core ein neues Feature einführt (z.B. advanced_search: true), muss jeder Client manuell aktualisiert werden.
Ist-Zustand¶
// Client: erp/assets/firebase_config/firebase_config_development.json
{
"apiKey": "...",
"projectId": "gemuesebau-steiner-dev",
"storageBucket": "...",
"cloudFunctionsRegion": "europe-west3"
}
Features werden aktuell über ClientConfig.features in Dart gesetzt — kein zentraler Config-Mechanismus.
Lösung: Feature-Defaults vom Core + Client-Overrides¶
Core stellt Default-Features bereit:
// core/shared/assets/default_features.json
{
"order_export": true,
"article_import": true,
"customer_import": true,
"advanced_search": true,
"stock_management": true,
"multi_warehouse": false,
"invoice_generation": false,
"shop_system": true
}
Client überschreibt nur Abweichungen:
// Client: erp/assets/firebase_config/feature_overrides.json
{
"multi_warehouse": true,
"shop_system": false,
"custom_client_feature": true
}
Merge-Logik (im Dart-Code beim App-Start):
// In AppConfig oder ClientConfig
Map<String, bool> get mergedFeatures {
final defaults = json.decode(rootBundle.loadString('assets/default_features.json'));
final overrides = json.decode(rootBundle.loadString('assets/feature_overrides.json'));
return {...defaults, ...overrides}; // Client gewinnt bei Konflikten
}
Vorteile:
- Neue Core-Features sind sofort für alle Clients verfügbar
- Clients aktivieren/deaktivieren nur was sie brauchen
- Ein Blick auf feature_overrides.json zeigt sofort Client-Anpassungen
- Keine Dart-Code-Änderung im Client nötig für Feature-Toggles
Aufwand: Gering (eine JSON-Datei im Core, Merge-Logik ~20 Zeilen Dart)
Priorität: ⭐⭐ Mittel
Vorschlag 5: Hosting Security Headers _core + _extra¶
Problem¶
firebase.json im Client enthält Hosting-Konfiguration mit Security-Headers (CSP, HSTS, X-Frame-Options etc.). Wenn Core einen Header aktualisiert (z.B. neue CSP-Directive), müssen alle Clients ihre firebase.json manuell anpassen.
Ist-Zustand¶
// Client: firebase/firebase.json
{
"hosting": {
"public": "../erp/build/web",
"rewrites": [{"source": "**", "destination": "/index.html"}]
}
}
Aktuell hat der Client minimale Headers. Core hat umfangreichere.
Lösung: firebase.json Generierung beim Deploy¶
Core liefert Standard-Hosting-Config:
// firebase_hosting_core.json
{
"headers": [
{
"source": "**",
"headers": [
{"key": "X-Frame-Options", "value": "DENY"},
{"key": "X-Content-Type-Options", "value": "nosniff"},
{"key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains"},
{"key": "Referrer-Policy", "value": "strict-origin-when-cross-origin"},
{"key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()"}
]
}
]
}
Client kann Headers ergänzen oder überschreiben:
// firebase_hosting_extra.json
{
"extraHeaders": [
{"key": "X-Custom-Header", "value": "gemuesebau-steiner"}
],
"overrideHeaders": {
"Permissions-Policy": "camera=(self), microphone=(), geolocation=()"
}
}
Deploy-Script merged Core + Extra → finale firebase.json.
Vorteile: - Security-Best-Practices zentral im Core - Client kann Client-spezifische Headers ergänzen (z.B. CSP für externe Dienste) - Neue Security-Headers wirken automatisch
Aufwand: Mittel (JSON-Merge-Logik + Deploy-Script-Anpassung)
Priorität: ⭐ Niedrig (erst relevant wenn Core komplexere Headers einführt)
Priorisierte Roadmap¶
| Prio | Vorschlag | Aufwand | Nutzen |
|---|---|---|---|
| 1 | Unified Deploy Script | Gering | Sofort nutzbar, weniger Fehler |
| 2 | CI/CD Reusable Workflow | Mittel | Keine manuelle CI-Pflege pro Client |
| 3 | CORS Merge | Gering | Konsistente CORS-Updates |
| 4 | Feature-Flag Defaults | Gering | Neue Features automatisch verfügbar |
| 5 | Hosting Headers Merge | Mittel | Security-Updates automatisch |
Empfehlung¶
Sofort umsetzen (Quick Wins): - Vorschlag 1 (deploy_all.sh) — am meisten praktischer Nutzen im Alltag - Vorschlag 3 (CORS Merge) — gleicher bewährter Pattern wie Rules
Nächste Iteration: - Vorschlag 2 (Reusable Workflow) — größter langfristiger Wartungs-Vorteil - Vorschlag 4 (Feature-Flag Defaults) — sinnvoll sobald Feature-Anzahl wächst
Bei Bedarf: - Vorschlag 5 (Hosting Headers) + Vorschlag 6 (Cloud Tasks)