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

156 lines
6.4 KiB
Markdown

<!-- status: canonical -->
<!-- lastReviewed: 2026-04-05 -->
# 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.
```tsx
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.
```python
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`:
```python
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.
```python
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.
```python
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