wiki/d-guides/coding-conventions.md
2026-04-10 12:33:19 +02:00

6.4 KiB

Coding-Konventionen

Naming

  • Alle internen Funktionen beginnen mit _ Prefix (nicht exportierbar)
  • camelCase fuer Variablen und Funktionsnamen (kein snake_case)
  • PascalCase fuer Klassen und Pydantic-Models
  • Dateien: camelCase fuer Module (z.B. mainServiceAi.py, routeBilling.py)

Frontend (React/TypeScript)

  • Keine Browser-Dialoge (alert, confirm, prompt) -- stattdessen useConfirm() / usePrompt() Hooks
  • CSS Modules fuer Styling
  • Hooks-Pattern fuer State und API-Zugriffe (useApiRequest, useBilling, etc.)
  • Fehler propagieren -- keine stillen Fallbacks bei kritischen Pfaden

i18n-Pflicht: t() fuer alle UI-Texte

Jeder sichtbare Text im UI (Labels, Buttons, Placeholders, Tooltips, Fehlermeldungen) muss mit t() getaggt werden. Hardcodierte deutsche Strings im JSX sind nicht erlaubt.

import { useLanguage } from '../../providers/language/LanguageContext';

const { t } = useLanguage();

// Einfacher Text
t('Speichern')

// Mit Variablen-Interpolation
t('{count} Eintraege gefunden', { count: String(total) })

// Gleicher Text, anderer Kontext → Klammer als Kontext-Hinweis
t('Offen (Status)')   // vs.  t('Offen (Zustand)')
  • Key = deutscher Klartext (kein Dot-Notation-Schema)
  • Kein Plural-Framework -- separate Keys verwenden: t('1 Eintrag') vs. t('{count} Eintraege', { count })
  • Fehlende Keys erscheinen als [Text] (eckige Klammern = unuebersetzt)
  • Admin synchronisiert Sprachsets ueber Administration → System → UI-Sprachen → "Alle aktualisieren"

Backend (FastAPI/Python)

  • Pydantic-Models als einzige Quelle fuer UI-Feld-Definitionen
  • PowerOnModel als Basis mit System-Audit-Feldern (sysCreatedAt, sysCreatedBy, sysModifiedAt, sysModifiedBy)
  • Fehler propagieren -- Exceptions explizit werfen, nicht schlucken
  • Config ueber APP_CONFIG (aus modules/shared/configuration.py)

i18n-Pflicht: t() fuer alle UI-sichtbaren Gateway-Texte

Jeder Text der im Frontend angezeigt wird (HTTPException-Details, API-Response-Messages, Erfolgs-/Fehlermeldungen) muss mit t() getaggt werden.

from modules.shared.i18nRegistry import t

# Fehlermeldung (context automatisch = "api")
raise HTTPException(status_code=403, detail=t("Zugriff verweigert", "api.routeSecurity",
    "Fehlermeldung bei fehlendem Zugriff"))

# Erfolgsmeldung
return {"message": t("Datei erfolgreich hochgeladen", "api.routeFiles",
    "Bestaetigung nach Datei-Upload")}

Nicht mit t() taggen: Log-Eintraege, AI-Prompts, interne technische Fehlermeldungen.

Fuer Route-Module gibt es den Shorthand apiRouteContext:

from modules.shared.i18nRegistry import apiRouteContext
routeApiMsg = apiRouteContext("routeBilling")

raise HTTPException(status_code=403, detail=routeApiMsg("Zugriff verweigert"))

Pydantic-Models: @i18nModel Decorator Pflicht

Jedes Pydantic-Model das im UI angezeigt wird (Tabellen, Formulare) muss den @i18nModel Decorator haben. Feld-Labels werden in json_schema_extra["label"] definiert.

from modules.shared.i18nRegistry import i18nModel

@i18nModel("Benutzer")
class User(PowerOnModel):
    name: str = Field(
        description="Full name of the user",
        json_schema_extra={"label": "Name", "frontend_type": "text"}
    )
    email: str = Field(
        description="Email address for login and notifications",
        json_schema_extra={"label": "E-Mail-Adresse", "frontend_type": "text"}
    )
  • @i18nModel("Deutscher Modelname") -- AI-Kontext kommt automatisch aus dem Class-Docstring
  • json_schema_extra={"label": "Deutscher Feldname"} -- Pflicht fuer jedes UI-sichtbare Feld
  • Field(description=...) -- wird als AI-Kontext fuer die Uebersetzung verwendet
  • Kein registerModelLabels() mehr verwenden (entfernt)

Feature-Module: Labels als deutsche Basis-Strings

Neue DATA_OBJECTS, RESOURCE_OBJECTS und UI_OBJECTS Labels verwenden deutsche Klartext-Strings als Basis-Key. Bestehende {en, de, fr}-Dicts werden beim Boot automatisch ueber _registerRbacLabels() registriert (Kontext rbac.data, rbac.resource, rbac.role, rbac.quickaction). Fuer neue Eintraege: de-Text als Basis-Key verwenden, en/fr im Dict fuer Legacy-Anzeige bis vollstaendige Migration.

DATA_OBJECTS = [
    {
        "objectKey": "data.uam.UserInDB",
        "label": {"en": "User", "de": "Benutzer", "fr": "Utilisateur"},
        "meta": {"table": "UserInDB", "namespace": "uam"}
    },
]

Die de-Texte erscheinen automatisch im xx-Basisset und koennen per AI uebersetzt werden.

Projektstruktur Gateway

gateway/
  app.py                          # FastAPI-App, Middleware, Startup
  config.ini                      # Statische Konfiguration
  modules/
    auth/                         # JWT, OAuth, CSRF, Authentication
    datamodels/                   # Pydantic-Models (zentrale Quelle)
    features/                     # Feature-Module (workspace, automation, ...)
      <name>/
        main<Name>.py             # FEATURE_CODE, Registrierung
        routeFeature<Name>.py     # HTTP-Endpunkte
        interfaceFeature<Name>.py # DB-Interface
        datamodelFeature<Name>.py # Feature-spezifische Models
    interfaces/                   # DB-Interfaces (CRUD, Queries)
    routes/                       # Core-Routes (billing, admin, GDPR, ...)
    security/                     # RBAC-Engine
    serviceCenter/
      core/                       # serviceSecurity, serviceUtils, serviceStreaming
      services/                   # serviceAi, serviceChat, serviceAgent, ...
      registry.py                 # Service-Registrierung und Dependencies
    shared/                       # configuration.py, Utilities
    system/                       # registry.py (Feature-Discovery)
    workflows/
      methods/                    # Unified Action Library
      processing/                 # WorkflowProcessor, Modes
      automation/                 # v1 Runtime
      automation2/                # v2 Engine
    connectors/                   # Externe Systeme (DB, SharePoint, Jira, ...)
    aicore/                       # AI-Provider-Plugins, Model-Selector

Anti-Patterns

  • Keine impliziten Type-Conversions in API-Responses
  • Keine DB-Queries in Route-Handlern (immer ueber Interfaces)
  • Kein direkter os.environ-Zugriff -- immer APP_CONFIG
  • Keine hartkodierten Secrets -- verschluesselt in Env-Dateien