INSIGHT-MVP/docs/INTEGRATION.md
Thomas Reitz a0f5474119 docs: add developer integration guide for container applications
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>
2026-03-10 12:53:15 +01:00

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

  1. Ueberblick
  2. Architektur
  3. Docker-Integration
  4. Authentifizierung & Autorisierung
  5. API-Kommunikation
  6. Traefik-Routing (API Gateway)
  7. Datenbank-Anbindung
  8. Redis / Cache
  9. Frontend-Integration (Sidebar)
  10. Sicherheitsanforderungen
  11. Health-Checks & Monitoring
  12. Checkliste fuer neue Container-Apps
  13. 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-db und insight-cache sind als internal markiert 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)

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:

  1. Deine Anwendung muss ein <link rel="icon"> Tag im HTML-<head> haben
  2. Alternativ: /favicon.ico im Root-Verzeichnis bereitstellen
  3. 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.yml oder 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.