Echtzeit-Ereignisse-Kochbuch - Signal-WS + Server-Webhooks.
Zwei sich ergaenzende Ereignis-Familien. Familie 1 ist der Signal-WebSocket (wss://<tenant>/signal.ashx) - latenzarme Raum- und Anrufzustaende, genutzt von Browser-SoftPhones und Ops-Dashboards. Familie 2 sind serverseitige HTTP-Webhooks (POST an Ihren Endpunkt), registriert in webhooks-admin.html - dauerhaft, mit Retry, HMAC-signiert. European Digital Identity Wallet-Sitzungsereignisse laufen ueber denselben Webhook-Dispatcher.
Familie 1 - Signal-WebSocket
Endpunkt: wss://<tenant>/signal.ashx?room=<room>&name=<peer>. Kein Bearer erforderlich - Mandantenbindung und IpAllowGate schuetzen den Socket. Vom Server emittierte type-Werte im Livecode verifiziert:
| Ereignis-Typ | Payload-Form | Ausloesebedingung | Status |
|---|---|---|---|
| welcome | {type,peers[],mode,room} | Sent to a joining peer after admission. | LIVE |
| peer-joined | {type,peer:{id,name,role}} | Broadcast when a new peer enters the room. | LIVE |
| peer-left | {type,peer:{id,name}} | Broadcast when a peer disconnects. | LIVE |
| mode-changed | {type,mode:mesh|sfu} | Broadcast when the room flips mesh<->SFU. | LIVE |
| ring | {type,from,room} | Sent to a callee to trigger ringing UI. | LIVE |
| ring-cancelled | {type,reason} | Sent when the caller aborts before answer. | LIVE |
| ring-cleared | {type} | Sent when the room clears an active ring state. | LIVE |
| dial-result | {type,ok,error?} | Result of a bridge-side dial attempt. | LIVE |
| office-registered | {type,user,expires} | SoftPhone registration ack. | LIVE |
| office-call-result | {type,ok,error?} | Result of a SoftPhone outbound-call attempt. | LIVE |
| office-call-answered | {type,peer} | Callee answered a SoftPhone call. | LIVE |
| office-call-timeout | {type,reason} | Callee did not answer in time. | LIVE |
| sfu-answer | {type,sdp} | SFU SDP answer to a publisher offer. | LIVE |
| sfu-subscribe-answer | {type,sdp,participantId} | SFU SDP answer to a subscribe offer. | LIVE |
| sfu-offer-failed | {type,error} | SFU publisher offer was rejected. | LIVE |
| sfu-subscribe-failed | {type,error} | SFU subscribe offer was rejected. | LIVE |
| signal | {type,payload} | Generic relay frame (SDP/ICE). | LIVE |
| knock | {type,peer} | Broadcast to admins when a peer knocks. | LIVE |
| knock-pending | {type} | Sent to a knocker while waiting for admit. | LIVE |
| denied | {type,reason?} | Sent to a peer whose knock was denied. | LIVE |
| dup-ip-warning | {type,ip} | Broadcast when two peers share source IP. | LIVE |
| breakout-list | {type,rooms[]} | Sent when breakout rooms are (re)listed. | LIVE |
| breakout-assigned | {type,room} | Sent to a peer moved into a breakout. | LIVE |
| breakout-end | {type} | Broadcast when a breakout ends. | LIVE |
| breakout-rejected | {type,reason} | Rejection of a breakout request. | LIVE |
| pong | {type} | Server reply to a client ping. | LIVE |
| error | {type,message} | Server-side error frame. | LIVE |
Snippet-Matrix
| Sprache | Bibliothek | Rezept | Snippet |
|---|---|---|---|
| Browser JS | native WebSocket | Oeffnen | signal-ws-browser.js |
| Node.js | ws | Oeffnen | signal-ws-nodejs.js |
| Python | websockets | Oeffnen | signal-ws-python.py |
| Go | gorilla/websocket | Oeffnen | signal-ws-go.go |
| .NET | System.Net.WebSockets | Oeffnen | signal-ws-dotnet.cs |
Browser JS Rezept
native WebSocket. Rohdatei laden: signal-ws-browser.js
Node.js Rezept
Python Rezept
websockets. Rohdatei laden: signal-ws-python.py
Go Rezept
gorilla/websocket. Rohdatei laden: signal-ws-go.go
.NET Rezept
System.Net.WebSockets. Rohdatei laden: signal-ws-dotnet.cs
Familie 2 - Server-Webhooks
Die Empfangsseite ist im Webhook-Kochbuch beschrieben. Unten der ehrliche Ereigniskatalog mit LIVE-/RESERVED-Status:
| Ereignisname | Payload-Form | Status |
|---|---|---|
| call.started | call payload | LIVE |
| call.answered | call payload | LIVE |
| call.ended | call payload | LIVE |
| call.ice.connected | call payload | LIVE |
| call.transferred | call payload | LIVE |
| transcript.saved | transcript payload | LIVE |
| outbound-ai.finished | outbound payload | LIVE |
| sfu.publisher.connected | publisher payload | LIVE |
| sfu.subscriber.connected | subscriber payload | LIVE |
| room.cascade.promoted | room payload | LIVE |
| room.cascade.demoted | room payload | LIVE |
| room.cascade.failed | room payload | LIVE |
| room.peer.joined | peer payload | LIVE |
| room.peer.left | peer payload | LIVE |
| room.bandwidth.degraded | room payload | LIVE |
| sfu.offer.received | offer payload | LIVE |
| sfu.subscribe.received | subscribe payload | LIVE |
Auth-Modell
WebSocket-Familie. Heute kein Bearer. Der Signal-WebSocket ist ueber den Request-Host mandantengebunden und ueber IpAllowGate geschuetzt; Einladungstokens (?tok=) dienen der Zulassung bei gesperrtem Raum. Webhook-Familie. Jeder POST traegt X-CodeB-Signature: sha256=<hex>. Das Verify-Muster ist im Webhook-Kochbuch dokumentiert.
Reconnect + Backoff
Alle fuenf Snippets nutzen dasselbe Muster: bei WS-Close wird backoff gewartet, dann neu verbunden. Start bei 1 Sekunde, jede weitere Fehlversuch verdoppelt, Deckel bei 30 Sekunden. Bei erfolgreichem Open zuruecksetzen.
RASP-Posture
Beide Endpunkte setzen serverseitig durch: Rate-Limits pro Mandant in signal.ashx, IpAllowGate vor WS-Accept, Algorithmen-Allowlist auf HMAC-Signaturen, Mandantenisolation via Host-Header und laute [SIGNAL-*]-, [WEBHOOK-*]-, [api-key-diag]-Diagnosen an jedem Zweig. Anomalien werden inline protokolliert, nicht verschluckt.
NIS2 / DORA / CRA
Echtzeit-Signalisierung und Webhook-Streams unterstuetzen NIS2-Erkennungspflichten (nahezu Echtzeit-Signal in ein SIEM) und die DORA-Betriebsresilienz-Ueberwachung. Die CRA-Auditierbarkeit auf Produktseite wird durch mandantenbezogene, HMAC-signierte Webhook-Zustellung und laute Diagnosen an jedem Zweig getragen.
FAQ
Strukturierte Antworten sind im Schema-Block oben eingebettet.