feat: Cloud-Fundament - Auth, Persistenz und Mandanten-Trennung
- SQLite-Store (app/store.py) hinter Store-Interface: Nutzer + Sessions persistent - Bearer-Token-Auth (app/auth.py); Nutzerverwaltung via Admin-Key (POST /api/admin/users) - GET /api/me, PUT /api/me/prefs (dauerhafte Nutzer-Praeferenzen) - chat/speak/transcribe/sessions auth-geschuetzt; Mandanten-Trennung (fremde Session -> 403) - Route-Aufloesung: Defaults < Profil < ENV < Nutzer-Prefs < Session < Request - SessionManager (in-memory) durch Store ersetzt - AUTH_ENABLED-Schalter (prod an, dev/Tests aus); DB_PATH/ADMIN_API_KEY - Doku aktualisiert (README, BEDIENUNGSANLEITUNG, Architektur, deploy-env); data/ gitignored - Tests: 29 gruen (Auth, Mandanten, Persistenz, Routing) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
293ed257db
commit
e0e69fdf15
22 changed files with 625 additions and 57 deletions
31
README.md
31
README.md
|
|
@ -14,7 +14,8 @@ Praktische Bedienung: [`BEDIENUNGSANLEITUNG.md`](BEDIENUNGSANLEITUNG.md).
|
|||
- **Pipeline mit getrennter Semantik/Sprache:** STT → Input-Cleaner → LLM → Spoken-Adapter → TTS-Normalizer → TTS
|
||||
- **Provider austauschbar** über Registry (OpenRouter remote; faster-whisper/piper/chatterbox als lokale Stubs)
|
||||
- **Geschichtete Konfiguration** mit Profilen (`local-dev` / `hybrid` / `cloud`)
|
||||
- **Routing auf jeder Ebene:** Default → Profil → ENV → Session → Request
|
||||
- **Routing auf jeder Ebene:** Default → Profil → Nutzer → Session → Request
|
||||
- **Authentifizierung** (Bearer-Token) + persistente Nutzer/Sessions (SQLite)
|
||||
- **REST-API** für Chat, Transkription, Sprachausgabe, Geräte, Sessions, Config
|
||||
- **Ohne Secrets im Code** — API-Keys nur über die Umgebung
|
||||
|
||||
|
|
@ -80,6 +81,9 @@ Aktive Konfiguration prüfen: `curl http://localhost:8080/api/config`.
|
|||
| `GET /api/devices` | verfügbare Audio-Endpunkte + Capabilities |
|
||||
| `POST /api/sessions/{id}/route` | Geräte/Provider/Sprache je Session setzen |
|
||||
| `GET /api/config` | aktives Profil + aufgelöste Route (ohne Secrets) |
|
||||
| `POST /api/admin/users` | Nutzer anlegen (Admin-Key) → Token einmalig |
|
||||
| `GET /api/me` | aktueller Nutzer + Präferenzen |
|
||||
| `PUT /api/me/prefs` | dauerhafte Routing-Präferenzen des Nutzers setzen |
|
||||
|
||||
Beispiel (Sprachausgabe an den Test-Loopback, lokaler TTS-Stub):
|
||||
|
||||
|
|
@ -91,6 +95,31 @@ curl -X POST http://localhost:8080/api/speak \
|
|||
|
||||
Unbekannter Endpunkt/Provider → `HTTP 422` mit Klartext-Hinweis.
|
||||
|
||||
## Authentifizierung
|
||||
|
||||
Standardmäßig (`AUTH_ENABLED=true`) sind `chat`/`speak`/`transcribe`/`sessions`/`me`
|
||||
durch ein **Bearer-Token pro Nutzer** geschützt. Nutzer/Sessions werden in SQLite
|
||||
persistiert (`DB_PATH`, Default `data/voice-assistant.db`).
|
||||
|
||||
```bash
|
||||
# 1) Nutzer anlegen (Admin-Key aus der Umgebung) — Token erscheint EINMALIG
|
||||
export ADMIN_API_KEY=ein-langes-geheimnis
|
||||
curl -X POST http://localhost:8080/api/admin/users \
|
||||
-H "X-Admin-Key: $ADMIN_API_KEY" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"display_name":"Oma Anna"}'
|
||||
# -> {"user_id":"…","display_name":"Oma Anna","token":"…"}
|
||||
|
||||
# 2) Mit dem Token aufrufen
|
||||
curl http://localhost:8080/api/me -H "Authorization: Bearer <TOKEN>"
|
||||
```
|
||||
|
||||
Dauerhafte Präferenzen pro Nutzer (`PUT /api/me/prefs`) fließen in die Route-Auflösung
|
||||
ein (Ebene zwischen Profil und Session). Fremde Sessions → `HTTP 403`.
|
||||
|
||||
> **Lokale Entwicklung:** `AUTH_ENABLED=false` setzen — dann gilt ein anonymer
|
||||
> Standardnutzer und es ist kein Token nötig.
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue