AsyncAPI 3.1.0 · specs/messaging/authsocket-asyncapi.yaml

AuthSocket WebSocket Protocol

v1.0.0
AsyncAPI 3.0 specification for the `AuthSocketServer` / `AuthSocket` WebSocket channel used by the BSV MessageBox Server. ## Transport layer `AuthSocketServer` wraps Socket.IO and sits on top of an HTTP server. All Socket.IO events are standard Socket.IO framing; this spec describes the *application-level* event names and payload shapes that flow over the Socket.IO connection. ## BRC-103 mutual authentication Every Socket.IO connection undergoes BRC-103 (`Peer`) handshake before application events are exchanged. The handshake is carried on the **`authMessage`** event using the `AuthMessage` envelope defined in the `@bsv/sdk` `Transport` interface. Once the handshake succeeds the peer's `identityKey` (compressed secp256k1 public key, 66-char hex) is known server-side and stored in memory for the lifetime of the connection. ## Application events After authentication the server emits and listens for the events described below. All application payloads are serialized as JSON inside the BRC-103 `general` message (`Peer.toPeer`). The transport layer (`SocketServerTransport`) wraps them in an `{ eventName, data }` envelope before signing. Source of truth: - `packages/messaging/authsocket/src/AuthSocketServer.ts` - `packages/messaging/authsocket/src/SocketServerTransport.ts` - `packages/messaging/message-box-server/src/index.ts`
2Servers16Channels17Operations0Messages18Schemas

Servers

2

production

wss://messagebox.babbage.systems/

Production MessageBox WebSocket endpoint (Socket.IO over WSS).
host
messagebox.babbage.systems
pathname
/
protocol
wss
description
Production MessageBox WebSocket endpoint (Socket.IO over WSS).

local

ws://localhost:{port}/

Local development Socket.IO server.
host
localhost:{port}
pathname
/
protocol
ws
description
Local development Socket.IO server.
variables
1 field
port
2 fields
default
5001
description
HTTP port the MessageBox Server listens on.

Channels

16

authMessage

authMessage

Low-level Socket.IO event used by `SocketServerTransport` to carry BRC-103 `AuthMessage` frames. This event is NOT an application event; it is emitted and received transparently by the `Peer` class from `@bsv/sdk`. Application developers do not interact with this channel directly — they use the typed events below. See `packages/messaging/authsocket/src/SocketServerTransport.ts`.
address
authMessage
description
Low-level Socket.IO event used by `SocketServerTransport` to carry BRC-103 `AuthMessage` frames. This event is NOT an application event; it is emitted and received transparently by the `Peer` class from `@bsv/sdk`. Application developers do not interact with this channel directly — they use the typed events below. See `packages/messaging/authsocket/src/SocketServerTransport.ts`.
messages
1 field
authMessageFrame
3 fields
name
authMessageFrame
summary
BRC-103 auth frame (both directions — client and server).
payload
1 field
$ref
#/components/schemas/AuthMessage

authenticated

authenticated

Fallback authentication event. The client emits this when its identity key was not included in the Socket.IO handshake. The server validates the key, updates its in-memory `authenticatedSockets` map, and emits `authenticationSuccess` or `authenticationFailed` in response.
address
authenticated
description
Fallback authentication event. The client emits this when its identity key was not included in the Socket.IO handshake. The server validates the key, updates its in-memory `authenticatedSockets` map, and emits `authenticationSuccess` or `authenticationFailed` in response.
messages
1 field
authenticateMessage
3 fields
name
authenticateMessage
summary
Client sends its identity key for post-connection auth.
payload
1 field
$ref
#/components/schemas/AuthenticatePayload

authenticationSuccess

authenticationSuccess

Emitted by the server after successful identity key validation.
address
authenticationSuccess
description
Emitted by the server after successful identity key validation.
messages
1 field
authSuccessMessage
2 fields
name
authSuccessMessage
payload
1 field
$ref
#/components/schemas/AuthSuccessPayload

authenticationFailed

authenticationFailed

Emitted by the server when identity key validation fails.
address
authenticationFailed
description
Emitted by the server when identity key validation fails.
messages
1 field
authFailedMessage
2 fields
name
authFailedMessage
payload
1 field
$ref
#/components/schemas/AuthFailedPayload

joinRoom

joinRoom

Client requests to subscribe to a room. Only authenticated sockets may join rooms. The server responds with `joinedRoom` on success or `joinFailed` on error. Room ID convention: `<recipientIdentityKey>-<messageBoxType>`.
address
joinRoom
description
Client requests to subscribe to a room. Only authenticated sockets may join rooms. The server responds with `joinedRoom` on success or `joinFailed` on error. Room ID convention: `<recipientIdentityKey>-<messageBoxType>`.
messages
1 field
joinRoomMessage
3 fields
name
joinRoomMessage
summary
Room ID string to join.
payload
1 field
$ref
#/components/schemas/JoinRoomPayload

joinedRoom

joinedRoom

