From ad24aacb1812908152fb6d9ec520fad855c86119 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Thu, 11 Jun 2026 21:26:56 +0200
Subject: [PATCH] doc update
---
TOPICS.md | 5 +-
b-reference/platform-core/ai-agent.md | 26 +++-
b-reference/platform/authentication.md | 129 ++++++++++++++++++
c-work/_CHANGELOG.md | 6 +
.../02_Zugriffsmanagement_IAM_PAM.md | 30 +++-
.../ims/05_betrieb/security-overview.md | 40 +++++-
6 files changed, 219 insertions(+), 17 deletions(-)
create mode 100644 b-reference/platform/authentication.md
diff --git a/TOPICS.md b/TOPICS.md
index 8b66b01..047aaca 100644
--- a/TOPICS.md
+++ b/TOPICS.md
@@ -1,5 +1,5 @@
-
+
# Themen-Index für AI-Kontext
@@ -19,7 +19,7 @@ Lade immer zuerst diese Datei. Dann gezielt die passende(n) Referenz-Datei(en).
|-------|-------|------------|
| Komponentenübersicht | b-reference/product.md | Repo-übergreifende Fragen, Tech-Stack |
| Gateway-Architektur | b-reference/platform-core/architecture.md | Backend-Module, Services, Interfaces |
-| AI Agent & Tools | b-reference/platform-core/ai-agent.md | Agent-Verhalten, Tool-Registrierung, RAG |
+| AI Agent & Tools | b-reference/platform-core/ai-agent.md | Agent-Verhalten, Tool-Registrierung, RAG, Embed-first, Prior-File-Kontextbudget (`maxPriorContextFiles`), Embedding-Cache |
| Agent-Tool File Bridge | b-reference/platform-core/agent-file-bridge.md | Wie Agent-Tool-Outputs (download / writeFile / renderDocument / generateImage / createChart) als ChatDocument im Workflow landen, `docItem:`-Pattern, runAgent Workflow-Propagation |
| Dokumenten-Rendering & Style-System | b-reference/platform-core/document-rendering.md | Rendering-Pipeline (MD->JSON->File), Style-Resolution (4 Schichten: DEFAULT_STYLE -> Agent-Overrides -> AI-Enhancement -> Per-Element), Tabellen-Styling, Renderer-Architektur (PDF/DOCX/PPTX/XLSX/HTML) |
| Workflow-Engine | b-reference/platform-core/workflow.md | Methoden, Aktionen, WorkflowManager |
@@ -36,6 +36,7 @@ Lade immer zuerst diese Datei. Dann gezielt die passende(n) Referenz-Datei(en).
| Thema | Datei | Wann laden |
|-------|-------|------------|
+| Authentifizierung & Sessions | b-reference/platform/authentication.md | Login, JWT, Multi-Session, MFA, Trusted Device, Silent Refresh, Session-Admin |
| Neutralisierung | b-reference/platform/neutralization.md | Datenschutz, AI-Call-Pipeline, Failsafe |
| Unified Data Bar (UDB) | b-reference/platform/unified-data-bar.md | Polymorphe `UdbNode`-Hierarchie, Flag-Mechanik (`neutralize`/`scope`/`ragIndexEnabled`), `POST /api/udb/tree/children`, `POST /api/udb/node/{key}/flag/{flag}`, RBAC fuer Flag-Edits (Owner vs Feature-Admin) |
| RBAC | b-reference/platform/rbac.md | 4-Stufen-Modell, Template-Rollen, Resolution, Datenmodell, UDB-Flag-Edit-Gate (Feature-Admin) |
diff --git a/b-reference/platform-core/ai-agent.md b/b-reference/platform-core/ai-agent.md
index 7c7dd87..81c1cec 100644
--- a/b-reference/platform-core/ai-agent.md
+++ b/b-reference/platform-core/ai-agent.md
@@ -1,6 +1,6 @@
-
-
+
+
# AI Agent & Knowledge Store
@@ -347,8 +347,26 @@ Zugriff über **`interfaceDbKnowledge`** (`FileContentIndex`, `ContentChunk`, Ro
Rückgabe: formatierter String für Injektion in den Agent-Systemkontext. **Wenn Embedding fehlschlägt**, liefert `buildAgentContext` einen **leeren String** (Agent arbeitet ohne diesen RAG-Block).
+**Query-Extraktion (ab 2026-06-11):** Der Suchvektor wird aus **`_extractUserQuery(currentPrompt)`** gebaut, nicht aus dem vollen angereicherten Prompt. Die Helper-Funktion isoliert die eigentliche User-Frage über die Enrichment-Marker (`"User request: "`-Suffix von `_enrichPromptWithFiles`, `[Active Data Sources]`/`[Attached Feature Data Sources]`-Sections). Grund: Der angereicherte Prompt enthält Datei-Metadaten-Blöcke, die (a) den Suchvektor semantisch verwässern und (b) das Per-Input-Limit der Embedding-Modelle sprengen können (Prod-Incident 2026-06-11: 29k-Token-Query gegen 8192-Token-Limit → RAG für den ganzen Run ausgefallen).
+
Erweiterte Hilfen (z. B. **`readSection`**, Caching) für selektives Lesen sind im selben Service dokumentiert.
+### Workspace-Datei-Kontext: Embed-first + Kontextbudget (ab 2026-06-11)
+
+Der Workspace-Agent (`routeFeatureWorkspace._runWorkspaceAgent`) steuert, welche Datei-Metadaten in den Agent-Prompt injiziert werden. Zwei Mechanismen:
+
+1. **Embed-first (`_ensureFilesIndexed`):** Alle der aktuellen Nachricht angehängten Files werden **vor Agent-Start** geprüft (`FileContentIndex.status`) und falls nötig inline extrahiert + indexiert. Idempotent (Status-Check + Content-Hash in `requestIngestion`) — jedes File wird genau einmal in seinem Lebenszyklus verarbeitet, ein Re-Attach ist ein No-op. Damit funktioniert RAG-Retrieval ab Runde 1, statt dass der Agent Inhalte lazy per `readFile` (pro Runde, teurer) ziehen muss.
+
+2. **Prior-File-Kontextbudget (`_selectPriorFilesForContext`):** Files aus früheren Nachrichten des Workflows werden nicht mehr pauschal alle in den Prompt gemerged (Kostentreiber: Metadaten-Injection × jede Agent-Runde; Prod-Incident: 30 Files → ~0.35 CHF pro LLM-Call). Stattdessen:
+ - Budget **`maxPriorContextFiles`** (Default `DEFAULT_MAX_PRIOR_CONTEXT_FILES = 10`), **pro Workspace-Instanz konfigurierbar** via `instanceConfig`.
+ - Auswahl läuft **nur**, wenn mehr Kandidaten als Budget existieren — sonst Durchreichen ohne Embedding-Call.
+ - Reihenfolge: semantisch relevante Files zuerst (pgvector-Suche der indexierten Chunks gegen den User-Prompt), Restbudget mit den **neuesten** Files aufgefüllt (Files ohne Index-Eintrag werden nicht benachteiligt).
+ - **Kein Datenverlust:** Die Limite betrifft nur die Metadaten-Injection. Alle Files bleiben über Conversation-History und `readFile` erreichbar.
+
+**Embedding-Cache (`interfaceAiObjects`):** In-Process-LRU (256 Einträge, SHA-256-Key) vor jedem Embedding-API-Call. Identische Texte (z. B. derselbe User-Prompt, embedded einmal für die Prior-File-Auswahl und einmal in `buildAgentContext`) verursachen nur **einen** API-Call. Greift für alle Embedding-Aufrufer plattformweit.
+
+**Per-Input-Limit (`_buildEmbeddingBatches`):** Einzelne Texte über dem modell-spezifischen Limit (`model.contextLength`, z. B. 8191 Tokens bei `text-embedding-3-small`) werden mit **sichtbarem Warning** truncated statt die API hart fehlschlagen zu lassen. File-Inhalte erreichen dieses Limit nie — die Chunking-Schicht (`_chunkForEmbedding`, `DEFAULT_CHUNK_TOKENS = 400`) splittet vollständig und verlustfrei; nur überlange Such-Queries können es treffen, wo Truncation semantisch akzeptabel ist.
+
### RAG Consent & Control (ab 2026-05)
Volle Architektur für transparente, datenzentrierte Steuerung der RAG-Indexierung durch den Benutzer.
@@ -496,7 +514,9 @@ Siehe [`b-reference/teams-bot/architecture.md`](../teams-bot/architecture.md) f
| `platform-core/modules/serviceCenter/services/serviceAgent/toolboxRegistry.py` | Toolbox-Definitionen, `requestToolbox` Meta-Tool-Schema |
| `platform-core/modules/serviceCenter/services/serviceAgent/workflowTools.py` | Workflow-Editing-Tools (readWorkflowGraph, addNode, ...) |
| `platform-core/modules/serviceCenter/services/serviceAgent/sandboxExecutor.py` | `executeCode`-Sandbox |
-| `platform-core/modules/serviceCenter/services/serviceKnowledge/mainServiceKnowledge.py` | Index, `buildAgentContext`, Workflow-/Round-Memory-Helfer |
+| `platform-core/modules/serviceCenter/services/serviceKnowledge/mainServiceKnowledge.py` | Index, `buildAgentContext` (Query-Extraktion via `_extractUserQuery`), Workflow-/Round-Memory-Helfer |
+| `platform-core/modules/features/workspace/routeFeatureWorkspace.py` | Workspace-SSE-Routen; `_runWorkspaceAgent` (Embed-first `_ensureFilesIndexed`, Prior-File-Budget `_selectPriorFilesForContext`) |
+| `platform-core/modules/interfaces/interfaceAiObjects.py` | AI-Interface-Layer; `callEmbedding` (Token-aware Batching, Embedding-Cache, Per-Input-Limit), Modell-Failover |
| `platform-core/modules/interfaces/interfaceDbKnowledge.py` | DB-Zugriff Knowledge / RAG |
| `platform-core/modules/datamodels/datamodelKnowledge.py` | FileContentIndex, ContentChunk, RoundMemory, WorkflowMemory |
| `platform-core/modules/serviceCenter/services/serviceAi/mainServiceAi.py` | Zentrales Neutralisierungs-Gate vor LLM, Billing, Provider-Aufruf |
diff --git a/b-reference/platform/authentication.md b/b-reference/platform/authentication.md
new file mode 100644
index 0000000..242cabe
--- /dev/null
+++ b/b-reference/platform/authentication.md
@@ -0,0 +1,129 @@
+
+
+
+
+# Authentifizierung & Session-Management
+
+## Uebersicht
+
+PORTA verwendet ein **hybrides JWT + Server-Side Token-Registry**-Modell. Jeder Login erzeugt ein JWT-Paar (Access + Refresh); die Token-IDs werden serverseitig in PostgreSQL gespeichert, um Revocation und Session-Management zu ermoeglichen.
+
+## Login-Methoden
+
+| Methode | Route | Provider |
+|---------|-------|----------|
+| Lokal (E-Mail/Passwort) | `POST /api/local/login` | Eigene DB |
+| Microsoft (Entra ID) | `GET /api/msft/auth/login` | Azure AD OAuth2 |
+| Google | `GET /api/google/auth/login` | Google OAuth2 |
+
+## Token-Architektur
+
+### Access Token
+- **Algorithmus:** HS256
+- **Lebensdauer:** Konfigurierbar via `APP_TOKEN_EXPIRY` (Default: 300 Minuten)
+- **Claims:** `sub`, `userId`, `authenticationAuthority`, `jti`, `sid` (Session-ID), `exp`
+- **Transport:** httpOnly Cookie `auth_token` (primaer) oder `Authorization: Bearer` (API-Clients)
+
+### Refresh Token
+- **Lebensdauer:** Konfigurierbar via `APP_REFRESH_TOKEN_EXPIRY` (Default: 7 Tage)
+- **Claims:** Wie Access + `type: "refresh"`
+- **Transport:** httpOnly Cookie `refresh_token`
+
+### Cookie-Policy
+- **HTTPS (Prod):** `Secure=True`, `SameSite=None` (Cross-Origin SPA)
+- **HTTP (Dev):** `Secure=False`, `SameSite=Lax`
+- Steuerbar via `APP_COOKIE_SECURE` env-Variable
+
+## Multi-Session-Support
+
+PORTA erlaubt **parallele Sessions** auf mehreren Geraeten/Browsern gleichzeitig. Ein neuer Login invalidiert bestehende Sessions NICHT.
+
+### Regulatorischer Kontext
+- **NIST SP 800-63B (Section 7.1):** Erlaubt explizit mehrere aktive Authenticator-Sessions pro Subscriber. Kein Grund fuer Single-Session-Erzwingung bei korrekt implementierter Revocation.
+- **BSI TR-03107:** Empfiehlt Session-Management mit Monitoring, nicht Single-Session-Zwang.
+- **Praxisstandard:** Microsoft 365, Google Workspace, AWS Console — alle erlauben parallele Sessions.
+
+### Sicherheitsgarantien
+- Jede Session hat eine eigene `sessionId` (UUID)
+- Admin kann jede Session einzeln oder alle Sessions eines Users revoken
+- Logout betrifft nur die aktuelle Session (`DELETE /api/local/logout`)
+- Token-DB-Pruefung bei jedem Request: nur Tokens mit aktivem DB-Eintrag sind gueltig
+
+## Silent Token Refresh
+
+Wenn der Access Token ablaeuft, versucht das Frontend automatisch eine stille Erneuerung via `POST /api/local/refresh`, bevor zum Login umgeleitet wird.
+
+### Ablauf
+1. API-Request erhaelt 401
+2. Frontend ruft `POST /api/local/refresh` (sendet `refresh_token` Cookie)
+3. Backend validiert Refresh-JWT + erstellt neuen Access Token
+4. Neuer Access Token wird in DB registriert + als Cookie gesetzt
+5. Originaler Request wird mit neuem Token wiederholt
+
+Falls Refresh fehlschlaegt (Token abgelaufen/revoked): Redirect zu `/login`.
+
+## MFA (Multi-Faktor-Authentifizierung)
+
+### Wann MFA verlangt wird (OR-Logik)
+1. User hat `mfaEnabled=True` (Opt-in)
+2. Mindestens ein Mandat des Users hat `mfaRequired=True`
+3. User ist SysAdmin/PlatformAdmin UND `MFA_REQUIRE_ADMINS=True`
+
+### Verfahren
+- **TOTP** (Time-based One-Time Password) via `pyotp`
+- 6 Ziffern, 30-Sekunden-Intervall, Toleranzfenster ±1
+- Secrets verschluesselt gespeichert (AES/Fernet)
+
+## Trusted Device (MFA-Skip)
+
+Nach erfolgreicher MFA-Verifizierung kann ein Geraet als **vertrauenswuerdig** markiert werden. Fuer die konfigurierte Dauer (Default: 60 Tage) wird MFA auf diesem Geraet uebersprungen.
+
+### Regulatorischer Kontext
+- **NIST SP 800-63B (Section 5.2.8):** Erlaubt "remember this device" ausdruecklich unter der Bedingung, dass der Authenticator kryptographisch an den Subscriber gebunden ist.
+- **BSI TR-03107:** Akzeptiert geraetegebundene Vertrauensstellung bei angemessener Laufzeitbegrenzung.
+- **Praxisstandard:** Microsoft ("Don't ask again for 60 days"), Google (trusted device), AWS (remembered device).
+
+### Mechanismus
+- httpOnly Cookie `mfa_trusted` mit kryptographisch zufaelligem Token
+- Server-Eintrag in `TrustedDevice`-Tabelle: `id`, `userId`, `trustedUntil`, `userAgent`, `ipAddress`
+- Beim Login: Cookie vorhanden + DB-Eintrag gueltig → MFA uebersprungen
+- Admin oder User kann Trusted Devices jederzeit revoken
+- Automatische Bereinigung abgelaufener Eintraege
+
+### Sicherheitsgrenzen
+- Vertrauensdauer auf 60 Tage begrenzt (konfigurierbar)
+- Bei Passwort-Aenderung oder Admin-Revoke: alle Trusted Devices invalidiert
+- Cookie ist geraetegebunden (httpOnly, nicht uebertragbar)
+
+## Session-Verwaltung (Admin)
+
+Administratoren koennen aktive Sessions und Trusted Devices ueber API-Endpoints verwalten:
+
+| Endpoint | Beschreibung |
+|----------|-------------|
+| `GET /api/admin/sessions?userId=X` | Aktive Sessions eines Users |
+| `DELETE /api/admin/sessions/{sessionId}` | Einzelne Session revoken |
+| `DELETE /api/admin/sessions?userId=X` | Alle Sessions eines Users revoken |
+| `GET /api/admin/trusted-devices?userId=X` | Trusted Devices auflisten |
+| `DELETE /api/admin/trusted-devices?userId=X` | Alle Trusted Devices revoken |
+
+## Token-Hygiene
+
+- Abgelaufene Token-Eintraege werden automatisch bereinigt (Hintergrundtask)
+- Abgelaufene TrustedDevice-Eintraege werden ebenso bereinigt
+- Revoked-Tokens werden fuer Audit-Zwecke 30 Tage aufbewahrt, danach geloescht
+
+## Schluessel-Dateien
+
+| Datei | Verantwortung |
+|-------|---------------|
+| `modules/auth/jwtService.py` | JWT-Erzeugung, Cookie-Helpers |
+| `modules/auth/authentication.py` | Token-Validierung, `_getUserBase()` |
+| `modules/auth/mfaService.py` | TOTP-Erzeugung/-Verifizierung |
+| `modules/auth/trustedDeviceService.py` | Trusted-Device-Logik |
+| `modules/routes/routeSecurityLocal.py` | Login/Logout/Refresh Endpoints |
+| `modules/routes/routeSecurityMsft.py` | Microsoft OAuth Callback |
+| `modules/routes/routeSecurityGoogle.py` | Google OAuth Callback |
+| `modules/routes/routeMfa.py` | MFA-Setup/-Verify Endpoints |
+| `modules/interfaces/interfaceDbApp.py` | Token-DB-Operationen |
+| `modules/datamodels/datamodelSecurity.py` | Token + TrustedDevice Models |
diff --git a/c-work/_CHANGELOG.md b/c-work/_CHANGELOG.md
index 1eb7eaa..48df55e 100644
--- a/c-work/_CHANGELOG.md
+++ b/c-work/_CHANGELOG.md
@@ -14,6 +14,12 @@ Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler.
## 2026-06-11
+- 2026-06-11 | fix | ui-nyla | **FormGeneratorTable Filter-Race systemweit behoben**: `_lastTableParams` Ref-Cache in 16 Seiten (10 HIGH, 6 MEDIUM) eingefuehrt. Parent-useEffects die ungefiltert den gleichen Loader wie `hookData.refetch` aufriefen, entfernt oder auf Cache umgestellt. Betroffene Seiten: WorkflowTemplatesPage, AdminUserMandatesPage, AdminMandateRolesPage, AdminFeatureAccessPage, AdminFeatureInstanceUsersPage, AdminFeatureRolesPage, AdminInvitationsPage, TrusteePositionsView, TrusteeDocumentsView, CommcoachSettingsView, ConnectionsPage, FilesPage, PromptsPage, AdminUsersPage, AdminMandatesPage, AdminSubscriptionsPage.
+- 2026-06-11 | fix | platform-core | **Google STT de-CH Language-Mapping**: `_normalizeSttLanguage()` mappt regionale Varianten (de-CH→de-DE, fr-CH→fr-FR etc.) vor Google Speech API-Aufruf; behebt `400 Invalid recognition config` fuer `latest_long` Modell.
+- 2026-06-11 | fix | ui-nyla | **8 UI/UX-Bugfixes**: (1) Voice-Preferences 404: `fetch`→`api`-Client in WorkspaceInput. (2) RAG-Seite: Datenobjekt-Toggle + Settings-Button pro Verbindung. (3) DSGVO i18n: Statische DE-Texte statt EN-Backend-Content, LOESCHEN-Placeholder via `t()`. (4) FormGeneratorTable Default-Sort: `initialSort` desc auf Compliance/Billing/Subscriptions. (5) FormGeneratorTable Filter-Race: Parent-Loader in ComplianceAuditPage entfernt + Loader-Params-Cache via Ref. (6+7) Admin-Wizards: Mandanten/User/Rollen alphabetisch sortiert (case-insensitive) in allen 3 Wizards.
+- 2026-06-11 | docs | wiki | **ai-agent.md: Embed-first + Prior-File-Kontextbudget dokumentiert** — Neue Sektion »Workspace-Datei-Kontext«, `buildAgentContext` Query-Extraktion, Embedding-Cache, Per-Input-Limit; Schlüssel-Dateien + TOPICS.md ergänzt.
+- 2026-06-11 | feat | platform-core | **Workspace-Agent: Embed-first + RAG-Kontextbudget**: Angehaengte Files werden vor Agent-Start indexiert (`_ensureFilesIndexed`, idempotent); Prior-Files via Relevanz-Ranking + Recency-Fill auf konfigurierbares Budget (`maxPriorContextFiles`, Default 10) statt pauschal alle; Query-Embedding nutzt nur den User-Prompt (`_extractUserQuery`); Embedding-Cache in `interfaceAiObjects` dedupliziert identische Query-Texte; Embedding-Inputs ueber Modell-Limit werden mit Warning truncated statt API-Fehler.
+- 2026-06-11 | fix | platform-core | **TrusteeAccountingConfig `text = boolean` Prod-Fehler**: `_SAFE_TYPE_CHANGES` um `("text", "BOOLEAN")`-Migration ergaenzt — `isActive`-Spalten aus Alt-Schema werden beim Boot zu BOOLEAN migriert (RMA-Einstellungen speichern schlug fehl).
- 2026-06-11 | docs | wiki | **IMS: Personen & VR im Organisationsreglement** — Vollständige Namen, VR-Mitglieder, FT/OP-Rollencodes, Mitarbeitende Stephan Schellworth / Ida Dittrich; PDFs neu.
- 2026-06-11 | docs | wiki | **IMS: MFA umgesetzt nachgeführt** — M-01 erledigt, R-03/SoA A.5.17+A.8.5 auf Umgesetzt, Zugriffsmanagement und Rechtsanalyse aktualisiert.
- 2026-06-11 | docs | wiki | **IMS: Organisationsreglement** — `02_fuehrung/organisationsreglement.md`; Kommunikation/Rollen/R-01 ergänzt; M-14 VR-Freigabe in Arbeit.
diff --git a/e-compliance/ims/05_betrieb/02_Zugriffsmanagement_IAM_PAM.md b/e-compliance/ims/05_betrieb/02_Zugriffsmanagement_IAM_PAM.md
index d9491f1..053b51e 100644
--- a/e-compliance/ims/05_betrieb/02_Zugriffsmanagement_IAM_PAM.md
+++ b/e-compliance/ims/05_betrieb/02_Zugriffsmanagement_IAM_PAM.md
@@ -5,7 +5,7 @@
**Version:** 1.0
**Status:** Entwurf zur internen Freigabe
**Owner:** Betrieb / DevOps
-**Letzte Aktualisierung:** 02.06.2026
+**Letzte Aktualisierung:** 11.06.2026
**Deckt ab (CACC):** 25, 36, 37, 66, 67, 68, 69
---
@@ -40,14 +40,31 @@ Jeder solche Zugriff wird protokolliert (Datenbank-Export/Import wird serverseit
| System | Authentifizierungsmethode | MFA |
|---|---|---|
-| PORTA Endnutzer | Microsoft Azure AD OAuth / Google OAuth / lokales Login | [ZU PRÜFEN: MFA erzwungen?] |
-| Admin-UI (SysAdmin) | Lokales Login / Session | **MFA erzwungen** (umgesetzt Juni 2026) |
+| PORTA Endnutzer | Microsoft Azure AD OAuth / Google OAuth / lokales Login | Konfigurierbar pro Mandat (`mfaRequired`) oder pro User (Opt-in) |
+| Admin-UI (SysAdmin) | Lokales Login / Session | **MFA erzwungen** (`MFA_REQUIRE_ADMINS=True`, umgesetzt Juni 2026) |
| SSH-Server | SSH-Key | [ZU PRÜFEN: Key + Passphrase? Bastion?] |
-| Drittdienste (OpenAI etc.) | API-Keys in `.env` | n/a |
+| Drittdienste (OpenAI etc.) | API-Keys in `.env` (verschlüsselt) | n/a |
**Vorgabe:** Für privilegierte Zugänge (SysAdmin, SSH, DB) ist Zwei-Faktor-Authentifizierung zu konfigurieren. SMS-/mobile TAN ist möglichst zu vermeiden; bevorzugt App- oder Hardware-Token.
-**Stand Juni 2026:** MFA auf Admin-UI (SysAdmin) und Server-Zugängen umgesetzt. Endnutzer-MFA über IdP (Azure AD/Google) und SSH-Details siehe unten — offene Punkte bleiben markiert.
+**Stand Juni 2026:** MFA auf Admin-UI (SysAdmin) und Server-Zugängen umgesetzt. Endnutzer-MFA konfigurierbar pro Mandat. Trusted-Device-Mechanismus (60 Tage) reduziert MFA-Haeufigkeit bei gleicher Sicherheit — konform mit NIST SP 800-63B Abschnitt 5.2.8.
+
+### 4.1 Session-Management
+
+| Eigenschaft | Umsetzung |
+|---|---|
+| Token-Typ | JWT (HS256) in httpOnly/Secure Cookie |
+| Multi-Session | Erlaubt (parallele Browser/Geräte) |
+| Session-Dauer (Access) | Konfigurierbar, Default 300 Min |
+| Session-Dauer (Refresh) | Konfigurierbar, Default 7 Tage |
+| Silent Refresh | Frontend erneuert Access Token automatisch via Refresh-Endpoint |
+| Token-Revocation | Serverseitig via PostgreSQL Token-Registry; Admin kann einzelne oder alle Sessions revoken |
+| Trusted Device | httpOnly Cookie nach MFA-Erfolg; Default 60 Tage; jederzeit durch Admin/User widerrufbar |
+
+**Regulatorische Grundlage:**
+- Multi-Session ist Standard bei Enterprise-Software (NIST SP 800-63B Section 7.1 erlaubt mehrere aktive Sessions).
+- Trusted Device entspricht NIST SP 800-63B Section 5.2.8 ("Verifier MAY re-authenticate only after a configurable period").
+- Session-Revocation erfüllt ISO 27001 A.9.4.2 (Secure log-on procedures) und A.9.2.6 (Removal/adjustment of access rights).
## 5. Berechtigungsvergabe, -änderung und -entzug (#67)
@@ -76,4 +93,7 @@ Privilegierter Zugriff (SSH, DB-Admin, SysAdmin) wird nur sorgfältig ausgewähl
|---|---|---|
| Personalisierte SSH-Accounts | Offen | Umstellung oder vollständige Sitzungsprotokollierung |
| MFA auf privilegierten Zugängen | **Umgesetzt** (Juni 2026) | Halbjährliche Rezertifizierung |
+| Multi-Session + Silent Refresh | **Umgesetzt** (Juni 2026) | Parallele Sessions erlaubt; automatische Token-Erneuerung |
+| Trusted Device (MFA-Skip 60d) | **Umgesetzt** (Juni 2026) | NIST-konform; Admin-Revoke jederzeit moeglich |
+| Admin Session-Verwaltung | **Umgesetzt** (Juni 2026) | Sessions/Trusted Devices pro User einsehbar und widerrufbar |
| Halbjährliche Rezertifizierung | Neu | Erstdurchführung terminieren |
diff --git a/e-compliance/ims/05_betrieb/security-overview.md b/e-compliance/ims/05_betrieb/security-overview.md
index c220d00..7ff2987 100644
--- a/e-compliance/ims/05_betrieb/security-overview.md
+++ b/e-compliance/ims/05_betrieb/security-overview.md
@@ -1,6 +1,6 @@
# PowerOn Plattform -- Sicherheit und Compliance
-**Stand:** Februar 2026
+**Stand:** Juni 2026
**Zielgruppe:** Entscheidungsträger, Einkauf, Rechtsabteilung, Datenschutzbeauftragte
**Klassifizierung:** Kundeninformation
@@ -302,7 +302,7 @@ Die Plattform adressiert die häufigsten Web-Sicherheitsrisiken gemäss OWASP:
| Cryptographic Failures | AES-Verschlüsselung, PBKDF2-Schlüsselableitung, HTTPS/TLS |
| Injection | Parametrisierte Datenbankabfragen, Eingabebereinigung, SQL-Leseeinschränkung |
| Security Misconfiguration | CORS-Einschränkungen, Rate Limiting, CSRF-Schutz |
-| Identification and Authentication Failures | JWT-basierte Authentifizierung, Token-Widerruf, Ratenbegrenzung bei Anmeldung |
+| Identification and Authentication Failures | JWT + serverseitige Token-Registry, MFA (TOTP), Trusted Device, Silent Refresh, Session-Revocation durch Admin, Ratenbegrenzung bei Anmeldung |
Es besteht **keine formale OWASP-Zertifizierung**. Die Massnahmen basieren auf den OWASP-Empfehlungen und sind als präventive Sicherheitsmassnahmen implementiert.
@@ -327,13 +327,39 @@ PowerOn unterstützt mehrere Authentifizierungsverfahren:
### 10.2 Sitzungssicherheit
- Authentifizierungstoken werden in sicheren, HTTP-only Cookies gespeichert (nicht im Browser-Speicher zugänglich)
-- Tokens haben eine konfigurierbare Gültigkeitsdauer
-- Token-Widerruf ist jederzeit möglich (z.B. bei Verdacht auf Kompromittierung)
-- Bei lokaler Anmeldung wird die Gültigkeit des Tokens zusätzlich gegen die Datenbank geprüft
+- Tokens haben eine konfigurierbare Gültigkeitsdauer (Access: 300 Min, Refresh: 7 Tage)
+- Token-Widerruf ist jederzeit möglich (z.B. bei Verdacht auf Kompromittierung) -- Administratoren können einzelne oder alle Sessions eines Nutzers sofort beenden
+- Jede Anmeldung wird serverseitig in einer Token-Registry (PostgreSQL) registriert; nur dort vorhandene Token werden akzeptiert
-### 10.3 Automatische Token-Erneuerung
+### 10.3 Parallele Sitzungen (Multi-Session)
-Authentifizierungstoken werden automatisch erneuert, bevor sie ablaufen. Dies gewährleistet eine unterbrechungsfreie Nutzung bei gleichzeitiger Begrenzung der Token-Gültigkeitsdauer.
+Nutzer können auf mehreren Geräten und Browsern gleichzeitig angemeldet sein -- analog zu Microsoft 365 und Google Workspace. Eine neue Anmeldung invalidiert bestehende Sitzungen nicht. Dies ist konform mit NIST SP 800-63B (Section 7.1) und ermöglicht die branchenübliche parallele Nutzung (z.B. Desktop + Mobilgerät).
+
+Die Sicherheit wird gewährleistet durch:
+- Serverseitige Session-Registry mit individueller Revocation
+- Admin-Zugang zur aktiven-Sitzungs-Übersicht mit Widerrufsmöglichkeit
+- Automatische Bereinigung abgelaufener Sitzungen
+
+### 10.4 Automatische Token-Erneuerung (Silent Refresh)
+
+Access-Tokens werden automatisch erneuert, bevor der Nutzer zum erneuten Login gezwungen wird. Der Refresh-Token (7 Tage Gültigkeit) ermöglicht eine unterbrechungsfreie Nutzung. Erst wenn auch der Refresh-Token abgelaufen ist, muss sich der Nutzer erneut anmelden.
+
+### 10.5 Multi-Faktor-Authentifizierung (MFA)
+
+PowerOn unterstützt TOTP-basierte MFA (Authenticator-App). MFA wird verlangt, wenn:
+- Der Mandant `mfaRequired=True` konfiguriert hat, oder
+- Der Nutzer MFA aktiviert hat (Opt-in), oder
+- Der Nutzer ein Admin ist und `MFA_REQUIRE_ADMINS` aktiv ist
+
+### 10.6 Vertrauenswürdige Geräte (Trusted Device)
+
+Nach erfolgreicher MFA-Verifizierung kann ein Gerät für 60 Tage als vertrauenswürdig markiert werden. Innerhalb dieses Zeitraums entfällt die MFA-Abfrage auf diesem Gerät. Dies entspricht dem Microsoft-Standard ("Don't ask again for 60 days") und ist konform mit NIST SP 800-63B Section 5.2.8.
+
+Sicherheitsgrenzen:
+- Vertrauensdauer ist zeitlich begrenzt und konfigurierbar
+- Administrator oder Nutzer können vertrauenswürdige Geräte jederzeit widerrufen
+- Bei Passwortänderung werden alle vertrauenswürdigen Geräte automatisch invalidiert
+- Das Vertrauens-Cookie ist httpOnly und nicht programmatisch auslesbar
---