Entwickler-Kochbuch

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-TypPayload-FormAusloesebedingungStatus
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

SpracheBibliothekRezeptSnippet
Browser JSnative WebSocketOeffnensignal-ws-browser.js
Node.jswsOeffnensignal-ws-nodejs.js
PythonwebsocketsOeffnensignal-ws-python.py
Gogorilla/websocketOeffnensignal-ws-go.go
.NETSystem.Net.WebSocketsOeffnensignal-ws-dotnet.cs

Browser JS Rezept

native WebSocket. Rohdatei laden: signal-ws-browser.js

Node.js Rezept

ws. Rohdatei laden: signal-ws-nodejs.js

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:

EreignisnamePayload-FormStatus
call.startedcall payloadLIVE
call.answeredcall payloadLIVE
call.endedcall payloadLIVE
call.ice.connectedcall payloadLIVE
call.transferredcall payloadLIVE
transcript.savedtranscript payloadLIVE
outbound-ai.finishedoutbound payloadLIVE
sfu.publisher.connectedpublisher payloadLIVE
sfu.subscriber.connectedsubscriber payloadLIVE
room.cascade.promotedroom payloadLIVE
room.cascade.demotedroom payloadLIVE
room.cascade.failedroom payloadLIVE
room.peer.joinedpeer payloadLIVE
room.peer.leftpeer payloadLIVE
room.bandwidth.degradedroom payloadLIVE
sfu.offer.receivedoffer payloadLIVE
sfu.subscribe.receivedsubscribe payloadLIVE

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.

var backoff = 1000; ws.on('close', function(){ setTimeout(connect, backoff); backoff = Math.min(30000, backoff * 2); });

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.