The rules live in the domain
Event lifecycle, organizer permissions and joining rules sit in a pure domain layer. FastAPI only parses requests and calls use cases, so the rules are tested without a server.
HTTP is the source of truth
Every change goes through the REST API and is committed first. Only then does one WebSocket channel notify every open client, which maps the notification into its own state. A notification a client cannot read makes it reload from the API.
A written contract for the live channel
The WebSocket messages are specified in an AsyncAPI 3.1 document, so the frontend and any other client build against the same contract.
Honest about scale
The live channel runs inside one service instance. The documentation names the next step to scale it out, a shared broker such as Redis Pub/Sub or PostgreSQL LISTEN/NOTIFY, instead of pretending the limit is not there.