6.8 KiB
FEDEO Central Services
Eigenständiger Stack für zentrale FEDEO-Dienste. Neben Push können Selfhost-Instanzen darüber freigeschaltete und verbrauchsabhängig erfasste KI- und Banking-Dienste verwenden. Die Instanzen authentifizieren sich mit einem rotierbaren HMAC-Schlüssel, der im Admin-Dashboard gepflegt wird.
Bestandteile
apps/api: Fastify API für Admin-Dashboard und Selfhost-Instanzenapps/admin: Nuxt Admin Dashboard mit Nuxt UIpackages/db: Drizzle Schema und Migrationen für PostgreSQLdocker-compose.yml: produktiver Stack aus Traefik, Postgres, API und Admin
Provider-Schlüssel wie OPENAI_API_KEY und die GoCardless-Zugangsdaten liegen ausschließlich in diesem zentralen Stack. Selfhost-Instanzen erhalten nur Instanz-ID und Instanzschlüssel.
Entwicklung
cd push-server
cp .env.example .env
npm install
npm run db:migrate
npm run dev:api
npm run dev:admin
Lokale Entwicklungsports:
- API:
http://localhost:4020 - Admin:
http://localhost:3000 - Postgres:
localhost:5442
Öffentlicher Betrieb mit Traefik
Voraussetzungen:
- Docker Engine mit Docker-Compose-Plugin
- freie Ports
80und443 - A- beziehungsweise AAAA-Records für API- und Admin-Domain auf den Server
Der geführte Erststart erzeugt sichere lokale Schlüssel, bereitet den Let’s-Encrypt-Speicher vor und kann den Stack direkt starten:
cd push-server
chmod +x scripts/setup.sh
./scripts/setup.sh --start
Standardmäßig werden services.fedeo.de für die API und services-admin.fedeo.de für das Admin-Dashboard vorgeschlagen. Anschließend müssen die zentralen Provider-Zugangsdaten in .env gepflegt werden:
OPENAI_API_KEY=...
GOCARDLESS_SECRET_ID=...
GOCARDLESS_SECRET_KEY=...
Ein Neustart nach Änderungen erfolgt mit:
docker compose pull
docker compose up -d
docker compose ps
docker compose logs -f api
API und Admin werden als fertige Images aus der FEDEO-Registry geladen:
git.federspiel.tech/flfeders/fedeo/central-services-api:dev
git.federspiel.tech/flfeders/fedeo/central-services-admin:dev
Über FEDEO_CENTRAL_TAG kann in .env ein anderer Branch- oder Release-Tag gewählt werden. Auf dem Zielserver findet kein lokaler Image-Build statt.
Traefik leitet HTTP automatisch auf HTTPS um und bezieht Zertifikate per Let’s Encrypt TLS-Challenge. PostgreSQL besitzt keinen Host-Port und ist nur im internen Docker-Netz erreichbar. API und Admin werden ebenfalls nicht direkt über Host-Ports veröffentlicht.
Der API-Container wendet Datenbankmigrationen vor jedem Start automatisch an. PostgreSQL-Daten liegen im Volume push_postgres_data; Let’s-Encrypt-Daten liegen unter traefik/letsencrypt.
Traefik und Docker Engine 29
Die Compose-Datei setzt für den Traefik-Docker-Provider ausdrücklich DOCKER_API_VERSION=1.40. Neuere Docker-Engines lehnen ältere Client-Anfragen ab; ohne diese Einstellung meldet Traefik beispielsweise client version 1.24 is too old. Nach einem Update der Compose-Datei genügt:
docker compose pull
docker compose up -d --force-recreate traefik
docker compose logs --tail=50 traefik
Falls die API im Log bereits Server listening meldet, Compose sie aber als unhealthy einstuft, muss die aktuelle Compose-Datei verwendet werden. Der API-Healthcheck läuft mit Node gegen http://127.0.0.1:4020/health und benötigt kein zusätzliches wget im Image:
git pull
docker compose up -d --force-recreate api admin
docker compose ps
Admin-Zugang
Das Dashboard nutzt den Wert aus ADMIN_TOKEN. Der Token wird im Browser nur lokal gespeichert und als Authorization: Bearer ... an die API gesendet.
Instanz-Authentifizierung
Instanzaufrufe verwenden HMAC-SHA256:
X-Fedeo-Instance-Id: inst_...
X-Fedeo-Timestamp: 2026-05-22T10:00:00.000Z
X-Fedeo-Signature: <hex-hmac>
Signiert wird:
METHOD
PATH
TIMESTAMP
SHA256(BODY)
INSTANCE_ID
Beispiel:
import { createHash, createHmac } from "node:crypto";
const body = JSON.stringify(payload);
const timestamp = new Date().toISOString();
const bodyHash = createHash("sha256").update(body).digest("hex");
const canonical = ["POST", "/v1/push", timestamp, bodyHash, instanceId].join("\n");
const signature = createHmac("sha256", clientSecret).update(canonical).digest("hex");
Wichtige API-Endpunkte
GET /v1/public-configPOST /v1/instances/heartbeatPOST /v1/devicesDELETE /v1/devices/:centralDeviceIdPOST /v1/pushGET /v1/push/:deliveryJobIdPOST /v1/services/ai/chat-completionsGET /v1/services/banking/institutionsPOST /v1/services/banking/requisitionsGET /v1/services/banking/requisitions/:idGET /v1/services/banking/accounts/:idGET /v1/services/banking/accounts/:id/balancesGET /v1/services/banking/accounts/:id/transactions
Admin:
GET /admin/summaryGET /admin/instancesPOST /admin/instancesPATCH /admin/instances/:idPOST /admin/instances/:id/rotate-secretGET /admin/instances/:id/devicesGET /admin/instances/:id/jobsGET /admin/instances/:id/servicesPUT /admin/instances/:id/services/:serviceGET /admin/instances/:id/usageGET /admin/usage/summary
Freischaltung und Abrechnung
Die Dienste ai und banking sind für neue Instanzen standardmäßig gesperrt. Im Instanzdetail des Admin-Dashboards werden sie einzeln aktiviert. Pro Dienst können ein Monatslimit und ein Preis in Mikro-Euro je Einheit gepflegt werden.
- KI wird anhand der von OpenAI gemeldeten Gesamt-Token erfasst.
- Banking wird je erfolgreichem Provider-Aufruf erfasst.
- Fehlgeschlagene Aufrufe werden technisch protokolliert, aber mit
0Einheiten und0Kosten verbucht. - Usage Events enthalten technische Metadaten, aber keine Prompts, Bankumsätze oder sonstigen fachlichen Nutzdaten.
Apple Push Notification service
Für iOS müssen diese Werte gesetzt sein:
IOS_BUNDLE_ID=software.federspiel.fedeo
APNS_TEAM_ID=...
APNS_KEY_ID=...
APNS_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
APNS_PRODUCTION=false
Solange APNs nicht vollständig konfiguriert ist, nimmt die API Push-Aufträge an, markiert iOS-Zustellversuche aber mit apns_not_configured.
Aktueller Umfang
Implementiert:
- Instanzverwaltung im Admin-Dashboard
- rotierbare Instanzschlüssel mit verschlüsselter Speicherung
- HMAC-authentifizierte Instanzbefehle
- Geräte-Registry für
web,iosundandroid - Zustelljobs mit Idempotenzschlüssel
- APNs-Zustellung für iOS
- technische Status- und Fehlererfassung
- dienstbezogene Freischaltungen und Monatslimits
- unveränderliche Usage Events samt Kostenwert
- zentraler OpenAI- und GoCardless-Zugang
Vorbereitet, aber noch nicht vollständig implementiert:
- Web Push Zustellung
- FCM Zustellung
- asynchrone Queue/Worker-Verarbeitung
- produktive Rate-Limits pro Instanz
- Rechnungsstellung beziehungsweise Export an ein Buchhaltungssystem