Corp/backend/docs/architecture/websocket-asyncapi.yaml

945 lines
27 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

asyncapi: 2.6.0
info:
title: EUSRR Realtime WebSocket API
version: 1.4.0
description: |
Отдельная AsyncAPI-спецификация для WebSocket-контура EUSRR.
HTTP API продолжает документироваться через OpenAPI в /api/schema/.
Этот документ описывает только двусторонний realtime-канал /ws/.
Аутентификация:
- browser: одноразовый ?ticket=<ticket> из POST /api/auth/ws-ticket/
- non-browser: заголовок Authorization: Bearer <jwt_access_token>
defaultContentType: application/json
servers:
development:
url: localhost:8000/ws/
protocol: ws
description: Локальная разработка
security:
- websocketTicket: []
- bearerAuth: []
production:
url: api.example.com/ws/
protocol: wss
description: Продакшен через TLS
security:
- websocketTicket: []
- bearerAuth: []
channels:
userRealtime:
address: /ws/
description: |
Универсальное пользовательское соединение для всех real-time сценариев:
- сообщения и список чатов
- уведомления и unread count
- typing indicators
- реакции и голосования
- procurement updates
- статусы commerce-интеграций и фоновых синхронизаций
- подписки на диапазоны календаря и calendar snapshots
publish:
operationId: clientAction
summary: Команды от клиента к серверу
message:
oneOf:
- $ref: '#/components/messages/OpenChatAction'
- $ref: '#/components/messages/CloseChatAction'
- $ref: '#/components/messages/SendMessageAction'
- $ref: '#/components/messages/EditMessageAction'
- $ref: '#/components/messages/DeleteMessageAction'
- $ref: '#/components/messages/AddReactionAction'
- $ref: '#/components/messages/RemoveReactionAction'
- $ref: '#/components/messages/TypingAction'
- $ref: '#/components/messages/StopTypingAction'
- $ref: '#/components/messages/VotePollAction'
- $ref: '#/components/messages/MarkReadAction'
- $ref: '#/components/messages/CalendarSubscribeAction'
- $ref: '#/components/messages/CalendarUnsubscribeAction'
- $ref: '#/components/messages/PongAction'
subscribe:
operationId: serverEvent
summary: События от сервера клиенту
message:
oneOf:
- $ref: '#/components/messages/PingEvent'
- $ref: '#/components/messages/ErrorEvent'
- $ref: '#/components/messages/ChatOpenedEvent'
- $ref: '#/components/messages/ChatClosedEvent'
- $ref: '#/components/messages/ChatAccessChangedEvent'
- $ref: '#/components/messages/InitialMessagesEvent'
- $ref: '#/components/messages/NewMessageEvent'
- $ref: '#/components/messages/ListUpdateEvent'
- $ref: '#/components/messages/MessageUpdatedEvent'
- $ref: '#/components/messages/MessageDeletedEvent'
- $ref: '#/components/messages/ReactionAddedEvent'
- $ref: '#/components/messages/ReactionRemovedEvent'
- $ref: '#/components/messages/TypingStartEvent'
- $ref: '#/components/messages/TypingStopEvent'
- $ref: '#/components/messages/PollUpdateEvent'
- $ref: '#/components/messages/MarkedReadEvent'
- $ref: '#/components/messages/NotificationEvent'
- $ref: '#/components/messages/UnreadCountEvent'
- $ref: '#/components/messages/NotificationReadEvent'
- $ref: '#/components/messages/NotificationsReadAllEvent'
- $ref: '#/components/messages/ProcurementUpdateEvent'
- $ref: '#/components/messages/CommerceConnectionUpdatedEvent'
- $ref: '#/components/messages/TaskBoardUpdateEvent'
- $ref: '#/components/messages/CalendarUpdateEvent'
- $ref: '#/components/messages/CalendarSnapshotEvent'
- $ref: '#/components/messages/CalendarErrorEvent'
components:
securitySchemes:
websocketTicket:
type: apiKey
in: query
name: ticket
description: Одноразовый билет со сроком жизни 30 секунд.
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
ChatId:
type: integer
minimum: 1
MessageId:
type: integer
minimum: 1
UserId:
type: integer
minimum: 1
Emoji:
type: string
minLength: 1
GenericMessagePayload:
type: object
description: |
Сериализованное сообщение чата. Полный набор полей зависит от
communications.serialization.serialize_message.
properties:
id:
type: integer
content:
type: string
nullable: true
mentions:
type: array
items:
$ref: '#/components/schemas/MessageMention'
chat:
type: integer
author:
type: integer
created_at:
type: string
format: date-time
required:
- id
additionalProperties: true
MessageMention:
type: object
required: [user_id, name, start, end]
properties:
user_id:
$ref: '#/components/schemas/UserId'
name:
type: string
start:
type: integer
minimum: 0
end:
type: integer
minimum: 1
NotificationPayload:
type: object
description: Сериализованное уведомление пользователя.
properties:
id:
type: integer
verb:
type: string
description:
type: string
unread:
type: boolean
action_url:
type: string
nullable: true
data:
type: object
additionalProperties: true
required:
- id
- verb
- unread
additionalProperties: true
CalendarEventPayload:
type: object
required: [id, title, start, end, calendar, is_recurring]
properties:
id:
oneOf:
- type: integer
- type: string
title:
type: string
description:
type: string
start:
type: string
format: date-time
end:
type: string
format: date-time
calendar:
type: integer
minimum: 1
event_id:
type: integer
minimum: 1
rule:
type: integer
minimum: 1
nullable: true
color_event:
type: string
nullable: true
can_edit:
type: boolean
can_delete:
type: boolean
is_recurring:
type: boolean
additionalProperties: true
CommerceSyncRunPayload:
type: object
required: [id, connection, status, processed, created_products, matched_products, stock_snapshots, images, image_errors, sales]
properties:
id:
type: string
connection:
type: string
status:
type: string
task_id:
type: string
processed:
type: integer
created_products:
type: integer
matched_products:
type: integer
stock_snapshots:
type: integer
images:
type: integer
image_errors:
type: integer
sales:
type: integer
error:
type: string
started_at:
type: string
format: date-time
nullable: true
finished_at:
type: string
format: date-time
nullable: true
created_at:
type: string
format: date-time
additionalProperties: false
CommerceConnectionUpdatePayload:
type: object
required: [id, status, auto_sync, sync_interval_minutes, updated_at]
properties:
id:
type: string
status:
type: string
account_name:
type: string
last_error:
type: string
last_tested_at:
type: string
format: date-time
nullable: true
last_sync_started_at:
type: string
format: date-time
nullable: true
last_sync_finished_at:
type: string
format: date-time
nullable: true
last_stats:
type: object
additionalProperties: true
task_id:
type: string
auto_sync:
type: boolean
sync_interval_minutes:
type: integer
next_sync_at:
type: string
format: date-time
nullable: true
updated_at:
type: string
format: date-time
recent_run:
oneOf:
- $ref: '#/components/schemas/CommerceSyncRunPayload'
- type: 'null'
additionalProperties: false
messages:
OpenChatAction:
name: OpenChatAction
title: Открыть чат
payload:
type: object
required: [action, chat_id]
properties:
action:
type: string
enum: [open_chat]
chat_id:
$ref: '#/components/schemas/ChatId'
load_history:
type: boolean
default: false
CloseChatAction:
name: CloseChatAction
title: Закрыть чат
payload:
type: object
required: [action, chat_id]
properties:
action:
type: string
enum: [close_chat]
chat_id:
$ref: '#/components/schemas/ChatId'
SendMessageAction:
name: SendMessageAction
title: Отправить сообщение
payload:
type: object
required: [action]
properties:
action:
type: string
enum: [send_message]
content:
type: string
text:
type: string
mentioned_user_ids:
type: array
maxItems: 50
uniqueItems: true
items:
$ref: '#/components/schemas/UserId'
EditMessageAction:
name: EditMessageAction
title: Редактировать сообщение
payload:
type: object
required: [action, message_id, content]
properties:
action:
type: string
enum: [edit_message]
message_id:
$ref: '#/components/schemas/MessageId'
content:
type: string
mentioned_user_ids:
type: array
maxItems: 50
uniqueItems: true
items:
$ref: '#/components/schemas/UserId'
DeleteMessageAction:
name: DeleteMessageAction
title: Удалить сообщение
payload:
type: object
required: [action, message_id]
properties:
action:
type: string
enum: [delete_message]
message_id:
$ref: '#/components/schemas/MessageId'
AddReactionAction:
name: AddReactionAction
title: Добавить реакцию
payload:
type: object
required: [action, message_id, emoji]
properties:
action:
type: string
enum: [add_reaction]
message_id:
$ref: '#/components/schemas/MessageId'
emoji:
$ref: '#/components/schemas/Emoji'
RemoveReactionAction:
name: RemoveReactionAction
title: Удалить реакцию
payload:
type: object
required: [action, message_id, emoji]
properties:
action:
type: string
enum: [remove_reaction]
message_id:
$ref: '#/components/schemas/MessageId'
emoji:
$ref: '#/components/schemas/Emoji'
TypingAction:
name: TypingAction
title: Пользователь печатает
payload:
type: object
required: [action]
properties:
action:
type: string
enum: [typing]
StopTypingAction:
name: StopTypingAction
title: Пользователь перестал печатать
payload:
type: object
required: [action]
properties:
action:
type: string
enum: [stop_typing]
VotePollAction:
name: VotePollAction
title: Голосование в опросе
payload:
type: object
required: [action, poll_id, option_ids]
properties:
action:
type: string
enum: [vote_poll]
poll_id:
type: integer
minimum: 1
option_ids:
type: array
items:
type: integer
minimum: 1
MarkReadAction:
name: MarkReadAction
title: Deprecated mark_read
payload:
type: object
required: [action, chat_id]
properties:
action:
type: string
enum: [mark_read]
chat_id:
$ref: '#/components/schemas/ChatId'
note:
type: string
example: Deprecated, используйте HTTP mark-read endpoint
CalendarSubscribeAction:
name: CalendarSubscribeAction
title: Подписаться на диапазон календаря
payload:
type: object
required: [action, subscription_id, start, end]
properties:
action:
type: string
enum: [calendar_subscribe]
subscription_id:
type: string
minLength: 1
maxLength: 80
start:
type: string
format: date-time
end:
type: string
format: date-time
calendar_id:
type: integer
minimum: 1
nullable: true
scope:
type: string
enum: [accessible, all]
default: accessible
CalendarUnsubscribeAction:
name: CalendarUnsubscribeAction
title: Отписаться от диапазона календаря
payload:
type: object
required: [action, subscription_id]
properties:
action:
type: string
enum: [calendar_unsubscribe]
subscription_id:
type: string
minLength: 1
maxLength: 80
PongAction:
name: PongAction
title: Ответ на heartbeat
payload:
type: object
required: [action]
properties:
action:
type: string
enum: [pong]
timestamp:
type: string
format: date-time
PingEvent:
name: PingEvent
payload:
type: object
required: [type, timestamp]
properties:
type:
type: string
enum: [ping]
timestamp:
type: string
format: date-time
ErrorEvent:
name: ErrorEvent
payload:
type: object
required: [type, error]
properties:
type:
type: string
enum: [error]
error:
type: string
chat_id:
$ref: '#/components/schemas/ChatId'
ChatOpenedEvent:
name: ChatOpenedEvent
payload:
type: object
required: [type, chat_id]
properties:
type:
type: string
enum: [chat_opened]
chat_id:
$ref: '#/components/schemas/ChatId'
ChatClosedEvent:
name: ChatClosedEvent
payload:
type: object
required: [type, chat_id]
properties:
type:
type: string
enum: [chat_closed]
chat_id:
$ref: '#/components/schemas/ChatId'
ChatAccessChangedEvent:
name: ChatAccessChangedEvent
payload:
type: object
required: [type, chat_id, can_access]
properties:
type:
type: string
enum: [chat_access_changed]
chat_id:
$ref: '#/components/schemas/ChatId'
can_access:
type: boolean
InitialMessagesEvent:
name: InitialMessagesEvent
payload:
type: object
required: [type, chat_id, messages]
properties:
type:
type: string
enum: [initial_messages]
chat_id:
$ref: '#/components/schemas/ChatId'
messages:
type: array
items:
$ref: '#/components/schemas/GenericMessagePayload'
NewMessageEvent:
name: NewMessageEvent
payload:
type: object
required: [type, chat_id, message]
properties:
type:
type: string
enum: [new_message]
chat_id:
$ref: '#/components/schemas/ChatId'
message:
$ref: '#/components/schemas/GenericMessagePayload'
ListUpdateEvent:
name: ListUpdateEvent
payload:
type: object
required: [type, chat_id, message]
properties:
type:
type: string
enum: [list_update]
chat_id:
$ref: '#/components/schemas/ChatId'
message:
$ref: '#/components/schemas/GenericMessagePayload'
MessageUpdatedEvent:
name: MessageUpdatedEvent
payload:
type: object
required: [type, chat_id, message]
properties:
type:
type: string
enum: [message_updated]
chat_id:
$ref: '#/components/schemas/ChatId'
message:
$ref: '#/components/schemas/GenericMessagePayload'
MessageDeletedEvent:
name: MessageDeletedEvent
payload:
type: object
required: [type, chat_id, message_id]
properties:
type:
type: string
enum: [message_deleted]
chat_id:
$ref: '#/components/schemas/ChatId'
message_id:
$ref: '#/components/schemas/MessageId'
ReactionAddedEvent:
name: ReactionAddedEvent
payload:
type: object
required: [type, chat_id, message_id, emoji, user_id]
properties:
type:
type: string
enum: [reaction_added]
chat_id:
$ref: '#/components/schemas/ChatId'
message_id:
$ref: '#/components/schemas/MessageId'
emoji:
$ref: '#/components/schemas/Emoji'
user_id:
$ref: '#/components/schemas/UserId'
user_name:
type: string
reactions_summary:
type: object
additionalProperties: true
ReactionRemovedEvent:
name: ReactionRemovedEvent
payload:
type: object
required: [type, chat_id, message_id, emoji, user_id]
properties:
type:
type: string
enum: [reaction_removed]
chat_id:
$ref: '#/components/schemas/ChatId'
message_id:
$ref: '#/components/schemas/MessageId'
emoji:
$ref: '#/components/schemas/Emoji'
user_id:
$ref: '#/components/schemas/UserId'
reactions_summary:
type: object
additionalProperties: true
TypingStartEvent:
name: TypingStartEvent
payload:
type: object
required: [type, chat_id, user_id]
properties:
type:
type: string
enum: [typing_start]
chat_id:
$ref: '#/components/schemas/ChatId'
user_id:
$ref: '#/components/schemas/UserId'
user_name:
type: string
TypingStopEvent:
name: TypingStopEvent
payload:
type: object
required: [type, chat_id, user_id]
properties:
type:
type: string
enum: [typing_stop]
chat_id:
$ref: '#/components/schemas/ChatId'
user_id:
$ref: '#/components/schemas/UserId'
PollUpdateEvent:
name: PollUpdateEvent
payload:
type: object
required: [type, chat_id]
properties:
type:
type: string
enum: [poll_update]
chat_id:
$ref: '#/components/schemas/ChatId'
poll_id:
type: integer
message_id:
$ref: '#/components/schemas/MessageId'
results:
type: object
additionalProperties: true
MarkedReadEvent:
name: MarkedReadEvent
payload:
type: object
required: [type, chat_id, last_read_message_id]
properties:
type:
type: string
enum: [marked_read]
chat_id:
$ref: '#/components/schemas/ChatId'
last_read_message_id:
$ref: '#/components/schemas/MessageId'
NotificationEvent:
name: NotificationEvent
payload:
type: object
required: [type, notification]
properties:
type:
type: string
enum: [notification]
notification:
$ref: '#/components/schemas/NotificationPayload'
UnreadCountEvent:
name: UnreadCountEvent
payload:
type: object
required: [type, count]
properties:
type:
type: string
enum: [unread_count]
count:
type: integer
minimum: 0
NotificationReadEvent:
name: NotificationReadEvent
payload:
type: object
required: [type, notification_id, unread_count]
properties:
type:
type: string
enum: [notification_read]
notification_id:
type: integer
unread_count:
type: integer
minimum: 0
NotificationsReadAllEvent:
name: NotificationsReadAllEvent
payload:
type: object
required: [type, notification_ids, unread_count]
properties:
type:
type: string
enum: [notifications_read_all]
notification_ids:
type: array
items:
type: integer
category:
type: string
nullable: true
unread_count:
type: integer
minimum: 0
ProcurementUpdateEvent:
name: ProcurementUpdateEvent
payload:
type: object
required: [type, event, data]
properties:
type:
type: string
enum: [procurement_update]
event:
type: string
data:
type: object
additionalProperties: true
CommerceConnectionUpdatedEvent:
name: CommerceConnectionUpdatedEvent
title: Изменение состояния commerce-интеграции
payload:
type: object
required: [type, connection]
properties:
type:
type: string
enum: [commerce_connection_updated]
connection:
$ref: '#/components/schemas/CommerceConnectionUpdatePayload'
additionalProperties: false
TaskBoardUpdateEvent:
name: TaskBoardUpdateEvent
payload:
type: object
required: [type, event, data]
properties:
type:
type: string
enum: [task_board_update]
event:
type: string
data:
type: object
additionalProperties: true
CalendarUpdateEvent:
name: CalendarUpdateEvent
payload:
type: object
required: [type, event, data]
properties:
type:
type: string
enum: [calendar_update]
event:
type: string
enum:
- event_created
- event_updated
- event_deleted
- event_membership_changed
- calendar_created
- calendar_updated
- calendar_deleted
- calendar_membership_changed
data:
type: object
required: [action, entity, calendar_id]
properties:
action:
type: string
entity:
type: string
enum: [calendar, event]
calendar_id:
type: integer
minimum: 1
event_id:
type: integer
minimum: 1
nullable: true
changed_fields:
type: array
items:
type: string
start:
type: string
format: date-time
nullable: true
end:
type: string
format: date-time
nullable: true
is_recurring:
type: boolean
CalendarSnapshotEvent:
name: CalendarSnapshotEvent
payload:
type: object
required: [type, reason, data]
properties:
type:
type: string
enum: [calendar_snapshot]
reason:
type: string
enum: [subscribed, updated]
data:
type: object
required: [subscription_id, start, end, scope, events]
properties:
subscription_id:
type: string
start:
type: string
format: date-time
end:
type: string
format: date-time
calendar_id:
type: integer
minimum: 1
nullable: true
scope:
type: string
enum: [accessible, all]
events:
type: array
items:
$ref: '#/components/schemas/CalendarEventPayload'
CalendarErrorEvent:
name: CalendarErrorEvent
payload:
type: object
required: [type, code, detail]
properties:
type:
type: string
enum: [calendar_error]
subscription_id:
type: string
nullable: true
code:
type: string
enum: [invalid_subscription, subscription_limit, snapshot_failed]
detail:
type: string