Comprehensive guide (INTEGRATION.md) explaining how external container applications can integrate with the INSIGHT platform, including: - Docker network integration and service discovery - JWT authentication and token validation (RS256) - API endpoints and communication patterns - Traefik routing configuration - Database access via PgBouncer - Redis caching with namespace conventions - Frontend sidebar integration - Security requirements and checklist - Example docker-compose extension Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
23 KiB
INSIGHT MVP - Entwickler-Integrationshandbuch
Zielgruppe: Entwickler von Container-Anwendungen, die nahtlos in die INSIGHT-Plattform integriert werden sollen.
Version: 1.0.0-alpha | Stand: 2026-03-10
Inhaltsverzeichnis
- Ueberblick
- Architektur
- Docker-Integration
- Authentifizierung & Autorisierung
- API-Kommunikation
- Traefik-Routing (API Gateway)
- Datenbank-Anbindung
- Redis / Cache
- Frontend-Integration (Sidebar)
- Sicherheitsanforderungen
- Health-Checks & Monitoring
- Checkliste fuer neue Container-Apps
- Beispiel: docker-compose Erweiterung
1. Ueberblick
INSIGHT ist eine modulare Multi-Tenant-Plattform, die als Docker-Compose-Stack betrieben wird. Externe Container-Anwendungen koennen ueber folgende Wege integriert werden:
| Integrationsart | Beschreibung |
|---|---|
| API-Integration | REST-API-Aufrufe gegen den Core-Service |
| Sidebar-Link | Anwendung als externer Link im INSIGHT-Menue |
| Shared Authentication | JWT-basierte Authentifizierung (SSO) |
| Shared Database | Eigenes Schema in der gemeinsamen PostgreSQL-DB |
| Docker-Netzwerk | Direkter Zugriff auf interne Services |
2. Architektur
Internet / Intranet
|
[Traefik Gateway]
Port 80 (HTTP)
|
+------------+------------+
| | |
[Frontend] [Core-API] [Deine App]
React/Vite NestJS Container
Port 8080 Port 3000 Port XXXX
| | |
+-----+------+-----+------+
| |
[PostgreSQL] [Redis]
via PgBouncer Port 6379
Port 6432
Docker-Netzwerke
| Netzwerk | Typ | Zweck |
|---|---|---|
insight-web |
bridge | Traefik-Routing, oeffentliche APIs |
insight-db |
internal | PostgreSQL + PgBouncer (isoliert) |
insight-cache |
internal | Redis (isoliert) |
Wichtig:
insight-dbundinsight-cachesind alsinternalmarkiert und somit nicht von aussen erreichbar. Deine Anwendung muss explizit in diese Netzwerke eingebunden werden.
3. Docker-Integration
3.1 Netzwerk-Anbindung
Dein Container muss in die benoetigten Netzwerke eingebunden werden:
# In deiner docker-compose.yml oder als Erweiterung
services:
meine-app:
image: git.xinion.lan/gitadmin/insight-meine-app:latest
networks:
- insight-web # Pflicht: fuer Traefik-Routing
- insight-db # Optional: nur bei direktem DB-Zugriff
- insight-cache # Optional: nur bei Redis-Zugriff
labels:
- "traefik.enable=true"
# Routing-Labels (siehe Abschnitt 6)
networks:
insight-web:
external: true
insight-db:
external: true
insight-cache:
external: true
3.2 Container Registry
| Parameter | Wert |
|---|---|
| Registry-URL | git.xinion.lan |
| Image-Prefix | git.xinion.lan/gitadmin/insight-{name} |
| Authentifizierung | Forgejo Login-Credentials |
# Image bauen und pushen
docker build -t git.xinion.lan/gitadmin/insight-meine-app:latest .
docker push git.xinion.lan/gitadmin/insight-meine-app:latest
3.3 Service Discovery (DNS)
Innerhalb des Docker-Netzwerks sind Services ueber ihre Servicenamen erreichbar:
| Service | Hostname | Port | Netzwerk |
|---|---|---|---|
| Core-API | core |
3000 | insight-web |
| PostgreSQL | postgres |
5432 | insight-db |
| PgBouncer | pgbouncer |
6432 | insight-db |
| Redis | redis |
6379 | insight-cache |
| Frontend | frontend |
8080 | insight-web |
| Traefik | traefik |
80 | insight-web |
4. Authentifizierung & Autorisierung
4.1 JWT-Token-Architektur
INSIGHT verwendet RS256 (asymmetrische) JWT-Tokens:
| Token-Typ | Speicherort | Lebensdauer | Zweck |
|---|---|---|---|
| Access Token | Memory (Variable) | 15 Minuten | API-Authentifizierung |
| Refresh Token | HttpOnly Cookie | 7 Tage | Token-Erneuerung |
4.2 JWT-Payload-Struktur
{
"sub": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"role": "USER",
"tenantId": "...",
"tenantSlug": "tenant_acme",
"jti": "unique-token-id",
"iat": 1710000000,
"exp": 1710000900
}
Rollen:
| Rolle | Beschreibung |
|---|---|
PLATFORM_ADMIN |
Plattform-Administrator (voller Zugriff) |
TENANT_ADMIN |
Mandanten-Administrator |
USER |
Standard-Benutzer |
4.3 Token-Validierung in deiner Anwendung
Um eingehende Requests zu validieren, brauchst du den oeffentlichen JWT-Schluessel
(RS256 Public Key). Dieser liegt im Core-Service unter /app/keys/jwt-public.pem.
Option A: Public Key mounten (empfohlen)
# docker-compose.yml
services:
meine-app:
volumes:
- ./keys/jwt-public.pem:/app/keys/jwt-public.pem:ro
Dann in deiner Anwendung:
1. Lese den Public Key aus /app/keys/jwt-public.pem
2. Validiere den JWT aus dem Authorization-Header:
- Algorithmus: RS256
- Issuer: (optional, je nach Konfiguration)
- Pruefe exp (Ablaufzeit)
- Pruefe jti gegen Redis-Blocklist (optional, fuer Revocation)
3. Extrahiere sub (User-ID), role, tenantId aus dem Payload
Option B: API-Proxy (einfacher)
Leite Requests ueber den Core-Service und nutze dessen eingebaute JWT-Validierung:
Client -> Traefik -> Core-Service (validiert JWT) -> Deine App
4.4 Token-Revocation (optional)
Gesperrte Tokens werden in Redis unter dem Key-Pattern blocked_token:{jti}
gespeichert. Fuer Echtzeit-Revocation pruefe den jti-Claim gegen Redis:
Redis Key: blocked_token:{jti}
Redis Value: "1"
TTL: Restlaufzeit des Tokens
4.5 Login-Flow fuer externe Anwendungen
Benutzer oeffnet deine App (via INSIGHT Sidebar-Link)
|
v
Kein gueltiger Token vorhanden?
|
v
Redirect zu INSIGHT Login: http://{HOST}/login?redirect={DEINE_APP_URL}
|
v
Benutzer meldet sich an (E-Mail/Passwort oder Microsoft SSO)
|
v
INSIGHT setzt Tokens und redirectet zurueck zu deiner App
|
v
Deine App liest den Access Token und nutzt ihn fuer API-Calls
4.6 API-Endpunkte fuer Authentifizierung
| Methode | Endpunkt | Auth | Beschreibung |
|---|---|---|---|
| POST | /api/v1/auth/login |
Nein | Login (E-Mail + Passwort) |
| POST | /api/v1/auth/refresh |
Cookie | Token erneuern |
| POST | /api/v1/auth/logout |
Ja | Logout + Token-Revocation |
| GET | /api/v1/users/me |
Ja | Aktuelle User-Daten |
5. API-Kommunikation
5.1 Basis-URL
| Umgebung | Basis-URL |
|---|---|
| Entwicklung | http://172.20.10.59/api/v1 |
| Docker-intern | http://core:3000/api/v1 |
5.2 Request-Format
Alle API-Requests muessen folgende Header enthalten:
Authorization: Bearer <access_token>
Content-Type: application/json
X-Tenant-ID: <tenant-uuid> # Optional: fuer Mandanten-spezifische Operationen
X-Request-ID: <uuid> # Optional: fuer Request-Tracing
5.3 Verfuegbare API-Endpunkte
Benutzer-Verwaltung:
| Methode | Endpunkt | Rolle | Beschreibung |
|---|---|---|---|
| GET | /api/v1/users/me |
Alle | Eigene User-Daten |
| PATCH | /api/v1/users/me |
Alle | Eigene Daten aktualisieren |
| GET | /api/v1/users |
PLATFORM_ADMIN | Alle User auflisten |
| POST | /api/v1/users |
PLATFORM_ADMIN | User anlegen |
| PATCH | /api/v1/users/:id |
PLATFORM_ADMIN | User bearbeiten |
Mandanten (Tenants):
| Methode | Endpunkt | Rolle | Beschreibung |
|---|---|---|---|
| GET | /api/v1/tenants |
PLATFORM_ADMIN | Alle Mandanten |
| GET | /api/v1/tenants/:id |
TENANT_ADMIN+ | Mandant-Details |
| POST | /api/v1/tenants |
PLATFORM_ADMIN | Mandant erstellen |
| PATCH | /api/v1/tenants/:id |
PLATFORM_ADMIN | Mandant bearbeiten |
Einstellungen:
| Methode | Endpunkt | Rolle | Beschreibung |
|---|---|---|---|
| GET | /api/v1/settings/external-links |
Alle | Sidebar-Links abrufen |
| POST | /api/v1/settings/external-links |
PLATFORM_ADMIN | Sidebar-Links setzen |
| GET | /api/v1/settings/branding |
Alle | Branding-Einstellungen |
Gesundheit:
| Methode | Endpunkt | Auth | Beschreibung |
|---|---|---|---|
| GET | /health |
Nein | Health-Check (DB + Redis) |
5.4 Fehler-Responses
Alle Fehler folgen einem einheitlichen Format:
{
"statusCode": 401,
"message": "Unauthorized",
"error": "Unauthorized"
}
| HTTP-Code | Bedeutung |
|---|---|
| 400 | Ungueltige Eingabe (Validierungsfehler) |
| 401 | Nicht authentifiziert (Token fehlt/ungueltig) |
| 403 | Keine Berechtigung (Rolle nicht ausreichend) |
| 404 | Ressource nicht gefunden |
| 429 | Rate-Limit ueberschritten |
6. Traefik-Routing (API Gateway)
6.1 Eigene Route registrieren
Um deine Anwendung ueber Traefik erreichbar zu machen, verwende Docker-Labels:
services:
meine-app:
labels:
- "traefik.enable=true"
- "traefik.http.routers.meine-app.rule=PathPrefix(`/meine-app`)"
- "traefik.http.routers.meine-app.entrypoints=web"
- "traefik.http.services.meine-app.loadbalancer.server.port=8080"
# Optional: Middleware fuer CORS und Security
- "traefik.http.routers.meine-app.middlewares=cors-headers@file,security-headers@file"
6.2 Bestehende Routen (nicht verwenden!)
Diese Pfade sind bereits belegt:
| Pfad-Prefix | Service | Beschreibung |
|---|---|---|
/api/* |
core | Backend-API |
/health |
core | Health-Check |
/* |
frontend | React-Frontend (Catch-all, niedrige Prioritaet) |
6.3 Verfuegbare Middlewares
Die folgenden Middlewares sind bereits konfiguriert und koennen referenziert werden:
| Middleware | Funktion |
|---|---|
cors-headers@file |
CORS-Header (Origin, Methoden, Custom-Headers) |
security-headers@file |
CSP, XSS-Filter, HSTS, Frame-Deny |
api-ratelimit@file |
Rate-Limiting (100 avg, 50 burst) |
gzip-compress@file |
Gzip-Komprimierung |
6.4 CORS-Konfiguration
Standardmaessig erlaubte Methoden und Header:
Methoden: GET, POST, PUT, PATCH, DELETE, OPTIONS
Header: Authorization, Content-Type, X-Tenant-ID, X-Request-ID
Origin: Konfigurierbar via CORS_ORIGINS Umgebungsvariable
Falls deine Anwendung zusaetzliche Header benoetigt, muss die
config/traefik/dynamic/middlewares.yml erweitert werden.
7. Datenbank-Anbindung
7.1 Verbindung ueber PgBouncer (empfohlen)
Host: pgbouncer
Port: 6432
Datenbank: platform_core (oder eigene DB)
Pool-Mode: transaction
Connection-String:
postgresql://{DB_USER}:{DB_PASSWORD}@pgbouncer:6432/{DB_NAME}
Hinweis: Die DB-Credentials stehen in der
.env-Datei auf dem Server. Niemals in Git committen!
7.2 Direkte Verbindung (nur fuer Migrationen)
postgresql://{DB_USER}:{DB_PASSWORD}@postgres:5432/{DB_NAME}
PgBouncer im transaction-Modus unterstuetzt keine SET-Befehle,
LISTEN/NOTIFY oder PREPARE-Statements. Fuer Migrationen immer
die direkte Verbindung verwenden.
7.3 Eigenes Datenbank-Schema
Fuer neue Anwendungen empfehlen wir ein eigenes Schema in der bestehenden PostgreSQL-Instanz:
-- Schema fuer deine Anwendung erstellen
CREATE SCHEMA IF NOT EXISTS app_meine_app;
-- Tabellen im Schema anlegen
CREATE TABLE app_meine_app.beispiel (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
Namenskonvention: app_{anwendungsname} fuer das Schema.
7.4 Zugriff auf bestehende INSIGHT-Daten
Die Core-Datenbank (platform_core) enthaelt folgende relevante Tabellen:
| Tabelle | Beschreibung |
|---|---|
User |
Benutzer (ID, Name, E-Mail, Rolle) |
Tenant |
Mandanten (ID, Name, Slug) |
TenantUser |
Mandant-Benutzer-Zuordnung |
AuthProvider |
Authentifizierungsmethoden pro User |
Achtung: Direkter Schreibzugriff auf Core-Tabellen ist untersagt! Verwende die REST-API fuer Aenderungen an Core-Daten.
8. Redis / Cache
8.1 Verbindung
Host: redis
Port: 6379
Netzwerk: insight-cache
8.2 Key-Namenskonventionen
Um Konflikte zu vermeiden, verwende einen App-spezifischen Prefix:
app:{anwendungsname}:{key}
Bestehende Prefixes (NICHT verwenden):
| Prefix | Verwendet von |
|---|---|
blocked_token:* |
Auth (Revocation) |
platform_* |
Core-Settings |
favicon:* |
Favicon-Cache |
sso:state:* |
SSO CSRF-Schutz |
8.3 TTL-Empfehlung
Setze immer einen TTL auf deine Keys, um Speicher-Leaks zu vermeiden:
Kurzlebige Daten (Sessions): 5 - 30 Minuten
Cache-Daten: 1 - 24 Stunden
Konfiguration: 24 - 48 Stunden
9. Frontend-Integration (Sidebar)
9.1 Externe Links im INSIGHT-Menue
Deine Anwendung wird als externer Link in der INSIGHT-Sidebar angezeigt. Die Konfiguration erfolgt durch einen PLATFORM_ADMIN unter Administration > Externe Links.
Jeder Link hat folgende Eigenschaften:
| Feld | Beschreibung |
|---|---|
label |
Anzeigename im Menue (z.B. "Meine App") |
url |
URL deiner Anwendung |
sortOrder |
Reihenfolge in der Sidebar |
customIcon |
Optionales Icon (Base64, max 100KB) |
9.2 Favicon-Erkennung
INSIGHT erkennt automatisch das Favicon deiner Anwendung ueber HTML-Parsing:
- Deine Anwendung muss ein
<link rel="icon">Tag im HTML-<head>haben - Alternativ:
/favicon.icoim Root-Verzeichnis bereitstellen - Oder: Eigenes Icon als Base64 in der Admin-Konfiguration hochladen
9.3 Oeffnungs-Verhalten
Externe Links werden in einem separaten Browser-Fenster geoeffnet
(window.open mit popup,noopener). Deine Anwendung laeuft eigenstaendig
und kommuniziert ueber die REST-API mit INSIGHT.
10. Sicherheitsanforderungen
10.1 Verbindliche Regeln
| Regel | Details |
|---|---|
| Kein localStorage fuer Tokens | Access Token nur im Memory speichern |
| HTTPS in Produktion | Aktuell HTTP (Dev), spaeter Pflicht |
| Keine Secrets in Git | .env, Keys, Passwoerter nie committen |
| Input-Validierung | Whitelist-Validierung, kein raw SQL |
| Rate-Limiting beachten | Max 200 Req/Min global, 100/50 pro Route |
| CORS-Origin registrieren | Deine Domain in CORS_ORIGINS eintragen |
10.2 Validierung (GlobalPipe)
Der Core-Service nutzt einen globalen ValidationPipe:
- whitelist: true (unbekannte Felder werden entfernt)
- forbidNonWhitelisted: true (unbekannte Felder fuehren zu 400)
- transform: true (Typen werden automatisch konvertiert)
Stelle sicher, dass deine API-Requests nur die dokumentierten Felder enthalten.
10.3 Body-Size-Limit
Das maximale Request-Body ist auf 12 MB begrenzt (fuer Base64-Uploads). Fuer groessere Dateien implementiere einen separaten Upload-Endpunkt.
10.4 Account-Lockout
Nach 5 fehlgeschlagenen Login-Versuchen wird der Account fuer 15 Minuten gesperrt. Implementiere entsprechende Fehlerbehandlung.
11. Health-Checks & Monitoring
11.1 Health-Check Endpunkt
Deine Anwendung sollte einen Health-Check bereitstellen:
GET /meine-app/health
Response: { "status": "ok" }
Konfiguriere den Docker-Healthcheck:
services:
meine-app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
11.2 Logging
Nutze strukturiertes JSON-Logging fuer die Integration mit dem Observability-Stack (Loki/Grafana):
{
"level": "info",
"timestamp": "2026-03-10T12:00:00Z",
"message": "Request verarbeitet",
"service": "meine-app",
"requestId": "...",
"userId": "...",
"duration": 42
}
11.3 Observability-Stack (optional)
| Service | Port | Zugriff |
|---|---|---|
| Grafana | 3001 | SSH-Tunnel (nur intern) |
| Prometheus | 9090 | Nur intern |
| Loki | 3100 | Nur intern (Log-Aggregation) |
| Tempo | 3200 | Nur intern (Tracing) |
12. Checkliste fuer neue Container-Apps
Vor der Entwicklung
- Tech-Stack festlegen (Empfehlung: TypeScript/Node.js, Go, oder Python)
- Datenbank-Schema planen (
app_{name}Schema) - API-Endpunkte definieren
- Traefik-Route planen (Pfad-Prefix
/{app-name})
Implementierung
- Dockerfile erstellen (Multi-Stage-Build empfohlen)
- JWT-Validierung implementieren (RS256, Public Key)
- Health-Check-Endpunkt implementieren
- Strukturiertes JSON-Logging einrichten
- CORS korrekt konfigurieren
- Input-Validierung implementieren
- Fehler-Responses im INSIGHT-Format zurueckgeben
Docker-Integration
- Image in Container Registry pushen (
git.xinion.lan) docker-compose.override.ymloder separates Compose-File erstellen- Netzwerke einbinden (
insight-web, ggf.insight-db,insight-cache) - Traefik-Labels konfigurieren
- Healthcheck konfigurieren
- Umgebungsvariablen dokumentieren
Deployment
.env-Eintraege auf dem Server ergaenzen- Traefik-Route testen (
curl http://172.20.10.59/{app-name}/health) - JWT-Validierung testen (mit gueltigem/ungueltigem Token)
- In INSIGHT-Sidebar als externen Link eintragen
- Favicon / Custom-Icon konfigurieren
Dokumentation
- API-Dokumentation erstellen (OpenAPI/Swagger empfohlen)
- Umgebungsvariablen dokumentieren
- Datenbank-Schema dokumentieren
- README.md im Repository anlegen
13. Beispiel: docker-compose Erweiterung
Erstelle eine docker-compose.meine-app.yml Datei:
# docker-compose.meine-app.yml
# Starten mit: docker compose -f docker-compose.yml -f docker-compose.meine-app.yml up -d
services:
meine-app:
image: git.xinion.lan/gitadmin/insight-meine-app:latest
container_name: insight-meine-app
restart: unless-stopped
environment:
- NODE_ENV=production
- PORT=8080
- DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@pgbouncer:6432/platform_core?schema=app_meine_app
- REDIS_HOST=redis
- REDIS_PORT=6379
- JWT_PUBLIC_KEY_PATH=/app/keys/jwt-public.pem
- INSIGHT_API_URL=http://core:3000/api/v1
volumes:
- ./keys/jwt-public.pem:/app/keys/jwt-public.pem:ro
networks:
- insight-web
- insight-db
- insight-cache
labels:
- "traefik.enable=true"
- "traefik.http.routers.meine-app.rule=PathPrefix(`/meine-app`)"
- "traefik.http.routers.meine-app.entrypoints=web"
- "traefik.http.services.meine-app.loadbalancer.server.port=8080"
- "traefik.http.routers.meine-app.middlewares=cors-headers@file,security-headers@file"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
depends_on:
pgbouncer:
condition: service_healthy
redis:
condition: service_healthy
networks:
insight-web:
external: true
insight-db:
external: true
insight-cache:
external: true
Starten
# Auf dem Server (insight-dev-01)
cd /home/deploy/insight
# Zusammen mit der Hauptanwendung starten
docker compose \
-f docker-compose.yml \
-f docker-compose.meine-app.yml \
up -d
# Nur die neue App starten (Hauptanwendung laeuft bereits)
docker compose \
-f docker-compose.yml \
-f docker-compose.meine-app.yml \
up -d meine-app
# Logs pruefen
docker compose \
-f docker-compose.yml \
-f docker-compose.meine-app.yml \
logs -f meine-app
Kontakt & Support
Bei Fragen zur Integration wende dich an das INSIGHT-Plattform-Team:
- Repository:
ssh://git@git.xinion.lan/gitadmin/INSIGHT-MVP.git - Admin-E-Mail:
admin@xinion.de
Hinweis: Dieses Dokument bezieht sich auf die Alpha-Version (v1.0.0-alpha). API-Endpunkte und Konfigurationen koennen sich in spaeteren Versionen aendern.