Server confirms the client has joined the specified room.
address
joinedRoom
description
Server confirms the client has joined the specified room.
messages
1 field
joinedRoomMessage
2 fields
name
joinedRoomMessage
payload
1 field
$ref
#/components/schemas/JoinedRoomPayload

joinFailed

joinFailed

Emitted when `joinRoom` fails (unauthenticated or invalid roomId).
address
joinFailed
description
Emitted when `joinRoom` fails (unauthenticated or invalid roomId).
messages
1 field
joinFailedMessage
2 fields
name
joinFailedMessage
payload
1 field
$ref
#/components/schemas/JoinFailedPayload

leaveRoom

leaveRoom

Client requests to leave a room.
address
leaveRoom
description
Client requests to leave a room.
messages
1 field
leaveRoomMessage
3 fields
name
leaveRoomMessage
summary
Room ID string to leave.
payload
1 field
$ref
#/components/schemas/LeaveRoomPayload

leftRoom

leftRoom

Server confirms the client has left the room.
address
leftRoom
description
Server confirms the client has left the room.
messages
1 field
leftRoomMessage
2 fields
name
leftRoomMessage
payload
1 field
$ref
#/components/schemas/LeftRoomPayload

leaveFailed

leaveFailed

Emitted when `leaveRoom` fails.
address
leaveFailed
description
Emitted when `leaveRoom` fails.
messages
1 field
leaveFailedMessage
2 fields
name
leaveFailedMessage
payload
1 field
$ref
#/components/schemas/LeaveFailedPayload

sendMessage

sendMessage

Client sends a message to a recipient via WebSocket when operator monetization is disabled. Paid servers return an error acknowledgement that instructs current clients to use their AuthFetch HTTP fallback. The unpriced WebSocket path: 1. Validates the sender is authenticated. 2. Validates `roomId` and `message`. 3. Creates the message box if it does not exist. 4. Inserts the message into the database (with ON CONFLICT IGNORE dedup). 5. Emits `sendMessageAck-{roomId}` back to the sender. 6. Broadcasts `sendMessage-{roomId}` to all connections in the room.
address
sendMessage
description
Client sends a message to a recipient via WebSocket when operator monetization is disabled. Paid servers return an error acknowledgement that instructs current clients to use their AuthFetch HTTP fallback. The unpriced WebSocket path: 1. Validates the sender is authenticated. 2. Validates `roomId` and `message`. 3. Creates the message box if it does not exist. 4. Inserts the message into the database (with ON CONFLICT IGNORE dedup). 5. Emits `sendMessageAck-{roomId}` back to the sender. 6. Broadcasts `sendMessage-{roomId}` to all connections in the room.
messages
1 field
sendMessageMessage
2 fields
name
sendMessageMessage
payload
1 field
$ref
#/components/schemas/WsSendMessagePayload

sendMessageAck

sendMessageAck-{roomId}

Per-room acknowledgement emitted to the sender after the message is stored or when the request must fall back to AuthFetch. The event name is `sendMessageAck-<roomId>` where `roomId` matches the value in the originating `sendMessage` payload.
address
sendMessageAck-{roomId}
description
Per-room acknowledgement emitted to the sender after the message is stored or when the request must fall back to AuthFetch. The event name is `sendMessageAck-<roomId>` where `roomId` matches the value in the originating `sendMessage` payload.
parameters
1 field
roomId
1 field
description
The room ID from the originating sendMessage request.
messages
1 field
sendMessageAckMessage
2 fields
name
sendMessageAckMessage
payload
1 field
$ref
#/components/schemas/WsSendMessageAckPayload

sendMessageBroadcast

sendMessage-{roomId}

Broadcast emitted to all connections subscribed to `roomId` after a successful `sendMessage`. The event name is `sendMessage-<roomId>`.
address
sendMessage-{roomId}
description
Broadcast emitted to all connections subscribed to `roomId` after a successful `sendMessage`. The event name is `sendMessage-<roomId>`.
parameters
1 field
roomId
1 field
description
The target room ID.
messages
1 field
sendMessageBroadcastMessage
2 fields
name
sendMessageBroadcastMessage
payload
1 field
$ref
#/components/schemas/WsSendMessageBroadcastPayload

messageFailed

messageFailed

Emitted to the sender when `sendMessage` processing fails.
address
messageFailed
description
Emitted to the sender when `sendMessage` processing fails.
messages
1 field
messageFailedMessage
2 fields
name
messageFailedMessage
payload
1 field
$ref
#/components/schemas/MessageFailedPayload

paymentFailed

paymentFailed

Emitted to unauthenticated sockets that attempt to send a message (same event name reused from older payment-gate logic).
address
paymentFailed
description
Emitted to unauthenticated sockets that attempt to send a message (same event name reused from older payment-gate logic).
messages
1 field
paymentFailedMessage
2 fields
name
paymentFailedMessage
payload
1 field
$ref
#/components/schemas/PaymentFailedPayload

disconnect

disconnect

Standard Socket.IO disconnect event. The server removes the socket from the `authenticatedSockets` map and the `peers` map in `AuthSocketServer`.
address
disconnect
description
Standard Socket.IO disconnect event. The server removes the socket from the `authenticatedSockets` map and the `peers` map in `AuthSocketServer`.
messages
1 field
disconnectMessage
2 fields
name
disconnectMessage
payload
1 field
$ref
#/components/schemas/DisconnectPayload

Operations

17

receiveAuthMessage

receive
Server receives an AuthMessage frame from the client during BRC-103 handshake.
action
receive
channel
1 field
$ref
#/channels/authMessage
summary
Server receives an AuthMessage frame from the client during BRC-103 handshake.
messages
1 item
  1. $ref
    #/channels/authMessage/messages/authMessageFrame

sendAuthMessage

send
Server sends an AuthMessage frame to the client during BRC-103 handshake.
action
send
channel
1 field
$ref
#/channels/authMessage
summary
Server sends an AuthMessage frame to the client during BRC-103 handshake.
messages
1 item
  1. $ref
    #/channels/authMessage/messages/authMessageFrame

receiveAuthenticated

receive
Server receives the client's identity key on the 'authenticated' event.
action
receive
channel
1 field
$ref
#/channels/authenticated
summary
Server receives the client's identity key on the 'authenticated' event.
messages
1 item
  1. $ref
    #/channels/authenticated/messages/authenticateMessage

sendAuthenticationSuccess

send
Server confirms successful identity key validation.
action
send
channel
1 field
$ref
#/channels/authenticationSuccess
summary
Server confirms successful identity key validation.
messages
1 item
  1. $ref
    #/channels/authenticationSuccess/messages/authSuccessMessage

sendAuthenticationFailed

send
Server rejects an invalid identity key.
action
send
channel
1 field
$ref
#/channels/authenticationFailed
summary
Server rejects an invalid identity key.
messages
1 item
  1. $ref
    #/channels/authenticationFailed/messages/authFailedMessage

receiveJoinRoom

receive
Server receives a room join request.
action
receive
channel
1 field
$ref
#/channels/joinRoom
summary
Server receives a room join request.
messages
1 item
  1. $ref
    #/channels/joinRoom/messages/joinRoomMessage

sendJoinedRoom

send
Server confirms room join.
action
send
channel
1 field
$ref
#/channels/joinedRoom
summary
Server confirms room join.
messages
1 item
  1. $ref
    #/channels/joinedRoom/messages/joinedRoomMessage

sendJoinFailed

send
Server signals room join failure.
action
send
channel
1 field
$ref
#/channels/joinFailed
summary
Server signals room join failure.
messages
1 item
  1. $ref
    #/channels/joinFailed/messages/joinFailedMessage

receiveLeaveRoom

receive
Server receives a room leave request.
action
receive
channel
1 field
$ref
#/channels/leaveRoom
summary
Server receives a room leave request.
messages
1 item
  1. $ref
    #/channels/leaveRoom/messages/leaveRoomMessage

sendLeftRoom

send
Server confirms room leave.
action
send
channel
1 field
$ref
#/channels/leftRoom
summary
Server confirms room leave.
messages
1 item
  1. $ref
    #/channels/leftRoom/messages/leftRoomMessage

sendLeaveFailed

send
Server signals room leave failure.
action
send
channel
1 field
$ref
#/channels/leaveFailed
summary
Server signals room leave failure.
messages
1 item
  1. $ref
    #/channels/leaveFailed/messages/leaveFailedMessage

receiveSendMessage

receive
Server receives a message from the client to deliver to a recipient.
action
receive
channel
1 field
$ref
#/channels/sendMessage
summary
Server receives a message from the client to deliver to a recipient.
messages
1 item
  1. $ref
    #/channels/sendMessage/messages/sendMessageMessage

sendSendMessageAck

send
Server acknowledges delivery of a message to the sender.
action
send
channel
1 field
$ref
#/channels/sendMessageAck
summary
Server acknowledges delivery of a message to the sender.
messages
1 item
  1. $ref
    #/channels/sendMessageAck/messages/sendMessageAckMessage

sendSendMessageBroadcast

send
Server broadcasts a new message to all room subscribers.
action
send
channel
1 field
$ref
#/channels/sendMessageBroadcast
summary
Server broadcasts a new message to all room subscribers.
messages
1 item
  1. $ref
    #/channels/sendMessageBroadcast/messages/sendMessageBroadcastMessage

sendMessageFailed

send
Server signals message delivery failure.
action
send
channel
1 field
$ref
#/channels/messageFailed
summary
Server signals message delivery failure.
messages
1 item
  1. $ref
    #/channels/messageFailed/messages/messageFailedMessage

sendPaymentFailed

send
Server signals auth/payment gate rejection.
action
send
channel
1 field
$ref
#/channels/paymentFailed
summary
Server signals auth/payment gate rejection.
messages
1 item
  1. $ref
    #/channels/paymentFailed/messages/paymentFailedMessage

