commit 5126decf364589a4fd841878ea73a0a4abff7e80
Author: Bjoern Runden
Date: Thu Jun 18 08:38:37 2026 +0200
init
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fdb3fe6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,31 @@
+# kbcrm
+
+[Kurzbeschreibung folgt – Zweck und Ziel der Applikation]
+
+**Authentifizierung** vollständig an Zitadel delegiert. Lokale Datenhaltung,
+Benutzer- und Rollenverwaltung über SQLite.
+
+---
+
+## Technologie-Stack
+
+| Komponente | Technologie |
+|---|---|
+| Backend | Python Flask 2.x |
+| OIDC-Client | Authlib |
+| Datenbank | SQLite via SQLAlchemy |
+| IdP | Zitadel |
+| Produktion | Docker / gunicorn |
+
+---
+
+## Lokale Entwicklung
+
+```bash
+python3 -m venv venv
+source venv/bin/activate
+pip install -r requirements.txt
+cp .env.example .env # Zitadel-Credentials eintragen
+flask db-init # Schema initialisieren
+flask seed-db # Testdaten einspielen
+flask run # App startet auf http://localhost:5000
diff --git a/ai-context/AI-auth-vorgaben.md b/ai-context/AI-auth-vorgaben.md
new file mode 100644
index 0000000..73b267d
--- /dev/null
+++ b/ai-context/AI-auth-vorgaben.md
@@ -0,0 +1,138 @@
+# Zitadel-Einrichtung – Schritt-für-Schritt
+
+Zitadel-Instanz: **https://id.vmlx.de**
+
+Ziel dieser Anleitung: Das OIDC-Projekt **kbcrm** anlegen, drei Testrollen definieren,
+drei Testnutzer erstellen, ihnen Rollen zuweisen und die Zitadel-User-IDs
+(`sub`-Werte) für das DB-Seeding ermitteln.
+
+---
+
+## Schritt 1 – Zitadel-Projekt anlegen
+
+1. Login unter https://id.vmlx.de
+2. Linke Navigation → **Projekte** → **Neu anlegen**
+3. Name: `kbcrm` → Speichern
+4. Im Projekt-Detail unter **Einstellungen** folgende Optionen aktivieren:
+ - ☑ **Assert Roles on Authentication** (Rollen werden in Token geschrieben)
+ - ☑ **Check Authorization on Authentication** (Zugriff nur für zugewiesene Nutzer)
+
+---
+
+## Schritt 2 – Rollen anlegen
+
+Im Projekt → Tab **Rollen** → drei Rollen anlegen:
+
+| Anzeigename | Schlüssel (Key) |
+|---|---|
+| Admin | `Admin` |
+| Mitarbeiter | `Mitarbeiter` |
+| Kunde | `Kunde` |
+
+> Der Schlüssel (Key) muss **exakt** so geschrieben sein – er erscheint so im Token-Claim.
+
+---
+
+## Schritt 3 – OIDC-Anwendung anlegen
+
+Im Projekt → Tab **Anwendungen** → **Neu anlegen**
+
+| Feld | Wert |
+|---|---|
+| Name | `kbcrm-web` |
+| Typ | **Web** |
+| Auth-Methode | **Code** (Authorization Code mit Client Secret) |
+
+Nach dem Erstellen:
+- **Client-ID** und **Client-Secret** notieren → kommen in die `.env`
+- Unter **Redirect-URIs** eintragen:
+ - `http://localhost:5000/auth/callback` (Lokal)
+ - `https:///auth/callback` (Prod, falls zutreffend)
+- Unter **Post-Logout-Redirect-URIs** eintragen:
+ - `http://localhost:5000/`
+
+---
+
+## Schritt 4 – Testnutzer anlegen
+
+Navigation: **Nutzer** (oberste Ebene, nicht innerhalb eines Projekts) → **Neu anlegen**
+
+Drei Nutzer erstellen:
+
+| Name | E-Mail | Passwort | Zitadel-Rolle |
+|---|---|---|---|
+| Admin Test | admin@test.local | (eigenes PW) | Admin |
+| Mitarbeiter Test | ma@test.local | (eigenes PW) | Mitarbeiter |
+| Kunde Test | kunde@test.local | (eigenes PW) | Kunde |
+
+> Bei der Erstellung: **Passwort beim ersten Login ändern** deaktivieren empfohlen, damit Tests flüssig laufen.
+
+---
+
+## Schritt 5 – Rollen an Nutzer vergeben
+
+Für jeden Nutzer:
+
+1. **Nutzer** → Nutzer auswählen → Tab **Autorisierungen**
+2. → **Neu** → Projekt `kbcrm` wählen → entsprechende Rolle wählen → Speichern
+
+---
+
+## Schritt 6 – User-IDs (sub) ermitteln
+
+Die User-ID (Zitadel-`sub`) ist die interne Zitadel-Nutzer-ID, **nicht** die E-Mail.
+
+**Methode A – Zitadel-Konsole:**
+Nutzer auswählen → oben in der Detailansicht steht die **User-ID** (z. B. `236968807784841234`)
+
+**Methode B – Aus dem App-Log (nach Schritt 7):**
+Nach dem ersten Login loggt die App in stdout:
+```
+OIDC Login – sub: 236968807784841234 | email: admin@test.local | roles: ['Admin']
+```
+
+Alle drei Sub-Werte notieren für den nächsten Schritt.
+
+---
+
+## Schritt 7 – .env befüllen und DB seeden
+
+`.env` aus `.env.example` kopieren und befüllen:
+
+```bash
+cp .env.example .env
+```
+
+```env
+ZITADEL_CLIENT_ID=
+ZITADEL_CLIENT_SECRET=
+ZITADEL_DISCOVERY_URL=https://id.vmlx.de/.well-known/openid-configuration
+SECRET_KEY=
+```
+
+Dann in `app/__init__.py` die Platzhalter in `seed_db()` mit den echten Sub-Werten ersetzen:
+
+```python
+ADMIN_ID = "236968807784841234" # <-- echte Zitadel-User-ID
+MITARBEITER_ID = "..."
+KUNDE_ID = "..."
+```
+
+Anschließend seeden:
+
+```bash
+source venv/bin/activate
+flask seed-db
+```
+
+---
+
+## Discovery-URL verifizieren
+
+```bash
+curl https://id.vmlx.de/.well-known/openid-configuration | python3 -m json.tool
+```
+
+Wenn die Antwort ein JSON mit `issuer`, `authorization_endpoint` usw. ist, ist die URL korrekt.
+Sollte die URL nicht funktionieren, alternative probieren:
+`https://id.vmlx.de/oauth/v2/.well-known/openid-configuration`
diff --git a/ai-context/AI-operative_Vorgaben.md b/ai-context/AI-operative_Vorgaben.md
new file mode 100644
index 0000000..4b1bb47
--- /dev/null
+++ b/ai-context/AI-operative_Vorgaben.md
@@ -0,0 +1,41 @@
+# AI.md — Strukturvorgaben für neue Applikation
+
+**Autoren:** Björn Runden, Gerd Goldberg
+**Zweck dieses Dokuments:** Verbindliche strukturelle, betriebliche und infrastrukturelle Vorgaben für eine neue Python-Applikation. Applikationslogik, Routing und Frontend sind bewusst nicht Teil dieses Dokuments.
+
+---
+
+## 1. Technologie-Stack
+
+| Schicht | Technologie |
+|---|---|
+| Backend-Framework | Python Flask 2.x |
+| OIDC-Authentifizierung | Authlib (gegen Zitadel als externen IdP) |
+| Datenbank / ORM | SQLite + SQLAlchemy |
+| Konfiguration | 12-Factor-App via `.env`-Datei |
+| Produktions-Server | Gunicorn |
+| Container | Docker (`python:3.11-slim`), orchestriert via `docker-compose.yml` |
+
+---
+
+## 2. Verzeichnisstruktur
+
+```text
+.
+├── .gitignore
+├── .env
+├── .env.example
+├── requirements.txt
+├── docker-compose.yml
+├── Dockerfile
+├── wsgi.py
+├── data/ ← Datenbankverzeichnis (persistente SQLite-Datei, nicht im Image)
+└── app/
+ ├── __init__.py
+ ├── config.py
+ ├── database.py
+ ├── models.py
+ ├── auth.py
+ ├── routes.py
+ ├── templates/
+ └── static/
diff --git a/ai-context/strukturelle-vorgaben.md b/ai-context/strukturelle-vorgaben.md
new file mode 100644
index 0000000..2fc1c0b
--- /dev/null
+++ b/ai-context/strukturelle-vorgaben.md
@@ -0,0 +1,131 @@
+# Strukturelle Vorgaben – Quellcode-Konventionen
+
+Dieses Dokument legt verbindliche Konventionen für alle Quelldateien im Projekt fest.
+
+---
+
+## 1. Datei-Header
+
+Jede Quelldatei beginnt mit einem standardisierten Header. Der Header dient gleichzeitig als Modul-Docstring und wird von **Sphinx** zur automatischen Dokumentationserzeugung ausgewertet (Python-Äquivalent zu JavaDoc).
+
+### Python (`.py`)
+
+Der Header ist ein Modul-Docstring (triple-quoted) direkt am Dateianfang. Sphinx liest ihn automatisch aus:
+
+```python
+"""
+
+
+
+
+:author: Vorname Nachname
+:date: YYYY-MM-DD
+:version: 1.0
+"""
+```
+
+Pflichtfelder: `:author:`, `:date:`
+Optionale Felder: `:version:`, `:see:`, `:note:`
+
+### Jinja2 / HTML (`.html`)
+
+Jinja2-Kommentare (`{# ... #}`) werden vom Browser nicht gerendert und sind deshalb die richtige Wahl für Template-Header:
+
+```html
+{#
+ Datei: templates/beispiel.html
+ Autor: Vorname Nachname
+ Datum: YYYY-MM-DD
+ Zweck: Kurze Beschreibung, welche Seite/Komponente dieses Template rendert
+ und welche Jinja2-Variablen es erwartet.
+#}
+```
+
+Pflichtfelder: `Datei:`, `Autor:`, `Datum:`, `Zweck:`
+
+---
+
+## 2. Dokumentationserzeugung mit Sphinx
+
+Python bietet mit **Sphinx** ein mächtiges Werkzeug analog zu JavaDoc. Es liest Modul-Docstrings (inkl. `:author:`/`:date:`-Felder) und erzeugt daraus eine vollständige HTML-Dokumentation.
+
+### Einrichtung (einmalig)
+
+```bash
+pip install sphinx
+cd docs/
+sphinx-quickstart # Interaktiver Setup-Assistent
+```
+
+Im Setup-Assistenten:
+- `autodoc` aktivieren (liest Docstrings automatisch)
+- Projektname, Autor und Version eingeben
+
+Anschließend in `docs/conf.py` sicherstellen:
+
+```python
+extensions = [
+ "sphinx.ext.autodoc",
+ "sphinx.ext.viewcode", # Links zum Quellcode
+]
+```
+
+### Dokumentation aus dem `app/`-Verzeichnis einlesen
+
+```bash
+sphinx-apidoc -o docs/source/ app/
+```
+
+Dieser Befehl scannt alle `.py`-Dateien unter `app/` und erzeugt `.rst`-Stub-Dateien, die den Modul-Docstring und alle Klassen/Funktionen einbinden.
+
+### Dokumentation bauen
+
+```bash
+cd docs/
+make html
+# Ergebnis liegt unter: docs/_build/html/index.html
+```
+
+### Ablauf
+
+```
+Modul-Docstrings → sphinx-apidoc → .rst-Dateien → make html → HTML-Doku
+```
+
+> **Hinweis:** Für HTML-Templates gibt es kein Python-natives Doku-Tool. Die Header-Kommentare dienen dort als Inline-Dokumentation für Entwickler.
+
+---
+
+## 3. Template-Dateien
+
+Im Verzeichnis [`_templates/`](_templates/) liegen Vorlagen, von denen sich der Entwickler **jederzeit eine frische Kopie ziehen** kann:
+
+| Template | Verwendung |
+|---|---|
+| [`_templates/_template.py`](_templates/_template.py) | Neue Python-Quelldatei |
+| [`_templates/_template.html`](_templates/_template.html) | Neues Jinja2/HTML-Template |
+
+### Workflow: neue Datei aus Template erzeugen
+
+```bash
+# Python-Datei
+cp _templates/_template.py app/mein_modul.py
+
+# HTML-Template
+cp _templates/_template.html app/templates/meine_seite.html
+```
+
+Anschließend im kopierten File die Platzhalter (`<...>`) ersetzen.
+
+---
+
+## 4. Kurzreferenz – Pflichtfelder auf einen Blick
+
+| Feldname | Python (Docstring) | HTML (Kommentar) | Pflicht |
+|---|---|---|---|
+| Autor | `:author:` | `Autor:` | Ja |
+| Datum | `:date:` | `Datum:` | Ja |
+| Zweck/Titel | Erste Docstring-Zeile | `Zweck:` | Ja |
+| Version | `:version:` | – | Nein |
+| Dateiname | – | `Datei:` | Ja |