docs: record verified local FCM setup and E2E test

This commit is contained in:
2026-09-15 11:23:17 +02:00
parent c4a84ec135
commit 59e9299883
4 changed files with 42 additions and 27 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ GITEA_TOKEN=
GITEA_OWNER=kai GITEA_OWNER=kai
GITEA_REPO=pingu-concerts GITEA_REPO=pingu-concerts
# Server push: keep disabled until a dedicated TEST service account is mounted. # Server push defaults to off; enable only in a local/test environment with the dedicated TEST service account mounted.
PUSH_ENABLED=false PUSH_ENABLED=false
FIREBASE_PROJECT_ID= FIREBASE_PROJECT_ID=
# Only needed with: docker compose -f compose.yml -f compose.push.yml ... # Only needed with: docker compose -f compose.yml -f compose.push.yml ...
+26 -17
View File
@@ -1,42 +1,51 @@
# ChatGPT-Prompt: Firebase-Zugang für MetalCircle # ChatGPT-Prompt: Firebase-E2E-Wiederholung für MetalCircle
Den folgenden Prompt in einen neuen Chat kopieren. Keine Secret-Dateien mitgeben. Den folgenden Prompt in einen neuen Chat kopieren. Keine Secret-Dateien mitgeben.
```text ```text
Hilf mir Schritt für Schritt, den serverseitigen Firebase-Zugang für MetalCircle Hilf mir, den bereits eingerichteten serverseitigen Firebase-Zugang für MetalCircle
im Entwicklungs-/Testbetrieb einzurichten. Verwende aktuelle offizielle im lokalen Entwicklungs-/Testbetrieb zu prüfen oder den lokalen FCM-E2E-Test zu
Firebase-/Google-Cloud-Dokumentation und erkläre mir die Console-Bedienung. wiederholen. Verwende aktuelle offizielle Firebase-/Google-Cloud-Dokumentation,
falls IAM-Fehler untersucht werden müssen.
Ausgangslage: Ausgangslage:
- Privates Projekt MetalCircle, Repository historisch kai/pingu-concerts. - Privates Projekt MetalCircle, Repository historisch kai/pingu-concerts.
- Android: Capacitor 6, Package ID dauerhaft de.pinguholic.concerts. - Android: Capacitor 6, Package ID dauerhaft de.pinguholic.concerts.
- Firebase-Anzeigename MetalCircle; die tatsächliche Projekt-ID muss ich prüfen. - Firebase-Projekt-ID: `metalcircle-30d9b`.
- Android-google-services.json ist vorhanden. Tokenregistrierung und manuelle - Android-google-services.json ist vorhanden. Tokenregistrierung und manuelle
Firebase-Testnachrichten/Kampagnen funktionieren bereits. Firebase-Testnachrichten/Kampagnen funktionieren bereits.
- Backend: FastAPI, PostgreSQL, Docker Compose, firebase-admin Python 7.1.0. - Backend: FastAPI, PostgreSQL, Docker Compose, firebase-admin Python 7.1.0.
- Pushs für Freundschaftsanfragen, Direktnachrichten und Einladungen sind implementiert. - Pushs für Freundschaftsanfragen, Direktnachrichten und Einladungen sind implementiert.
Kategorien und DE/EN werden pro Empfänger beachtet; Nachrichteninhalt bleibt privat. Kategorien und DE/EN werden pro Empfänger beachtet; Nachrichteninhalt bleibt privat.
- Versand ist standardmäßig deaktiviert und wurde mit simuliertem Firebase getestet. - Lokaler Versand wurde mit einem echten Android-Gerät über FCM HTTP v1 erfolgreich
getestet. Falls der HTTP-403 `PERMISSION_DENIED` erneut auftritt, wurde für den
dedizierten Test-Service-Account diese Rolle als erforderlich bestätigt:
`roles/firebasecloudmessaging.admin` (Firebase Cloud Messaging API Admin).
- Der lokale Service Account ist
`metalcircle-push-local@metalcircle-30d9b.iam.gserviceaccount.com`.
- Die Service-Account-Datei wird lokal schreibgeschützt als
`/run/secrets/firebase-service-account.json` eingebunden.
Bitte begleite mich bei: Bitte begleite mich bei:
1. Auswahl des Projekts und Ermittlung der tatsächlichen Projekt-ID. 1. Den bestehenden Projekt-, Service-Account- und read-only-Mount-Status anhand
2. Prüfung/Aktivierung der Firebase Cloud Messaging API HTTP v1. ungefährlicher Metadaten prüfen; keine neue Rolle oder Schlüsseldatei anlegen.
3. Einem eigenen Test-Service-Account, z. B. metalcircle-push-test, mit den für FCM 2. Nur bei einem erneuten Versandfehler die FCM HTTP-v1-Aktivierung und die
nötigen Rechten. Prüfe roles/firebasecloudmessaging.admin bzw. Zuweisung von `roles/firebasecloudmessaging.admin` für genau diesen lokalen
cloudmessaging.messages.create. Kein persönliches Admin-Konto verwenden. Service Account im Projekt `metalcircle-30d9b` prüfen.
4. Erstellung und sicherer Ablage der Service-Account-JSON außerhalb von Repository 3. Lokale `.env`-Konfiguration nur auf gesetzte Werte prüfen, nie Inhalte ausgeben:
und Docker-Buildkontext. Nur der Betreiber soll die Datei lesen können.
5. Lokaler .env-Konfiguration:
PUSH_ENABLED=true PUSH_ENABLED=true
FIREBASE_PROJECT_ID=<echte Projekt-ID> FIREBASE_PROJECT_ID=<echte Projekt-ID>
FIREBASE_SERVICE_ACCOUNT_FILE=<absoluter Pfad zur Secret-Datei> FIREBASE_SERVICE_ACCOUNT_FILE=<absoluter Pfad zur Secret-Datei>
6. Start mit compose.yml plus compose.push.yml. Dieses Override mountet die Datei 4. Lokaler Start mit `compose.yml` plus `compose.push.yml`. Dieses Override mountet die Datei
read-only unter /run/secrets/firebase-service-account.json und setzt im Backend read-only unter /run/secrets/firebase-service-account.json und setzt im Backend
GOOGLE_APPLICATION_CREDENTIALS auf diesen Pfad. GOOGLE_APPLICATION_CREDENTIALS auf diesen Pfad.
Lokal HTTP: COOKIE_SECURE=false docker compose -f compose.yml -f compose.push.yml up -d --build web Lokal HTTP: COOKIE_SECURE=false docker compose -f compose.yml -f compose.push.yml up -d --build web
Auf einem HTTPS-Testserver bleibt COOKIE_SECURE=true. Auf einem HTTPS-Testserver bleibt COOKIE_SECURE=true.
7. End-to-End-Test mit zwei Testkonten: Anfrage, Nachricht, Veranstaltungseinladung, 5. Falls erforderlich, gezielten lokalen E2E-Test mit Testkonten ausführen:
DE/EN, Kategorien, Antippen, Logout und Benutzerwechsel. Freundschaftsanfrage, Nachricht, Veranstaltungseinladung und echter Android-
Empfang. Bei erneutem HTTP 403 zuerst die bereinigte Fehlerantwort, Zielprojekt,
aktive Service-Account-Identität und Projektrollen prüfen; bei Erfolg keine
unnötigen Tests, Builds oder Cloud-Änderungen ausführen.
Grenzen: Grenzen:
- Niemals Schlüssel, Tokens, vollständige .env oder JSON-Inhalte im Chat anfordern. - Niemals Schlüssel, Tokens, vollständige .env oder JSON-Inhalte im Chat anfordern.
+11 -7
View File
@@ -7,12 +7,12 @@ Das Firebase-Projekt heißt **MetalCircle**. Android ist dauerhaft als `de.pingu
- `android/android/app/google-services.json`: lokale, Git-ignorierte Android-Client-Konfiguration. Projekt-/App-Kennungen und der Client-API-Key werden vom Build in die APK übernommen; sie sind kein Backend-Privatschlüssel. - `android/android/app/google-services.json`: lokale, Git-ignorierte Android-Client-Konfiguration. Projekt-/App-Kennungen und der Client-API-Key werden vom Build in die APK übernommen; sie sind kein Backend-Privatschlüssel.
- **Service-Account-JSON**: privater Schlüssel für das Backend. Niemals in Git, APK, Docker-Image, Webassets, Chat, Wiki oder Logs aufnehmen. Die Android-Datei ersetzt diesen Zugang nicht. - **Service-Account-JSON**: privater Schlüssel für das Backend. Niemals in Git, APK, Docker-Image, Webassets, Chat, Wiki oder Logs aufnehmen. Die Android-Datei ersetzt diesen Zugang nicht.
## Entwicklung/Test einrichten ## Lokale Entwicklungs-/Testumgebung
1. In Firebase **MetalCircle** auswählen und die tatsächliche **Projekt-ID** notieren; sie kann vom Anzeigenamen abweichen. 1. In Firebase **MetalCircle** auswählen und die tatsächliche **Projekt-ID** notieren; sie kann vom Anzeigenamen abweichen.
2. In der zugehörigen Google Cloud Console die **Firebase Cloud Messaging API (HTTP v1)** prüfen/aktivieren. 2. In der zugehörigen Google Cloud Console die **Firebase Cloud Messaging API (HTTP v1)** prüfen/aktivieren.
3. Einen eigenen Test-Service-Account anlegen, z. B. `metalcircle-push-test`. Für Versand ist `cloudmessaging.messages.create` nötig, enthalten in **Firebase Cloud Messaging API Admin** (`roles/firebasecloudmessaging.admin`). Keine persönlichen oder Gitea-Zugänge verwenden. Siehe [Firebase IAM](https://firebase.google.com/docs/projects/iam/permissions) und [FCM-Rollen](https://docs.cloud.google.com/iam/docs/roles-permissions/firebasecloudmessaging). 3. Der lokale Test verwendet den dedizierten Service Account `metalcircle-push-local@metalcircle-30d9b.iam.gserviceaccount.com`. Für dessen Versand ist die Projektrolle **Firebase Cloud Messaging API Admin**, Rollen-ID `roles/firebasecloudmessaging.admin`, erforderlich. Diese genaue Rolle ist diesem lokalen Test-Service-Account auf Projektebene im Projekt `metalcircle-30d9b` zugewiesen. Sie enthält `cloudmessaging.messages.create`. Nicht mit ähnlich benannten Firebase-Administrationsrollen verwechseln; OAuth-Tokenbezug allein beweist keine Versandberechtigung. Keine persönlichen oder Gitea-Zugänge verwenden. Siehe [Firebase IAM](https://firebase.google.com/docs/projects/iam/permissions) und [FCM-Rollen](https://docs.cloud.google.com/iam/docs/roles-permissions/firebasecloudmessaging).
4. Für diesen Account einen JSON-Schlüssel erstellen und geschützt **außerhalb des Repositories und Docker-Buildkontexts** speichern. Der Betreiber verwaltet den Schlüssel. [Firebase Admin Setup](https://firebase.google.com/docs/admin/setup) beschreibt Service-Account-Dateien. 4. Den privaten JSON-Schlüssel geschützt **außerhalb des Repositories und Docker-Buildkontexts** speichern. Der Betreiber verwaltet die Datei. [Firebase Admin Setup](https://firebase.google.com/docs/admin/setup) beschreibt Service-Account-Dateien.
5. Dateirechte einschränken, beispielsweise `chmod 600 /absoluter/pfad/firebase-service-account.json`. Keine Inhalte ausgeben. 5. Dateirechte einschränken, beispielsweise `chmod 600 /absoluter/pfad/firebase-service-account.json`. Keine Inhalte ausgeben.
6. In der lokalen `.env` die folgenden Werte selbst eintragen: 6. In der lokalen `.env` die folgenden Werte selbst eintragen:
@@ -28,12 +28,16 @@ FIREBASE_SERVICE_ACCOUNT_FILE=/absoluter/pfad/firebase-service-account.json
COOKIE_SECURE=false docker compose -f compose.yml -f compose.push.yml up -d --build web COOKIE_SECURE=false docker compose -f compose.yml -f compose.push.yml up -d --build web
``` ```
`compose.push.yml` bindet die Datei schreibgeschützt unter `/run/secrets/firebase-service-account.json` ein und setzt dort `GOOGLE_APPLICATION_CREDENTIALS` für das Backend. Die Quelldatei muss existieren. Der Sender prüft, dass `FIREBASE_PROJECT_ID` zum Account passt. Die Android-App muss dasselbe Firebase-Projekt nutzen. `compose.push.yml` liest `FIREBASE_SERVICE_ACCOUNT_FILE` als absoluten Host-Pfad, bindet diese Datei **read-only** unter `/run/secrets/firebase-service-account.json` in den `web`-Container ein und setzt `GOOGLE_APPLICATION_CREDENTIALS=/run/secrets/firebase-service-account.json`. Die Quelldatei muss existieren. Der Sender prüft, dass `FIREBASE_PROJECT_ID` zur Projekt-ID des Credentials passt. Die Android-App muss dasselbe Firebase-Projekt verwenden. Schlüsseldatei, `.env` und Token gehören weder ins Repository noch in ein Image.
Cloud-Staging richtet der Betreiber separat ein; dort hinter HTTPS `COOKIE_SECURE=true` lassen. Codex auf PinguCore greift nicht automatisch darauf zu. Produktion bekommt später eigene Credentials, keine kopierten Testschlüssel. Cloud-Staging richtet der Betreiber separat ein; dort hinter HTTPS `COOKIE_SECURE=true` lassen. Codex auf PinguCore greift nicht automatisch darauf zu. Produktion bekommt später eigene Credentials, keine kopierten Testschlüssel.
## Prüfen ## Verifizierter lokaler E2E-Stand
Mit zwei Testkonten den Ablauf unter [Push Notifications](Push-Notifications.md) prüfen. Logs enthalten feste Kategorien wie `configuration`, `transient` oder `unregistered`. Bei `configuration` Mount, Projekt-ID, API-Aktivierung und Rechte prüfen. Keine Legacy-Server-Keys einsetzen. Am **15.09.2026** wurde der vollständige lokale Weg mit dem Android-Testgerät und dem lokalen Backend erfolgreich geprüft. Nach Zuweisung von `roles/firebasecloudmessaging.admin` verschwand der vorherige HTTP-403-Fehler `PERMISSION_DENIED`. Das Service-Account-Credential stimmte mit `FIREBASE_PROJECT_ID=metalcircle-30d9b` überein; der Firebase Admin SDK Versand wurde vom FCM HTTP-v1-Endpunkt angenommen.
Der echte Backend-Integrationstest steht aus, solange kein Test-Service-Account hinterlegt ist. Automatisierte Tests simulieren Firebase und bestätigen nicht die Berechtigungen eines künftig erstellten Accounts. Freundschaftsanfrage und Veranstaltungseinladung wurden im Android Notification Manager nachgewiesen. Die Direktnachrichten-Benachrichtigung wurde auf dem Gerät gesehen; Antippen öffnete den zugehörigen Chat. Alle drei Benachrichtigungen verwenden generische Vorschautexte ohne Nachrichtentext oder private Veranstaltungsdetails. Die installierte Test-App war `1.1.0-debug`, Package ID `de.pinguholic.concerts`.
Für eine Wiederholung lokale App und Backend verwenden; mit `adb reverse tcp:8080 tcp:8080` wird der Android-Testbuild an den lokalen Port 8080 weitergeleitet. Keine Cloud-Staging- oder Produktionsumgebung verwenden. In der Datenbank bedeutet `push_notifications.state='sent'`, dass der Firebase-Sendeaufruf angenommen wurde; für einen vollständigen E2E-PASS zusätzlich den tatsächlichen Android-Empfang über Notification Manager oder gleichwertige Gerätebeobachtung prüfen.
Automatisierte Backend-Tests simulieren Firebase und belegen nicht die Cloud-IAM-Berechtigung. Die lokale Suite mit 53 Tests und der Android-Debug-Build waren erfolgreich; der oben beschriebene Gerätetest hat zusätzlich den echten FCM-Versand und Empfang bestätigt. Bei erneutem `configuration`-/403-Fehler Projekt-ID, aktiven Service Account, dessen `roles/firebasecloudmessaging.admin`-Zuweisung im richtigen Firebase-Projekt, API-Aktivierung und Secret-Mount prüfen. Logs enthalten absichtlich keine vollständigen Firebase-Fehlerantworten oder Secrets. Keine Legacy-Server-Keys einsetzen.
+4 -2
View File
@@ -24,8 +24,10 @@ Aufträge verfallen nach einer Stunde; FCM erhält fünf Minuten Gültigkeit. De
Bereits zugestellte Meldungen lassen sich serverseitig nicht zurückrufen. Die App leert eigene Benachrichtigungen beim Sitzungswechsel; generische Texte und Zielprüfung schützen zusätzlich. Ein kleiner Zeitraum zwischen letzter Berechtigungsprüfung und Netzwerkzustellung bleibt technisch bestehen. Bereits zugestellte Meldungen lassen sich serverseitig nicht zurückrufen. Die App leert eigene Benachrichtigungen beim Sitzungswechsel; generische Texte und Zielprüfung schützen zusätzlich. Ein kleiner Zeitraum zwischen letzter Berechtigungsprüfung und Netzwerkzustellung bleibt technisch bestehen.
## Tests ## Tests und verifizierter Gerätetest
Automatisierte Tests nutzen isolierte lokale PostgreSQL-Schemas und simuliertes Firebase; sie senden keine echten Pushs. Nach der Zugangseinrichtung mit zwei Testkonten prüfen: Anfrage A → B, Freundschaft annehmen und Nachricht senden, private Veranstaltung mit Einladung für B; Vordergrund/Hintergrund, Antippen, EN/DE, Kategorien, Blockierung, entfernte Einladung sowie Logout/Benutzerwechsel. Keine Produktionsaktivitäten dafür verwenden. Automatisierte Tests nutzen isolierte lokale PostgreSQL-Schemas und simuliertes Firebase; sie senden keine echten Pushs. Sie prüfen unter anderem DE/EN, Kategorie-Abwahl, private Nachrichtentexte, Logout/Benutzerwechsel, Tokenwechsel, ungültige Tokens und Fehlerbehandlung.
Der echte lokale FCM-E2E-Test wurde am **15.09.2026** mit dem Android-Gerät und dem lokalen Backend erfolgreich abgeschlossen. Freundschaftsanfrage, Direktnachricht und Veranstaltungseinladung erreichten das Gerät. Freundschaftsanfrage und Einladung wurden im Android Notification Manager bestätigt; bei der Direktnachricht öffnete Antippen der Benachrichtigung den Chat. Die Push-Vorschauen blieben generisch. Für IAM, Firebase-Projekt und Secret-Mount siehe [Firebase](Firebase.md). Der Test fand lokal statt; Cloud-Staging und Produktion waren nicht betroffen.
Ein [fertiger ChatGPT-Prompt](Firebase-Setup-Prompt.md) begleitet die Einrichtung. Ein [fertiger ChatGPT-Prompt](Firebase-Setup-Prompt.md) begleitet die Einrichtung.