receiveDisconnect

receive
Client disconnects; server cleans up in-memory state.
action
receive
channel
1 field
$ref
#/channels/disconnect
summary
Client disconnects; server cleans up in-memory state.
messages
1 item
  1. $ref
    #/channels/disconnect/messages/disconnectMessage

Schemas

18

PubKeyHex

Compressed secp256k1 public key, 66 hex characters.
type
string
pattern
^0[23][0-9a-fA-F]{64}$
description
Compressed secp256k1 public key, 66 hex characters.

AuthMessage

BRC-103 auth envelope as defined in `@bsv/sdk`. Carried on the low-level `authMessage` Socket.IO event. Not an application-level event.
type
object
description
BRC-103 auth envelope as defined in `@bsv/sdk`. Carried on the low-level `authMessage` Socket.IO event. Not an application-level event.
required
3 items
  1. messageType
  2. version
  3. identityKey
properties
9 fields
messageType
3 fields
type
string
enum
3 items
  1. initialRequest
  2. initialResponse
  3. general
description
- `initialRequest` — first handshake message from initiating peer - `initialResponse` — server's challenge response (includes nonce, signature) - `general` — signed application payload after handshake
version
2 fields
type
string
description
Auth protocol version string.
identityKey
1 field
$ref
#/components/schemas/PubKeyHex
nonce
2 fields
type
string
description
Fresh random nonce (base64) generated by the sender.
yourNonce
2 fields
type
string
description
Echo of the peer's nonce from the previous message.
initialNonce
2 fields
type
string
description
Present in `initialRequest`; absent in subsequent messages.
payload
3 fields
type
array
items
1 field
type
integer
description
Signed application payload (byte array). Empty for handshake messages.
signature
3 fields
type
array
items
1 field
type
integer
description
DER-encoded ECDSA signature over the payload.
requestedCertificates
3 fields
type
object
description
Optional certificate request set (BRC-52 format).
additionalProperties
true

EventEnvelope

Application-level wrapper JSON-encoded inside the BRC-103 `general` message payload. The `SocketServerTransport` encodes/decodes this transparently; application code only sees `eventName` and `data`.
type
object
description
Application-level wrapper JSON-encoded inside the BRC-103 `general` message payload. The `SocketServerTransport` encodes/decodes this transparently; application code only sees `eventName` and `data`.
required
2 items
  1. eventName
  2. data
properties
2 fields
eventName
2 fields
type
string
description
The Socket.IO event name.
data
1 field
description
The event-specific payload.

AuthenticatePayload

Sent by the client on the `authenticated` event when the identity key was not available at connection time (fallback path). The server validates the key and responds with `authenticationSuccess` or `authenticationFailed`.
type
object
description
Sent by the client on the `authenticated` event when the identity key was not available at connection time (fallback path). The server validates the key and responds with `authenticationSuccess` or `authenticationFailed`.
properties
1 field
identityKey
1 field
$ref
#/components/schemas/PubKeyHex

AuthSuccessPayload

type
object
required
1 item
  1. status
properties
1 field
status
2 fields
type
string
enum
1 item
  1. success

AuthFailedPayload

type
object
required
1 item
  1. reason
properties
1 field
reason
2 fields
type
string
description
Human-readable reason for failure.

JoinRoomPayload

The room ID string sent by the client on the `joinRoom` event. Room IDs use the convention `<recipientKey>-<messageBoxType>`. Example: `028d37b9...-payment_inbox`.
type
string
description
The room ID string sent by the client on the `joinRoom` event. Room IDs use the convention `<recipientKey>-<messageBoxType>`. Example: `028d37b9...-payment_inbox`.

JoinedRoomPayload

type
object
required
1 item
  1. roomId
properties
1 field
roomId
1 field
type
string

JoinFailedPayload

type
object
required
1 item
  1. reason
properties
1 field
reason
1 field
type
string

LeaveRoomPayload

The room ID string sent by the client on the `leaveRoom` event.
type
string
description
The room ID string sent by the client on the `leaveRoom` event.

LeftRoomPayload

type
object
required
1 item
  1. roomId
properties
1 field
roomId
1 field
type
string

LeaveFailedPayload

type
object
required
1 item
  1. reason
properties
1 field
reason
1 field
type
string

WsSendMessagePayload

Payload for the client-to-server `sendMessage` event.
type
object
description
Payload for the client-to-server `sendMessage` event.
required
2 items
  1. roomId
  2. message
properties
2 fields
roomId
2 fields
type
string
description
Target room. Format: `<recipientKey>-<messageBoxType>`. The server removes the exact recipient-key prefix and uses the authenticated sender key from `authenticatedSockets`.
message
3 fields
type
object
required
3 items
  1. messageId
  2. recipient
  3. body
properties
3 fields
messageId
2 fields
type
string
description
Unique identifier for this message (deduplication key).
recipient
1 field
$ref
#/components/schemas/PubKeyHex
body
2 fields
type
string
description
Message body string.

