Files
FEDEO/push-server/README.md

152 lines
4.9 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`: lokaler Stack aus 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
```
Für den dauerhaften Betrieb:
```bash
cp .env.example .env
# .env mit sicheren Zugangsdaten und Provider-Schlüsseln befüllen
docker compose up -d --build
```
Der API-Container wendet Datenbankmigrationen vor jedem Start automatisch an. PostgreSQL-Daten liegen im Volume `push_postgres_data`. Für ein öffentliches Deployment müssen API und Admin hinter einem TLS-Reverse-Proxy betrieben und `PUBLIC_API_BASE_URL` auf die öffentliche API-Adresse gesetzt werden.
Standardports:
- API: `http://localhost:4020`
- Admin: `http://localhost:3000` lokal oder `http://localhost:3020` über Docker Compose
- Postgres: `localhost:5442`
## 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