Files
FEDEO/push-server/README.md
flfeders 28c5e8511f
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
ci: central services images veröffentlichen
2026-08-02 17:23:30 +02:00

188 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 Lets-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 Lets 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`; Lets-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