WsSendMessageAckPayload

Acknowledgement emitted by the server on `sendMessageAck-{roomId}`. A successful write includes `messageId`. An error includes `code`; paid servers use `ERR_PAYMENT_REQUIRES_AUTHFETCH` so compatible clients retry the send through the BRC-105 AuthFetch HTTP path.
type
object
description
Acknowledgement emitted by the server on `sendMessageAck-{roomId}`. A successful write includes `messageId`. An error includes `code`; paid servers use `ERR_PAYMENT_REQUIRES_AUTHFETCH` so compatible clients retry the send through the BRC-105 AuthFetch HTTP path.
required
1 item
  1. status
properties
3 fields
status
2 fields
type
string
enum
2 items
  1. success
  2. error
messageId
1 field
type
string
code
1 field
type
string

WsSendMessageBroadcastPayload

Broadcast emitted by the server on `sendMessage-{roomId}` to all connections in the room (including the sender). Note: the event name is dynamic.
type
object
description
Broadcast emitted by the server on `sendMessage-{roomId}` to all connections in the room (including the sender). Note: the event name is dynamic.
required
3 items
  1. sender
  2. messageId
  3. body
properties
3 fields
sender
1 field
$ref
#/components/schemas/PubKeyHex
messageId
1 field
type
string
body
1 field
type
string

MessageFailedPayload

type
object
required
1 item
  1. reason
properties
1 field
reason
1 field
type
string

PaymentFailedPayload

type
object
required
1 item
  1. reason
properties
1 field
reason
1 field
type
string

DisconnectPayload

The Socket.IO disconnect reason string (e.g. `transport close`, `server namespace disconnect`).
type
string
description
The Socket.IO disconnect reason string (e.g. `transport close`, `server namespace disconnect`).
Raw YAML source
asyncapi: "3.1.0"

info:
  title: AuthSocket WebSocket Protocol
  version: "1.0.0"
  description: |
    AsyncAPI 3.0 specification for the `AuthSocketServer` / `AuthSocket`
    WebSocket channel used by the BSV MessageBox Server.

    ## Transport layer

    `AuthSocketServer` wraps Socket.IO and sits on top of an HTTP server.
    All Socket.IO events are standard Socket.IO framing; this spec describes
    the *application-level* event names and payload shapes that flow over the
    Socket.IO connection.

    ## BRC-103 mutual authentication

    Every Socket.IO connection undergoes BRC-103 (`Peer`) handshake before
    application events are exchanged. The handshake is carried on the
    **`authMessage`** event using the `AuthMessage` envelope defined in the
    `@bsv/sdk` `Transport` interface.

    Once the handshake succeeds the peer's `identityKey` (compressed secp256k1
    public key, 66-char hex) is known server-side and stored in memory for the
    lifetime of the connection.

    ## Application events

    After authentication the server emits and listens for the events described
    below. All application payloads are serialized as JSON inside the
    BRC-103 `general` message (`Peer.toPeer`). The transport layer
    (`SocketServerTransport`) wraps them in an `{ eventName, data }` envelope
    before signing.

    Source of truth:
    - `packages/messaging/authsocket/src/AuthSocketServer.ts`
    - `packages/messaging/authsocket/src/SocketServerTransport.ts`
    - `packages/messaging/message-box-server/src/index.ts`

servers:
  production:
    host: "messagebox.babbage.systems"
    pathname: "/"
    protocol: wss
    description: Production MessageBox WebSocket endpoint (Socket.IO over WSS).
  local:
    host: "localhost:{port}"
    pathname: "/"
    protocol: ws
    description: Local development Socket.IO server.
    variables:
      port:
        default: "5001"
        description: HTTP port the MessageBox Server listens on.

# ---------------------------------------------------------------------------
# Components
# ---------------------------------------------------------------------------
components:
  schemas:
    PubKeyHex:
      type: string
      pattern: "^0[23][0-9a-fA-F]{64}$"
      description: Compressed secp256k1 public key, 66 hex characters.

    AuthMessage:
      type: object
      description: |
        BRC-103 auth envelope as defined in `@bsv/sdk`. Carried on the
        low-level `authMessage` Socket.IO event. Not an application-level event.
      required: [messageType, version, identityKey]
      properties:
        messageType:
          type: string
          enum: [initialRequest, initialResponse, general]
          description: |
            - `initialRequest`  — first handshake message from initiating peer
            - `initialResponse` — server's challenge response (includes nonce, signature)
            - `general`         — signed application payload after handshake
        version:
          type: string
          description: Auth protocol version string.
        identityKey:
          $ref: "#/components/schemas/PubKeyHex"
        nonce:
          type: string
          description: Fresh random nonce (base64) generated by the sender.
        yourNonce:
          type: string
          description: Echo of the peer's nonce from the previous message.
        initialNonce:
          type: string
          description: Present in `initialRequest`; absent in subsequent messages.
        payload:
          type: array
          items:
            type: integer
          description: Signed application payload (byte array). Empty for handshake messages.
        signature:
          type: array
          items:
            type: integer
          description: DER-encoded ECDSA signature over the payload.
        requestedCertificates:
          type: object
          description: Optional certificate request set (BRC-52 format).
          additionalProperties: true

    EventEnvelope:
      type: object
      description: |
        Application-level wrapper JSON-encoded inside the BRC-103 `general`
        message payload. The `SocketServerTransport` encodes/decodes this
        transparently; application code only sees `eventName` and `data`.
      required: [eventName, data]
      properties:
        eventName:
          type: string
          description: The Socket.IO event name.
        data:
          description: The event-specific payload.

    # ----- Authentication flow -----
    AuthenticatePayload:
      type: object
      description: |
        Sent by the client on the `authenticated` event when the identity key
        was not available at connection time (fallback path). The server validates
        the key and responds with `authenticationSuccess` or `authenticationFailed`.
      properties:
        identityKey:
          $ref: "#/components/schemas/PubKeyHex"

    AuthSuccessPayload:
      type: object
      required: [status]
      properties:
        status:
          type: string
          enum: [success]

    AuthFailedPayload:
      type: object
      required: [reason]
      properties:
        reason:
          type: string
          description: Human-readable reason for failure.

    # ----- Room management -----
    JoinRoomPayload:
      type: string
      description: |
        The room ID string sent by the client on the `joinRoom` event.
        Room IDs use the convention `<recipientKey>-<messageBoxType>`.
        Example: `028d37b9...-payment_inbox`.

    JoinedRoomPayload:
      type: object
      required: [roomId]
      properties:
        roomId:
          type: string

    JoinFailedPayload:
      type: object
      required: [reason]
      properties:
        reason:
          type: string

    LeaveRoomPayload:
      type: string
      description: The room ID string sent by the client on the `leaveRoom` event.

    LeftRoomPayload:
      type: object
      required: [roomId]
      properties:
        roomId:
          type: string

    LeaveFailedPayload:
      type: object
      required: [reason]
      properties:
        reason:
          type: string

    # ----- Message sending -----
    WsSendMessagePayload:
      type: object
      description: Payload for the client-to-server `sendMessage` event.
      required: [roomId, message]
      properties:
        roomId:
          type: string
          description: |
            Target room. Format: `<recipientKey>-<messageBoxType>`.
            The server removes the exact recipient-key prefix and uses the
            authenticated sender key from `authenticatedSockets`.
        message:
          type: object
          required: [messageId, recipient, body]
          properties:
            messageId:
              type: string
              description: Unique identifier for this message (deduplication key).
            recipient:
              $ref: "#/components/schemas/PubKeyHex"
            body:
              type: string
              description: Message body string.

    WsSendMessageAckPayload:
      type: object
      description: |
        Acknowledgement emitted by the server on `sendMessageAck-{roomId}`. A
        successful write includes `messageId`. An error includes `code`; paid
        servers use `ERR_PAYMENT_REQUIRES_AUTHFETCH` so compatible clients retry
        the send through the BRC-105 AuthFetch HTTP path.
      required: [status]
      properties:
        status:
          type: string
          enum: [success, error]
        messageId:
          type: string
        code:
          type: string

    WsSendMessageBroadcastPayload:
      type: object
      description: |
        Broadcast emitted by the server on `sendMessage-{roomId}` to all
        connections in the room (including the sender). Note: the event name
        is dynamic.
      required: [sender, messageId, body]
      properties:
        sender:
          $ref: "#/components/schemas/PubKeyHex"
        messageId:
          type: string
        body:
          type: string

    MessageFailedPayload:
      type: object
      required: [reason]
      properties:
        reason:
          type: string

    PaymentFailedPayload:
      type: object
      required: [reason]
      properties:
        reason:
          type: string

    DisconnectPayload:
      type: string
      description: |
        The Socket.IO disconnect reason string (e.g. `transport close`,
        `server namespace disconnect`).

# ---------------------------------------------------------------------------
# Channels
# ---------------------------------------------------------------------------
channels:

  # -------- Low-level auth handshake (BRC-103 / Peer transport) --------
  authMessage:
    address: authMessage
    description: |
      Low-level Socket.IO event used by `SocketServerTransport` to carry
      BRC-103 `AuthMessage` frames. This event is NOT an application event;
      it is emitted and received transparently by the `Peer` class from
      `@bsv/sdk`. Application developers do not interact with this channel
      directly — they use the typed events below.

      See `packages/messaging/authsocket/src/SocketServerTransport.ts`.
    messages:
      authMessageFrame:
        name: authMessageFrame
        summary: BRC-103 auth frame (both directions — client and server).
        payload:
          $ref: "#/components/schemas/AuthMessage"

  # -------- Application authentication --------
  authenticated:
    address: authenticated
    description: |
      Fallback authentication event. The client emits this when its identity
      key was not included in the Socket.IO handshake. The server validates
      the key, updates its in-memory `authenticatedSockets` map, and emits
      `authenticationSuccess` or `authenticationFailed` in response.
    messages:
      authenticateMessage:
        name: authenticateMessage
        summary: Client sends its identity key for post-connection auth.
        payload:
          $ref: "#/components/schemas/AuthenticatePayload"

  authenticationSuccess:
    address: authenticationSuccess
    description: Emitted by the server after successful identity key validation.
    messages:
      authSuccessMessage:
        name: authSuccessMessage
        payload:
          $ref: "#/components/schemas/AuthSuccessPayload"

  authenticationFailed:
    address: authenticationFailed
    description: Emitted by the server when identity key validation fails.
    messages:
      authFailedMessage:
        name: authFailedMessage
        payload:
          $ref: "#/components/schemas/AuthFailedPayload"

  # -------- Room management --------
  joinRoom:
    address: joinRoom
    description: |
      Client requests to subscribe to a room. Only authenticated sockets may
      join rooms. The server responds with `joinedRoom` on success or
      `joinFailed` on error.

      Room ID convention: `<recipientIdentityKey>-<messageBoxType>`.
    messages:
      joinRoomMessage:
        name: joinRoomMessage
        summary: Room ID string to join.
        payload:
          $ref: "#/components/schemas/JoinRoomPayload"

  joinedRoom:
    address: joinedRoom
    description: Server confirms the client has joined the specified room.
    messages:
      joinedRoomMessage:
        name: joinedRoomMessage
        payload:
          $ref: "#/components/schemas/JoinedRoomPayload"

  joinFailed:
    address: joinFailed
    description: Emitted when `joinRoom` fails (unauthenticated or invalid roomId).
    messages:
      joinFailedMessage:
        name: joinFailedMessage
        payload:
          $ref: "#/components/schemas/JoinFailedPayload"

  leaveRoom:
    address: leaveRoom
    description: Client requests to leave a room.
    messages:
      leaveRoomMessage:
        name: leaveRoomMessage
        summary: Room ID string to leave.
        payload:
          $ref: "#/components/schemas/LeaveRoomPayload"

  leftRoom:
    address: leftRoom
    description: Server confirms the client has left the room.
    messages:
      leftRoomMessage:
        name: leftRoomMessage
        payload:
          $ref: "#/components/schemas/LeftRoomPayload"

  leaveFailed:
    address: leaveFailed
    description: Emitted when `leaveRoom` fails.
    messages:
      leaveFailedMessage:
        name: leaveFailedMessage
        payload:
          $ref: "#/components/schemas/LeaveFailedPayload"

  # -------- Message sending --------
  sendMessage:
    address: sendMessage
    description: |
      Client sends a message to a recipient via WebSocket when operator
      monetization is disabled. Paid servers return an error acknowledgement
      that instructs current clients to use their AuthFetch HTTP fallback. The
      unpriced WebSocket path:
      1. Validates the sender is authenticated.
      2. Validates `roomId` and `message`.
      3. Creates the message box if it does not exist.
      4. Inserts the message into the database (with ON CONFLICT IGNORE dedup).
      5. Emits `sendMessageAck-{roomId}` back to the sender.
      6. Broadcasts `sendMessage-{roomId}` to all connections in the room.
    messages:
      sendMessageMessage:
        name: sendMessageMessage
        payload:
          $ref: "#/components/schemas/WsSendMessagePayload"

  sendMessageAck:
    address: "sendMessageAck-{roomId}"
    description: |
      Per-room acknowledgement emitted to the sender after the message is
      stored or when the request must fall back to AuthFetch. The event name is
      `sendMessageAck-<roomId>` where `roomId` matches the value in the
      originating `sendMessage` payload.
    parameters:
      roomId:
        description: The room ID from the originating sendMessage request.
    messages:
      sendMessageAckMessage:
        name: sendMessageAckMessage
        payload:
          $ref: "#/components/schemas/WsSendMessageAckPayload"

  sendMessageBroadcast:
    address: "sendMessage-{roomId}"
    description: |
      Broadcast emitted to all connections subscribed to `roomId` after a
      successful `sendMessage`. The event name is `sendMessage-<roomId>`.
    parameters:
      roomId:
        description: The target room ID.
    messages:
      sendMessageBroadcastMessage:
        name: sendMessageBroadcastMessage
        payload:
          $ref: "#/components/schemas/WsSendMessageBroadcastPayload"

  messageFailed:
    address: messageFailed
    description: Emitted to the sender when `sendMessage` processing fails.
    messages:
      messageFailedMessage:
        name: messageFailedMessage
        payload:
          $ref: "#/components/schemas/MessageFailedPayload"

  paymentFailed:
    address: paymentFailed
    description: |
      Emitted to unauthenticated sockets that attempt to send a message
      (same event name reused from older payment-gate logic).
    messages:
      paymentFailedMessage:
        name: paymentFailedMessage
        payload:
          $ref: "#/components/schemas/PaymentFailedPayload"

  # -------- Lifecycle --------
  disconnect:
    address: disconnect
    description: |
      Standard Socket.IO disconnect event. The server removes the socket from
      the `authenticatedSockets` map and the `peers` map in `AuthSocketServer`.
    messages:
      disconnectMessage:
        name: disconnectMessage
        payload:
          $ref: "#/components/schemas/DisconnectPayload"

