feat: Notruf-Eskalation per SMS/Anruf (provider-agnostischer Webhook)
Zweiter Benachrichtigungskanal neben der E-Mail: bei einem Notruf geht zusätzlich ein JSON-POST an EMERGENCY_WEBHOOK_URL mit Kanälen (sms,call), Kontakt-Telefonnummern und fertigen SMS-/Anruf-Texten. Den konkreten Gateway (Twilio, seven.io, sipgate, eigener Dienst) verdrahtet der Empfänger dahinter — kein Provider-Lock-in im Code. - config: EMERGENCY_WEBHOOK_URL aktiviert + _TOKEN (Bearer), _CONTACT_PHONE (CSV/E.164), _WEBHOOK_CHANNELS (default sms,call) - emergency.py: async httpx-POST (best effort), Telefon-Auflösung analog zur E-Mail (Pref emergency_phones > Default), notified = email OR webhook; Hinweise kanal-neutral formuliert; Response um webhook_sent + channels ergänzt - Tests: Webhook-Versand inkl. Payload/Bearer-Header + "ohne URL kein POST" - Doku: §10 + Env-Var-Tabelle aktualisiert (zwei Kanäle, Payload-Format) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9cfaaab7b0
commit
1816a26734
4 changed files with 209 additions and 38 deletions
|
|
@ -2011,31 +2011,56 @@ unzuverlässig (Fehlalarme **wie** verpasste Notfälle) und intransparent. Ein N
|
|||
- Der Notruf wird protokolliert (Admin → System → **Notrufe**); der Nutzer erhält einen
|
||||
klaren Hinweis in seiner Sprache.
|
||||
|
||||
**Benachrichtigung (Testphase):** Ist SMTP konfiguriert, geht beim Notruf eine **E-Mail**
|
||||
an die Kontaktperson(en) (`EMERGENCY_CONTACT_EMAIL`). Ohne SMTP wird nichts versendet und
|
||||
der Nutzer sieht „ACHTUNG: Es ist noch keine Benachrichtigung eingebaut.". SMS/Anruf folgen
|
||||
später.
|
||||
**Benachrichtigung — zwei unabhängige Kanäle (best effort):**
|
||||
|
||||
1. **E-Mail (SMTP):** Ist `SMTP_HOST` gesetzt, geht eine E-Mail an die Kontaktperson(en)
|
||||
(`EMERGENCY_CONTACT_EMAIL`; pro Nutzer übersteuerbar via Pref `emergency_contacts`).
|
||||
2. **SMS/Anruf (provider-agnostischer Webhook):** Ist `EMERGENCY_WEBHOOK_URL` gesetzt, geht
|
||||
zusätzlich ein JSON-POST dorthin — mit den angefragten Kanälen, den Telefonnummern
|
||||
(`EMERGENCY_CONTACT_PHONE`; pro Nutzer via Pref `emergency_phones`) und **fertigen
|
||||
SMS-/Anruf-Texten**. Den konkreten Gateway (Twilio, seven.io, sipgate, eigener Dienst …)
|
||||
verdrahtet man hinter dem Webhook; `EMERGENCY_WEBHOOK_TOKEN` schützt ihn optional per
|
||||
`Authorization: Bearer <token>`.
|
||||
|
||||
Geht über **mindestens einen** Kanal etwas raus, sieht der Nutzer „Hilfe wurde verständigt …",
|
||||
sonst „ACHTUNG: Es ist noch keine Benachrichtigung eingebaut.".
|
||||
|
||||
```bash
|
||||
EMERGENCY_CONTACT_EMAIL=dieter.schlueter@linix.de # Default-Kontaktperson
|
||||
SMTP_HOST= # ohne Host kein Versand — KEINE Inline-Kommentare hinter Werten!
|
||||
EMERGENCY_CONTACT_EMAIL=dieter.schlueter@linix.de # Default-Kontaktperson (E-Mail)
|
||||
SMTP_HOST= # ohne Host kein E-Mail-Versand — KEINE Inline-Kommentare hinter Werten!
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=
|
||||
SMTP_PASSWORD=
|
||||
SMTP_FROM= # muss dem SMTP_USER gehören (sonst 553 Sender rejected)
|
||||
SMTP_STARTTLS=true
|
||||
EMERGENCY_WEBHOOK_URL= # optional, für spätere Eskalation
|
||||
EMERGENCY_WEBHOOK_URL= # SMS/Anruf-Eskalation: JSON-POST hierhin (leer = aus)
|
||||
EMERGENCY_WEBHOOK_TOKEN= # optional -> Authorization: Bearer <token>
|
||||
EMERGENCY_CONTACT_PHONE= # Default-Telefonnummer(n), CSV, E.164 (+49…)
|
||||
EMERGENCY_WEBHOOK_CHANNELS=sms,call # angefragte Kanäle im Payload
|
||||
```
|
||||
|
||||
Das POST-Payload, das der Gateway-Empfänger bekommt:
|
||||
```json
|
||||
{
|
||||
"event": "emergency", "category": "manual", "source": "voice-assistant",
|
||||
"timestamp": "2026-06-25T…Z", "language": "de",
|
||||
"user": {"id": "…", "name": "…"},
|
||||
"channels": ["sms", "call"],
|
||||
"phones": ["+4915112345678"],
|
||||
"message": {"sms": "NOTRUF: …", "call": "Achtung. …"}
|
||||
}
|
||||
```
|
||||
|
||||
Auslösen per API (z. B. zum Testen):
|
||||
```bash
|
||||
curl -s -X POST $URL/api/emergency -H 'Content-Type: application/json' \
|
||||
-d '{"language":"de"}' | jq
|
||||
# → {"category":"manual","notice":"…","email_sent":true|false}
|
||||
# → {"category":"manual","notice":"…","email_sent":…,"webhook_sent":…,"channels":[…]}
|
||||
```
|
||||
|
||||
> ⚠️ **Wichtig:** Der Notruf ist **kein Ersatz** für einen echten Rettungsdienst. In der
|
||||
> Testphase ist die Zustellung nur E-Mail (best effort, abhängig vom Mailserver).
|
||||
> ⚠️ **Wichtig:** Der Notruf ist **kein Ersatz** für einen echten Rettungsdienst. Die
|
||||
> Zustellung ist best effort und hängt vom Mailserver bzw. dem hinter dem Webhook
|
||||
> verdrahteten SMS/Anruf-Gateway ab.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -2295,7 +2320,10 @@ Logs: Terminal von `make run`. Mehr Details: `LOG_LEVEL=debug` in `.env`.
|
|||
| `SMTP_USER` / `SMTP_PASSWORD` | (leer) | SMTP-Zugangsdaten |
|
||||
| `SMTP_FROM` | (leer → `SMTP_USER`) | Absender (muss dem SMTP_USER gehören) |
|
||||
| `SMTP_STARTTLS` | `true` | STARTTLS verwenden |
|
||||
| `EMERGENCY_WEBHOOK_URL` | (leer) | optionaler Webhook (spätere Eskalation) |
|
||||
| `EMERGENCY_WEBHOOK_URL` | (leer) | SMS/Anruf-Eskalation: JSON-POST hierhin (leer = aus) |
|
||||
| `EMERGENCY_WEBHOOK_TOKEN` | (leer) | optional → `Authorization: Bearer <token>` für den Webhook |
|
||||
| `EMERGENCY_CONTACT_PHONE` | (leer) | Default-Telefonnummer(n) für SMS/Anruf, CSV, E.164 |
|
||||
| `EMERGENCY_WEBHOOK_CHANNELS` | `sms,call` | im Payload angefragte Kanäle (CSV) |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue