Chat Events¶
Chat events provide real-time messaging between auction participants and staff during a live auction. Both events below are planned in the current server build; the socket chat.send and chat.typing contracts are part of the documented protocol but no route is registered yet.
Reference: rooms.md · errors.md · rate-limits.md
Event list¶
| Event | Direction | Status |
|---|---|---|
chat.send | Client → Server | Planned |
chat.typing | Client → Server | Planned |
Chat is delivered within a room (auction:<auctionId> by default). The server validates message size and rate, persists (when enabled), and rebroadcasts the message to every other member of the room.
chat.send¶
Description¶
Sends a chat message to the auction room. This is a command, so it follows the async CQRS protocol: the server returns command.acknowledged immediately and the message is delivered to the room via the server-pushed chat.created event (see protocol.md). The sender does not receive its own chat.created back.
Direction¶
Client → Server
Roles Allowed¶
All roles subscribed to the auction (participants and staff).
Permissions Required¶
chat:send (planned).
Request Schema¶
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | chat.send |
id | string | Yes | Command id; echoed as correlationId/causationId. |
data.auctionId | string | Yes | Auction cycle to which the message belongs. |
data.body | string | Yes | Message text, trimmed, max 2000 chars. |
data.clientMessageId | string | Yes | Client-generated id for idempotency and echo control. |
Response Schema¶
The command acknowledgement contains no business data; the message identity is carried by the chat.created server event.
Success Response¶
{
"id": "req_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
"type": "command.acknowledged",
"version": "1.0",
"source": "dichit-backend",
"timestamp": "2026-08-05T10:00:00.000Z",
"sequence": 1,
"correlationId": "req_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
"causationId": "req_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
"data": {
"command": "chat.send",
"status": "accepted"
}
}
Business failures after acceptance are pushed as command.failed with an errorCode and message.
Error Responses¶
| Code | Description |
|---|---|
FORBIDDEN | Caller not in the auction room or lacks chat:send. |
NOT_FOUND | Auction/cycle not found or not subscribed. |
BAD_REQUEST | body empty/too long, auctionId missing, clientMessageId missing. |
RATE_LIMITED | Chat rate limit exceeded (see rate-limits.md). |
Validation Rules¶
| Rule | Behaviour |
|---|---|
auctionId non-empty string | Required. |
body trimmed, 1–2000 chars | Required. |
clientMessageId non-empty string | Required for idempotency. |
Duplicate clientMessageId in window | Returns previous acknowledgement (idempotent). |
Example Request¶
{
"type": "chat.send",
"id": "req_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
"data": {
"auctionId": "cyc_01HQ5BWN3F9P5RX0W5X0W5X0W5X",
"body": "Best of luck, everyone!",
"clientMessageId": "msg_cl_1HQ5KYP1K7"
}
}
Broadcast Behaviour¶
After a successful chat.send, the server pushes a chat.created (planned) message to every other member of the auction:<auctionId> room (excluding the sender) with the full message payload. The same clientMessageId is echoed so clients can reconcile order with the acknowledgement.
Related Events¶
chat.typing- events/auction.md — room membership via
auction.subscribe.
Notes¶
- Implementation status: Planned.
- Messages are tied to the auction room; joining requires
auction.subscribe/room.joinwith the sameauctionId.
Best Practices¶
- Send
clientMessageIdto make retries safe. - Charge
chat.sendrate limit per user + per IP (see rate-limits.md).
chat.typing¶
Description¶
A lightweight typing indicator pushed to the room. Typing events are transient, short-lived, and rate-limited aggressively. They are not persisted.
Direction¶
Client → Server
Roles Allowed¶
All roles subscribed to the auction.
Permissions Required¶
chat:typing (planned).
Request Schema¶
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | chat.typing |
data.auctionId | string | Yes | Auction cycle. |
data.isTyping | boolean | Yes | true to start, false to stop. |
Response (ack)¶
{
"id": "req_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
"type": "ack",
"version": "1.0",
"source": "dichit-backend",
"timestamp": "2026-08-05T10:00:00.000Z",
"sequence": 1,
"data": {
"eventType": "chat.typing",
"auctionId": "cyc_01HQ5BWN3F5RX0W6X0W5X0W5X",
"isTyping": true
}
}
Validation Rules¶
| Rule | Behaviour |
|---|---|
auctionId non-empty | Required. |
isTyping boolean | Required. |
Example Request¶
{
"type": "chat.typing",
"id": "req_01HQ5HXWYP1Y5RX0W5X0W5X0W5X",
"data": { "auctionId": "cyc_01HQ5BWN3F5RX0W5X0W5X0W5X", "isTyping": true }
}
Broadcast Behaviour¶
Fanned out to the room as chat.typing with the sender identity, throttled server-side to avoid flooding.
Related Events¶
chat.send
Notes¶
- Implementation status: Planned.
- Never block actual sending on a typing indicator; it is best-effort and can be dropped under load.
Best Practices¶
- Coalesce typing events client-side (at most one every few hundred ms).
- Stop the indicator when the message is sent or a timeout elapses.
Example broadcast for a chat message¶
Recipients (other room members) receive a server-push message:
{
"type": "chat.send",
"data": {
"messageId": "msg_01HQ5BY2K7K2RY210W5X0W5X0W5X",
"auctionId": "cyc_01HQ5BWN3F5P5RX0W5X0W5X0W5X",
"clientMessageId": "msg_cl_1HQ5KYP1K7",
"author": {
"userId": "sub_01HQ5BWYP1Y5RX0W5X0W5X0W5X",
"name": "Annie Mohan"
},
"body": "Best of luck, everyone!",
"createdAt": "2026-08-03T10:00:00.000Z"
}
}
Related documents¶
- rate-limits.md —
chat.send30/min,chat.typingthrottled. - rooms.md —
auction:<auctionId>room. - errors.md — error codes.