# ---------------------------------------------------------------------------
# Operations
# ---------------------------------------------------------------------------
operations:

  # --- Auth handshake (transport-level, both directions) ---
  receiveAuthMessage:
    action: receive
    channel:
      $ref: "#/channels/authMessage"
    summary: Server receives an AuthMessage frame from the client during BRC-103 handshake.
    messages:
      - $ref: "#/channels/authMessage/messages/authMessageFrame"

  sendAuthMessage:
    action: send
    channel:
      $ref: "#/channels/authMessage"
    summary: Server sends an AuthMessage frame to the client during BRC-103 handshake.
    messages:
      - $ref: "#/channels/authMessage/messages/authMessageFrame"

  # --- Client authentication ---
  receiveAuthenticated:
    action: receive
    channel:
      $ref: "#/channels/authenticated"
    summary: Server receives the client's identity key on the 'authenticated' event.
    messages:
      - $ref: "#/channels/authenticated/messages/authenticateMessage"

  sendAuthenticationSuccess:
    action: send
    channel:
      $ref: "#/channels/authenticationSuccess"
    summary: Server confirms successful identity key validation.
    messages:
      - $ref: "#/channels/authenticationSuccess/messages/authSuccessMessage"

  sendAuthenticationFailed:
    action: send
    channel:
      $ref: "#/channels/authenticationFailed"
    summary: Server rejects an invalid identity key.
    messages:
      - $ref: "#/channels/authenticationFailed/messages/authFailedMessage"

  # --- Room management ---
  receiveJoinRoom:
    action: receive
    channel:
      $ref: "#/channels/joinRoom"
    summary: Server receives a room join request.
    messages:
      - $ref: "#/channels/joinRoom/messages/joinRoomMessage"

  sendJoinedRoom:
    action: send
    channel:
      $ref: "#/channels/joinedRoom"
    summary: Server confirms room join.
    messages:
      - $ref: "#/channels/joinedRoom/messages/joinedRoomMessage"

  sendJoinFailed:
    action: send
    channel:
      $ref: "#/channels/joinFailed"
    summary: Server signals room join failure.
    messages:
      - $ref: "#/channels/joinFailed/messages/joinFailedMessage"

  receiveLeaveRoom:
    action: receive
    channel:
      $ref: "#/channels/leaveRoom"
    summary: Server receives a room leave request.
    messages:
      - $ref: "#/channels/leaveRoom/messages/leaveRoomMessage"

  sendLeftRoom:
    action: send
    channel:
      $ref: "#/channels/leftRoom"
    summary: Server confirms room leave.
    messages:
      - $ref: "#/channels/leftRoom/messages/leftRoomMessage"

  sendLeaveFailed:
    action: send
    channel:
      $ref: "#/channels/leaveFailed"
    summary: Server signals room leave failure.
    messages:
      - $ref: "#/channels/leaveFailed/messages/leaveFailedMessage"

  # --- Message sending ---
  receiveSendMessage:
    action: receive
    channel:
      $ref: "#/channels/sendMessage"
    summary: Server receives a message from the client to deliver to a recipient.
    messages:
      - $ref: "#/channels/sendMessage/messages/sendMessageMessage"

  sendSendMessageAck:
    action: send
    channel:
      $ref: "#/channels/sendMessageAck"
    summary: Server acknowledges delivery of a message to the sender.
    messages:
      - $ref: "#/channels/sendMessageAck/messages/sendMessageAckMessage"

  sendSendMessageBroadcast:
    action: send
    channel:
      $ref: "#/channels/sendMessageBroadcast"
    summary: Server broadcasts a new message to all room subscribers.
    messages:
      - $ref: "#/channels/sendMessageBroadcast/messages/sendMessageBroadcastMessage"

  sendMessageFailed:
    action: send
    channel:
      $ref: "#/channels/messageFailed"
    summary: Server signals message delivery failure.
    messages:
      - $ref: "#/channels/messageFailed/messages/messageFailedMessage"

  sendPaymentFailed:
    action: send
    channel:
      $ref: "#/channels/paymentFailed"
    summary: Server signals auth/payment gate rejection.
    messages:
      - $ref: "#/channels/paymentFailed/messages/paymentFailedMessage"

  # --- Lifecycle ---
  receiveDisconnect:
    action: receive
    channel:
      $ref: "#/channels/disconnect"
    summary: Client disconnects; server cleans up in-memory state.
    messages:
      - $ref: "#/channels/disconnect/messages/disconnectMessage"