Skip to content

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.

Notes

  • Implementation status: Planned.
  • Messages are tied to the auction room; joining requires auction.subscribe/room.join with the same auctionId.

Best Practices

  • Send clientMessageId to make retries safe.
  • Charge chat.send rate 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.

  • 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"
  }
}