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:
registry.py→registerAllFeaturesInCatalog()laedt Feature-Main-Module- Jedes Feature-Main definiert seinen
FEATURE_CODEunddbDatabase - Der Datenbank-Name wird in
_initializeDatabase()des Feature-Interfaces gesetzt - Der
DatabaseConnectorerzeugt 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/ |