wiki/b-reference/platform/database-architecture.md
2026-04-06 00:46:32 +02:00

9.5 KiB

Datenbank-Architektur

Ueberblick

PowerOn verwendet PostgreSQL mit einer klaren Trennung: jedes Modul (App, Chat, Billing, Knowledge, Features) hat eine eigene physische Datenbank (poweron_*). Datenbank-Zugriffe laufen ueber Interfaces (interfaceDb*.py), die auf dem zentralen DatabaseConnector (connectorDbPostgre.py) aufbauen. Datenbanken und Tabellen werden automatisch beim ersten Zugriff erzeugt -- kein manuelles Schema-Management noetig.


Architektur-Stack

Route / Service
    |
    v
Interface (interfaceDb*.py)
    |-- XxxObjects Klasse
    |-- getInterface() Factory (cached)
    |-- setUserContext() -> RBAC-Anbindung
    |
    v
DatabaseConnector (connectorDbPostgre.py)
    |-- Auto-Create Database
    |-- Auto-Create/Extend Tables (aus Pydantic-Modellen)
    |-- CRUD-Operationen (getRecordset, recordCreate, recordUpdate, recordDelete)
    |
    v
PostgreSQL (+ pgvector Extension)

Datenbanken

Inventar

Datenbank Modul / Zweck Interface
poweron_app Kernapplikation: UAM, Mandanten, Rollen, RBAC-Regeln, Navigation, Config interfaceDbApp.py
poweron_chat Chat-Verlaeufe, Messages, Attachments interfaceDbChat.py
poweron_management System-Management, Logs interfaceDbManagement.py
poweron_knowledge RAG Knowledge-Store (mit pgvector) interfaceDbKnowledge.py
poweron_billing Billing Accounts, Transactions, Usage interfaceDbBilling.py
poweron_billing Subscriptions (gleiche DB wie Billing) interfaceDbSubscription.py
poweron_workspace AI Workspace Feature-Daten Feature-Interface
poweron_automation Automation v1 Workflows, Runs Feature-Interface
poweron_automation2 Automation v2 (Graph-Editor) Workflows, Runs Feature-Interface
poweron_chatbot Chatbot Feature-Daten Feature-Interface
poweron_trustee Trustee Feature-Daten Feature-Interface
poweron_commcoach CommCoach Feature-Daten Feature-Interface
poweron_neutralization Neutralisierungs-Daten Feature-Interface
poweron_realestate RealEstate Feature-Daten Feature-Interface
poweron_teamsbot Teams-Bot Feature-Daten Feature-Interface
poweron_test Test-Datenbank Nur in Tests

Namenskonvention

Feature-Datenbanken folgen dem Pattern poweron_{featureCode.lower()}. Der Datenbankname wird hart-codiert in der _initializeDatabase() Methode des jeweiligen Interfaces.

Konfiguration

Verbindungsparameter kommen aus APP_CONFIG (config.ini / Environment):

Key Beschreibung
DB_HOST PostgreSQL Host
DB_PORT PostgreSQL Port
DB_USER Datenbank-Benutzer
DB_PASSWORD_SECRET Passwort (ggf. verschluesselt)
DB_DATABASE Default-DB-Name (Standard: poweron_app)

Interface-Pattern

Jedes Interface folgt einem einheitlichen Aufbau:

XxxObjects Klasse

class AppObjects:
    db: DatabaseConnector        # Connector zur eigenen DB
    rbac: RbacClass              # RBAC-Integration
    currentUser: dict            # Aktueller Benutzer
    mandateId: str               # Aktueller Mandant
    featureInstanceId: str       # (nur bei Feature-Interfaces)

_initializeDatabase()

Setzt den Datenbanknamen und erstellt den Connector:

def _initializeDatabase(self):
    dbDatabase = "poweron_app"   # hart-codiert pro Interface
    self.db = DatabaseConnector(
        host=APP_CONFIG.get("DB_HOST"),
        database=dbDatabase,
        user=APP_CONFIG.get("DB_USER"),
        password=APP_CONFIG.get("DB_PASSWORD_SECRET"),
        port=APP_CONFIG.get("DB_PORT")
    )

setUserContext()

Bindet Benutzer und RBAC an die Instanz:

def setUserContext(self, currentUser, mandateId):
    self.currentUser = currentUser
    self.userId = currentUser["id"]
    self.mandateId = mandateId
    self.rbac = RbacClass(self.db, dbApp=dbApp)
    self.db.updateContext(self.userId)

RBAC-Besonderheit: poweron_app ist Sonderfall (dbApp=self.db), weil RBAC-Regeln selbst in poweron_app liegen. Alle anderen Interfaces nutzen getRootDbAppConnector() um Rules aus der App-DB zu lesen:

dbApp = getRootDbAppConnector()
self.rbac = RbacClass(self.db, dbApp=dbApp)

getInterface() Factory

Cached pro Kontext:

Interface Cache-Key Ergebnis
App {mandateId}_{userId} AppObjects
Chat {mandateId}_{featureInstanceId}_{userId} ChatObjects
Billing {userId}_{mandateId} BillingObjects
Knowledge "default" (Singleton) KnowledgeObjects

DatabaseConnector

Auto-Initialisierung

Beim Erstellen eines DatabaseConnector (initDbSystem()):

1. _create_database_if_not_exists()
   -> Verbindet sich zu DB "postgres"
   -> Prueft pg_database auf Existenz
   -> CREATE DATABASE "{name}" falls fehlend

2. _create_tables()
   -> Erstellt nur die _system Registry-Tabelle
   -> Applikations-Tabellen werden lazy durch Interfaces erzeugt

3. _connect()
   -> psycopg2-Verbindung zur Ziel-DB

4. _initializeSystemTable()
   -> _ensureTableExists(SystemTable)

Lazy Table Creation

Tabellen werden bei erstem Zugriff automatisch aus Pydantic-Modellen erzeugt (_ensureTableExists(model_class)):

  • Tabellenname = Python-Klassenname des Pydantic-Modells (z.B. Role, AccessRule, UserMandate)
  • Spalten werden aus Modellfeldern abgeleitet
  • JSONB fuer komplexe Typen (dict, list, Pydantic-Submodelle)
  • vector fuer pgvector-Felder (Knowledge-Store)
  • Additive Migration: Wenn die Tabelle existiert, werden fehlende Spalten automatisch hinzugefuegt. Bestehende Spalten werden nicht geaendert oder entfernt.

Connector-Caching

_get_cached_connector(host, database, port)

Wiederverwendet einen DatabaseConnector pro Datenbank-Identitaet (host:database:port). Genutzt von App, Management, Knowledge. Chat und Billing instanziieren direkt (kein Cache).

userId Context

userId wird ueber eine contextvar am Connector gesetzt (updateContext(userId)). Damit werden System-Felder (_createdBy, _updatedBy) automatisch befuellt.


RBAC-Integration in DB-Abfragen

Die RBAC-Schicht greift direkt in Datenbank-Abfragen ein:

Kern-Funktionen in interfaceRbac.py

Funktion Zweck
getRecordsetWithRBAC() Listet Datensaetze mit RBAC-Filter in SQL WHERE
buildRbacWhereClause() Uebersetzt Access Levels in SQL-Bedingungen
buildDataObjectKey() Baut Keys wie data.uam.UserInDB fuer Rule-Lookup
TABLE_NAMESPACE Mapping von Modellnamen zu logischen Namespaces

Namespace-Mapping

TABLE_NAMESPACE ordnet Pydantic-Modellnamen logischen Bereichen zu:

Namespace Modelle (Beispiele)
uam UserInDB, UserMandate, Role, AccessRule
chat ChatHistory, ChatMessage
files FileRecord, FileFolder
feature.trustee TrusteePosition, TrusteeDocument
feature.workspace Workspace-spezifische Modelle

SQL-Filter nach Access Level

Level SQL WHERE
a (ALL) Kein Filter
m (MANDATE) mandateId = :mandateId
o (OWN) _createdBy = :userId
n (NONE) 1=0 (kein Ergebnis)

System-Felder

Jedes PowerOnModel erbt automatisch System-Felder:

Feld Beschreibung Schutz
id UUID, auto-generiert Immutable
_createdBy userId des Erstellers Immutable
_createdAt Zeitstempel Erstellung Immutable
_updatedBy userId der letzten Aenderung Auto-gesetzt
_updatedAt Zeitstempel letzte Aenderung Auto-gesetzt

Felder mit fuehrendem _ sind fuer Anwendungs-CUD geschuetzt -- der Connector erzwingt das unabhaengig von Access Rules.


Feature-DB-Registrierung

Features registrieren sich nicht in einer zentralen DB-Liste. Stattdessen:

  1. registry.pyregisterAllFeaturesInCatalog() laedt Feature-Main-Module
  2. Jedes Feature-Main definiert seinen FEATURE_CODE und dbDatabase
  3. Der Datenbank-Name wird in _initializeDatabase() des Feature-Interfaces gesetzt
  4. Der DatabaseConnector erzeugt die DB automatisch beim ersten Zugriff

Admin-Sicht

routeSecurityAdmin.py bietet eine API, die alle poweron_%-Datenbanken aus PostgreSQL auflistet -- fuer Systemadministration und Diagnostik.


Schluessel-Dateien

Thema Pfad
PostgreSQL Connector gateway/modules/connectors/connectorDbPostgre.py
App-DB Interface gateway/modules/interfaces/interfaceDbApp.py
Chat-DB Interface gateway/modules/interfaces/interfaceDbChat.py
Management-DB Interface gateway/modules/interfaces/interfaceDbManagement.py
Knowledge-DB Interface gateway/modules/interfaces/interfaceDbKnowledge.py
Billing-DB Interface gateway/modules/interfaces/interfaceDbBilling.py
Subscription Interface gateway/modules/interfaces/interfaceDbSubscription.py
RBAC in DB-Schicht gateway/modules/interfaces/interfaceRbac.py
Feature-Interface (Template) gateway/modules/interfaces/interfaceFeatures.py
Bootstrap / DB-Seed gateway/modules/interfaces/interfaceBootstrap.py
DB-Migration Script gateway/scripts/script_db_export_migration.py
Admin DB-Listing gateway/modules/routes/routeSecurityAdmin.py
Datenmodelle (Pydantic) gateway/modules/datamodels/