docs: record verified local FCM setup and E2E test
This commit is contained in:
+1
-1
@@ -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 ...
|
||||||
|
|||||||
@@ -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
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user