feat: Tageskontingent und Notfall-Eskalation (#6)
- Quota (app/quota.py): Anfragen pro Nutzer/Tag (usage-Tabelle), DAILY_REQUEST_LIMIT, pro Nutzer via prefs uebersteuerbar; 429 (REST) bzw. error-Event (WS); Metrik - Notfall (app/safety/emergency.py): heuristische Erkennung (de/en); Log im Store (emergency_events) + optionaler Webhook (best-effort) + X-Emergency/emergency-Event; Metrik emergency_total; Notfaelle umgehen das Kontingent - verdrahtet in chat/speak/transcribe + WS-Turns - Tests: 64 gruen (+6); Doku aktualisiert (README, BEDIENUNGSANLEITUNG, Architektur, .env.example) Hinweis: Notfall-Erkennung ist eine Heuristik (kein Lebensretter); erkannte Texte sind sensibel -> DSGVO beachten. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6422444017
commit
1eb79c1f09
14 changed files with 378 additions and 2 deletions
|
|
@ -7,7 +7,9 @@ from app.dependencies import (
|
|||
resolve_route,
|
||||
build_orchestrator,
|
||||
resolve_input_endpoint,
|
||||
get_store,
|
||||
)
|
||||
from app.quota import enforce_quota, record_usage, QuotaExceededError
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
|
@ -39,6 +41,12 @@ async def transcribe(
|
|||
except RoutingError as exc:
|
||||
raise HTTPException(status_code=422, detail=str(exc))
|
||||
|
||||
store = get_store()
|
||||
try:
|
||||
enforce_quota(user, store)
|
||||
except QuotaExceededError as exc:
|
||||
raise HTTPException(status_code=429, detail=str(exc))
|
||||
|
||||
content = await file.read()
|
||||
suffix = (file.filename or "audio.wav").rsplit(".", 1)[-1].lower()
|
||||
|
||||
|
|
@ -52,4 +60,6 @@ async def transcribe(
|
|||
except Exception as exc:
|
||||
raise HTTPException(status_code=502, detail=str(exc))
|
||||
|
||||
record_usage(user, store, len(trace.raw_transcript or ""))
|
||||
|
||||
return {"route": route.as_dict(), "trace": trace.model_dump()}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue