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
|
|
@ -11,7 +11,9 @@ from app.dependencies import (
|
|||
resolve_route,
|
||||
build_orchestrator,
|
||||
resolve_output_endpoint,
|
||||
get_store,
|
||||
)
|
||||
from app.quota import enforce_quota, record_usage, QuotaExceededError
|
||||
from app.schemas import SpeakRequest
|
||||
|
||||
router = APIRouter()
|
||||
|
|
@ -42,6 +44,12 @@ async def speak(
|
|||
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))
|
||||
|
||||
try:
|
||||
audio = await orchestrator.speak_only(
|
||||
payload.text,
|
||||
|
|
@ -49,6 +57,7 @@ async def speak(
|
|||
language=route.language,
|
||||
output=output,
|
||||
)
|
||||
record_usage(user, store, len(payload.text))
|
||||
|
||||
headers = {
|
||||
"Content-Language": route.language,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue