- Shipped
- August 21, 2026 at 11:55 PM UTC
- Author
- Kamo
- Commit
- 5cdee9d
Applies the policy at the three places a conversation can start or continue: session creation, member adds, and the send path. A room is not policed pair by pair -- the invite gate IS the direct-message gate, so you may bring someone into a room exactly when you could have messaged them, and a room that shrinks back to two blocked members is re-read as a direct message. Two pre-existing holes were directly under this work and are fixed with it. The send endpoint never checked that the sender belonged to the session, so any authenticated member could post into any session guid they could guess -- a policy gate would have been decorative without it. And typing indicators were published to a bare /topic/chat/typing that every connected client in the organization subscribed to; scoping them per session stops the leak and stops a separated pair from signalling to each other. Reply grants back "reply only while their window is open": the browser reports what it can see and the server decides, with a grace that outlives a missed beat and not a closed laptop. Their broadcast is per member and guarded, since a forged grant would unlock a composer the policy locked. The admin write is its own bean and its own transaction. On YugabyteDB a read after a write in one transaction raises 40001 and aborts everything around it, and a self-invoked @Transactional is not a boundary at all -- so the save reads before, writes, and reads again only once it has committed.