All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 33s
Build and Push Docker Images / build-frontend (push) Successful in 18s
Build and Push Docker Images / build-website (push) Successful in 16s
Build and Push Docker Images / build-central-services-api (push) Successful in 38s
Build and Push Docker Images / build-central-services-admin (push) Successful in 1m0s
Build and Push Docker Images / build-docs (push) Successful in 17s
188 lines
6.1 KiB
Markdown
188 lines
6.1 KiB
Markdown
# 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-Instanzen
|
||
- `apps/admin`: Nuxt Admin Dashboard mit Nuxt UI
|
||
- `packages/db`: Drizzle Schema und Migrationen für PostgreSQL
|
||
- `docker-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
|
||
|
||
```bash
|
||
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 `80` und `443`
|
||
- 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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```env
|
||
OPENAI_API_KEY=...
|
||
GOCARDLESS_SECRET_ID=...
|
||
GOCARDLESS_SECRET_KEY=...
|
||
```
|
||
|
||
Ein Neustart nach Änderungen erfolgt mit:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```text
|
||
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`.
|
||
|
||
## 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:
|
||
|
||
```text
|
||
X-Fedeo-Instance-Id: inst_...
|
||
X-Fedeo-Timestamp: 2026-05-22T10:00:00.000Z
|
||
X-Fedeo-Signature: <hex-hmac>
|
||
```
|
||
|
||
Signiert wird:
|
||
|
||
```text
|
||
METHOD
|
||
PATH
|
||
TIMESTAMP
|
||
SHA256(BODY)
|
||
INSTANCE_ID
|
||
```
|
||
|
||
Beispiel:
|
||
|
||
```ts
|
||
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-config`
|
||
- `POST /v1/instances/heartbeat`
|
||
- `POST /v1/devices`
|
||
- `DELETE /v1/devices/:centralDeviceId`
|
||
- `POST /v1/push`
|
||
- `GET /v1/push/:deliveryJobId`
|
||
- `POST /v1/services/ai/chat-completions`
|
||
- `GET /v1/services/banking/institutions`
|
||
- `POST /v1/services/banking/requisitions`
|
||
- `GET /v1/services/banking/requisitions/:id`
|
||
- `GET /v1/services/banking/accounts/:id`
|
||
- `GET /v1/services/banking/accounts/:id/balances`
|
||
- `GET /v1/services/banking/accounts/:id/transactions`
|
||
|
||
Admin:
|
||
|
||
- `GET /admin/summary`
|
||
- `GET /admin/instances`
|
||
- `POST /admin/instances`
|
||
- `PATCH /admin/instances/:id`
|
||
- `POST /admin/instances/:id/rotate-secret`
|
||
- `GET /admin/instances/:id/devices`
|
||
- `GET /admin/instances/:id/jobs`
|
||
- `GET /admin/instances/:id/services`
|
||
- `PUT /admin/instances/:id/services/:service`
|
||
- `GET /admin/instances/:id/usage`
|
||
- `GET /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 `0` Einheiten und `0` Kosten 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:
|
||
|
||
```env
|
||
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`, `ios` und `android`
|
||
- 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
|