# Build 060.10 — WebSocket Trade Schema Validation **Engineering Migration Report** --- # Контроль документа | Свойство | Значение | |----------|----------| | Build | 060.10 | | Название | WebSocket Trade Schema Validation | | Статус | Completed | | Проект | Dzentra | | Подсистема | Market Data Acquisition | | Компонент | Trades Feed | | Версия | 1.0 | --- # Цель Build После завершения Build 060.9 система получила транспортную модель WebSocket Trade (`DzengiWebSocketTradeEvent`), описывающую одно событие биржи на транспортном уровне. Следующим обязательным этапом развития WebSocket-конвейера является реализация слоя структурной проверки входящих сообщений. Build 060.10 вводит механизм **Schema Validation** для сообщений Dzengi WebSocket канала `internal.trade`. Основная задача Build — гарантировать, что последующие этапы обработки получают структурно корректный документ, содержащий все обязательные элементы транспортного контракта. Данный Build ограничивается исключительно проверкой структуры сообщения и не затрагивает: - Parser; - Value Validation; - Mapper; - Adapter; - Runtime; - Routing; - Trades Feed. --- # Предпосылки К моменту начала Build архитектура Dzentra уже содержала завершённые уровни Schema Validation для остальных типов WebSocket-событий. ## WebSocket Quote ```text Raw WebSocket Quote │ ▼ Schema Validation │ ▼ ValidatedWebSocketQuoteDocument │ ▼ Quote Parser ``` ## WebSocket OHLC ```text Raw WebSocket OHLC │ ▼ Schema Validation │ ▼ ValidatedWebSocketOhlcDocument │ ▼ OHLC Parser ``` После завершения Build 060.9 появилась транспортная модель: ```text DzengiWebSocketTradeEvent ``` Однако между необработанным JSON-документом и Parser отсутствовал слой, отвечающий за структурную проверку сообщения. В результате WebSocket-конвейер обработки сделок оставался незавершённым и отличался от уже реализованных конвейеров Quote и OHLC. --- # Архитектурное основание В архитектуре Dzentra каждый уровень Pipeline имеет строго определённую область ответственности. Schema Validation располагается между транспортным JSON-документом и Parser и отвечает исключительно за проверку структуры сообщения. На данном уровне выполняется: - проверка структуры корневого объекта; - проверка обязательных элементов транспортной оболочки; - проверка структуры объекта `payload`; - проверка наличия обязательных полей транспортного события. Schema Validation принципиально **не выполняет**: - преобразование типов; - преобразование числовых значений; - проверку диапазонов; - проверку бизнес-семантики; - создание транспортной модели; - преобразование в каноническую модель `Trade`. Такое разделение позволяет каждому уровню Pipeline выполнять одну строго определённую задачу и исключает смешивание ответственности между компонентами. --- # Результаты архитектурного аудита Перед началом реализации был выполнен аудит существующей подсистемы Validation. Подтверждено наличие полностью реализованных компонентов: - `ValidatedWebSocketQuoteDocument`; - `ValidatedWebSocketOhlcDocument`; - `validate_dzengi_websocket_quote_schema()`; - `validate_dzengi_websocket_ohlc_schema()`. Также подтверждено существование полной иерархии ошибок обработки Trade: - `TradeTransportError`; - `TradeSchemaError`; - `TradeParseError`; - `TradeValueError`; - `TradeMappingError`. Одновременно подтверждено отсутствие собственного уровня Schema Validation для WebSocket Trade. Таким образом Build 060.10 полностью соответствует утверждённой дорожной карте серии 060 и закрывает второй этап WebSocket-ветки обработки сделок. --- # Архитектурное решение По итогам аудита было принято решение не проектировать отдельную архитектуру для Trade. Вместо этого реализован третий экземпляр уже существующего архитектурного шаблона. В систему добавлены: ```text ValidatedWebSocketTradeDocument validate_dzengi_websocket_trade_schema(...) ``` Архитектура всех WebSocket-конвейеров стала полностью симметричной. ```text Quote Raw WebSocket │ ▼ Schema Validation │ ▼ ValidatedWebSocketQuoteDocument OHLC Raw WebSocket │ ▼ Schema Validation │ ▼ ValidatedWebSocketOhlcDocument Trade Raw WebSocket │ ▼ Schema Validation │ ▼ ValidatedWebSocketTradeDocument ``` Build 060.10 не изменяет существующее поведение Quote и OHLC, а лишь расширяет существующую архитектуру новым типом рыночных данных. --- # Реализованный документ Schema Validation В файл ```text src/market_data/acquisition/validation/schema.py ``` добавлен новый документ структурной проверки: ```python @dataclass(frozen=True, slots=True) class ValidatedWebSocketTradeDocument: payload: Mapping[str, object] status: object destination: object correlation_id: object | None ``` Документ представляет собой неизменяемый результат успешной проверки структуры WebSocket-сообщения. Экземпляр содержит: - транспортную оболочку сообщения; - неизменяемый `payload`; - статус сообщения; - назначение сообщения; - необязательный `correlationId`. После создания объект используется исключительно последующими стадиями Pipeline и не предполагает модификации. --- # Почему используется отдельный документ Validation `ValidatedWebSocketTradeDocument` не является транспортной моделью биржи. Он представляет собой результат успешной структурной проверки входящего JSON-документа. Документ: - не содержит бизнес-логики; - не преобразует данные; - не выполняет Parsing; - не выполняет Value Validation; - не выполняет Mapping; - не является канонической моделью `Trade`. Его единственная задача — гарантировать Parser, что структура сообщения соответствует ожидаемому контракту. Такое разделение полностью повторяет архитектурный подход, уже применяемый для Quote и OHLC. --- # Проверяемая структура WebSocket-документа В рамках Build 060.10 реализована проверка исключительно структуры сообщения. Ожидаемый контракт WebSocket-события имеет следующий вид: ```json { "status": "OK", "destination": "internal.trade", "payload": { "buyer": false, "id": 2134846831, "orderId": "00a02503-0079-54c4-0000-000081e62b58", "price": 64555.55, "size": 0.002, "symbol": "BTC/USD_LEVERAGE", "ts": 1784218012030 } } ``` Build 060.10 гарантирует наличие обязательных элементов данного контракта, но принципиально не анализирует их содержимое. --- # Проверяемые элементы транспортной оболочки На уровне корневого документа выполняется проверка наличия обязательных полей: ```text status destination payload ``` Кроме того, проверяется, что сам корневой объект является JSON Mapping и содержит только строковые ключи. Поле ```text correlationId ``` не является обязательным. При наличии оно сохраняется в результирующем документе без какой-либо дополнительной обработки. Следует отметить, что Build 060.10 проверяет **наличие** поля ```text destination ``` но **не проверяет его значение**. В частности, валидатор не сравнивает содержимое поля со строкой ```text internal.trade ``` Подобная проверка относится не к структурной корректности сообщения, а к его семантике и поэтому не входит в область ответственности Schema Validation. Такое разделение полностью соответствует архитектурному принципу Dzentra, согласно которому Schema Validation отвечает исключительно за структуру входящего документа, а не за интерпретацию его содержимого. --- # Проверяемые элементы payload После успешной проверки транспортной оболочки выполняется проверка структуры объекта ```text payload ``` Payload обязан быть JSON Mapping. Для объекта выполняется проверка строковых ключей и наличие обязательных элементов транспортного контракта. Обязательными являются: ```text id price size symbol ts buyer orderId ``` Отсутствие любого из перечисленных полей приводит к генерации исключения ```text TradeSchemaError ``` с указанием отсутствующих элементов. --- # Проверка Mapping Build 060.10 следует архитектурному правилу Dzentra: любая структура JSON после прохождения Schema Validation должна представлять собой Mapping со строковыми ключами. Поэтому реализованы две независимые проверки. Первая проверяет корневой документ: ```text $ ``` Вторая проверяет вложенный объект: ```text $.payload ``` В обоих случаях: - объект обязан быть Mapping; - каждый ключ обязан иметь тип `str`. Подобный подход полностью совпадает с реализацией Quote и OHLC. --- # Использование MappingProxyType После успешной проверки содержимое ```text payload ``` копируется в ```python MappingProxyType(dict(payload)) ``` Таким образом создаётся неизменяемое представление транспортного документа. Использование `MappingProxyType` решает сразу несколько задач. Во-первых, предотвращается случайное изменение данных после завершения Schema Validation. Во-вторых, исключается влияние внешнего кода на результаты проверки структуры. В-третьих, последующие уровни Pipeline получают гарантированно неизменяемый документ. Parser, Value Validation и Mapper могут безопасно использовать полученные данные, не опасаясь их изменения между этапами обработки. --- # Почему не используется транспортная модель Build 060.10 принципиально не создаёт экземпляр ```text DzengiWebSocketTradeEvent ``` Это является обязанностью Parser. Schema Validation лишь подтверждает корректность структуры сообщения. Создание транспортной модели переносится на следующий Build. Подобное разделение ответственности уже используется в существующих WebSocket-конвейерах Quote и OHLC. --- # Граница ответственности Build Build 060.10 отвечает исключительно за структурную корректность документа. В его обязанности входит: - проверка структуры корневого объекта; - проверка транспортной оболочки; - проверка структуры payload; - проверка обязательных полей; - формирование неизменяемого документа Validation. Build **не выполняет**: - Parsing; - преобразование JSON в транспортную модель; - преобразование типов; - Decimal-конвертацию; - проверку диапазонов; - проверку timestamp; - проверку символа; - проверку стороны сделки; - Mapping; - создание канонической модели `Trade`. Каждая из перечисленных задач относится к отдельному архитектурному уровню и будет реализована в следующих Build. --- # Использование TradeSchemaError Для всех ошибок структуры используется уже существующее исключение ```text TradeSchemaError ``` Build не вводит новых типов исключений. Это сохраняет единый подход ко всей подсистеме Validation и полностью соответствует существующей архитектуре обработки ошибок. --- # Целевой конвейер обработки WebSocket Trade После завершения Build 060.10 конвейер обработки принимает следующий вид. ```text Raw WebSocket Object │ ▼ WebSocket Trade Schema Validation │ ▼ ValidatedWebSocketTradeDocument │ ▼ Build 060.11 — WebSocket Trade Parser │ ▼ DzengiWebSocketTradeEvent │ ▼ Build 060.12 — WebSocket Trade Value Validation │ ▼ Validated Trade Transport Event │ ▼ Build 060.13 — WebSocket Trade Mapper │ ▼ Trade ``` Таким образом Build 060.10 завершает второй архитектурный уровень WebSocket-конвейера обработки сделок. --- # Соотношение с транспортной моделью Build 060.9 и Build 060.10 реализуют два различных архитектурных уровня. ```text Build 060.9 ``` вводит транспортную модель ```text DzengiWebSocketTradeEvent ``` которая описывает уже разобранное WebSocket-событие. ```text Build 060.10 ``` вводит документ ```text ValidatedWebSocketTradeDocument ``` который представляет собой результат проверки структуры исходного JSON-документа. Таким образом последовательность обработки становится следующей. ```text Raw JSON │ ▼ ValidatedWebSocketTradeDocument │ ▼ DzengiWebSocketTradeEvent │ ▼ Trade ``` Каждый объект относится к собственному архитектурному уровню и не дублирует ответственность другого. --- # Изменённые файлы В рамках Build были изменены только два файла. ## Schema Validation ```text src/market_data/acquisition/validation/schema.py ``` Добавлены: ```text ValidatedWebSocketTradeDocument validate_dzengi_websocket_trade_schema(...) _validate_websocket_trade_payload(...) _require_websocket_trade_mapping(...) ``` При этом существующие валидаторы Quote и OHLC, импорты и поведение файла не изменялись. --- ## Unit-тесты ```text tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py ``` Добавлен полный набор unit-тестов нового уровня Schema Validation. --- # Добавленные тесты В рамках Build реализовано двадцать unit-тестов, полностью покрывающих функциональность нового валидатора. ## Проверка успешной валидации Тест ```text test_validate_websocket_trade_schema_returns_immutable_document ``` проверяет: - успешную проверку корректного документа; - создание `ValidatedWebSocketTradeDocument`; - использование `MappingProxyType`; - сохранение обязательных полей. --- ## Проверка correlationId Тест ```text test_validate_websocket_trade_schema_preserves_correlation_id ``` подтверждает корректное сохранение необязательного поля `correlationId`. --- ## Проверка копирования payload Тест ```text test_validate_websocket_trade_schema_copies_payload ``` подтверждает, что изменения исходного словаря после Validation не влияют на содержимое результирующего документа. --- ## Проверка структуры корневого объекта Тест ```text test_validate_websocket_trade_schema_rejects_non_mapping_root ``` подтверждает генерацию `TradeSchemaError`, если корневой объект не является JSON Mapping. --- ## Проверка обязательных полей транспортной оболочки Параметризованный тест ```text test_validate_websocket_trade_schema_rejects_missing_root_field ``` проверяет отсутствие: - status; - destination; - payload. --- ## Проверка структуры payload Тест ```text test_validate_websocket_trade_schema_rejects_non_mapping_payload ``` проверяет, что поле `payload` обязано быть JSON Mapping. --- ## Проверка обязательных полей Trade Параметризованный тест ```text test_validate_websocket_trade_schema_rejects_missing_payload_field ``` проверяет отсутствие каждого обязательного элемента: - id; - price; - size; - ts; - symbol; - buyer; - orderId. --- ## Проверка сообщения об ошибке Тест ```text test_validate_websocket_trade_schema_reports_all_missing_fields ``` подтверждает, что исключение содержит полный список отсутствующих полей. --- ## Отсутствие проверки значений Тест ```text test_validate_websocket_trade_schema_does_not_validate_values ``` подтверждает архитектурный принцип Build. Schema Validation проверяет исключительно структуру и принципиально не анализирует содержимое полей. --- ## Дополнительные поля Тест ```text test_validate_websocket_trade_schema_allows_additional_fields ``` подтверждает, что неподтверждённые Production поля не вызывают ошибку Validation. В частности проверяется возможность присутствия ```text clientOrderId ``` и других дополнительных элементов. --- ## Проверка строковых ключей Реализованы отдельные тесты проверки строковых ключей для: - корневого объекта; - объекта payload. Это полностью соответствует архитектуре существующих WebSocket Schema Validation. --- # Результаты тестирования Выполнен целевой запуск нового набора unit-тестов. ```bash python -m pytest \ tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py \ -q ``` Результат: ```text 20 passed in 0.02s ``` Все проверки новой функциональности успешно завершены. --- # Регрессионное тестирование После завершения реализации выполнен полный запуск подсистемы Validation. ```bash python -m pytest \ tests/unit/market_data/acquisition/validation \ -q ``` Результат: ```text 302 passed in 0.10s ``` Регрессий существующей функциональности не обнаружено. --- # Проверка компиляции Выполнена проверка компиляции изменённых файлов. ```bash python -m compileall \ src/market_data/acquisition/validation/schema.py \ tests/unit/market_data/acquisition/validation/test_websocket_trade_schema.py ``` Компиляция завершилась успешно. Синтаксические ошибки отсутствуют. --- # Проверка Git diff Выполнена финальная проверка изменений. ```bash git diff --check ``` Ошибок не обнаружено. Это подтверждает отсутствие: - trailing whitespace; - конфликтов окончания строк; - ошибок форматирования diff. --- # Scope Build 060.10 В рамках данного Build реализовано только: ```text WebSocket Trade Schema Validation ``` Build **не включает**: - WebSocket Trade Parser; - WebSocket Trade Value Validation; - WebSocket Trade Mapper; - WebSocket Trade Adapter; - Runtime Integration; - Unified Routing; - Trades Feed. Это полностью соответствует принципу атомарной реализации Build. --- # Архитектурный результат После завершения Build система содержит завершённый уровень Schema Validation для всех поддерживаемых WebSocket-событий. ```text Quote Raw WebSocket │ ▼ Schema Validation │ ▼ ValidatedWebSocketQuoteDocument OHLC Raw WebSocket │ ▼ Schema Validation │ ▼ ValidatedWebSocketOhlcDocument Trade Raw WebSocket │ ▼ Schema Validation │ ▼ ValidatedWebSocketTradeDocument ``` Архитектура стала полностью симметричной. --- # Состояние WebSocket Trade Pipeline После завершения Build 060.10 конвейер имеет следующий вид. ```text Raw WebSocket Trade Document │ ▼ ValidatedWebSocketTradeDocument │ ▼ Parser │ ▼ DzengiWebSocketTradeEvent │ ▼ Value Validation │ ▼ Mapper │ ▼ Trade ``` Статус реализации компонентов: | Компонент | Build | Статус | |-----------|-------|--------| | Canonical Trade Model | 060.1 | ✔ Completed | | WebSocket Trade Transport Model | 060.9 | ✔ Completed | | WebSocket Trade Schema Validation | 060.10 | ✔ Completed | | WebSocket Trade Parser | 060.11 | Pending | | WebSocket Trade Value Validation | 060.12 | Pending | | WebSocket Trade Mapper | 060.13 | Pending | | WebSocket Trade Adapter | 060.14 | Pending | | Unified WebSocket Routing | 060.15 | Pending | --- # Соблюдение архитектурных принципов В рамках Build полностью сохранены архитектурные инварианты Dzentra. ## Локальность изменений Изменены только: - Schema Validation; - unit-тесты нового валидатора. --- ## Повторное использование архитектуры Новая реализация полностью повторяет существующий шаблон Quote и OHLC. Новая архитектура не создавалась. --- ## Разделение ответственности Schema Validation отвечает исключительно за проверку структуры сообщения. Parser, Value Validation, Mapper и Runtime остаются полностью независимыми уровнями. --- ## Отсутствие бизнес-логики Build не выполняет: - Parsing; - преобразование типов; - Value Validation; - Mapping; - Runtime Integration. Это полностью соответствует архитектуре Dzentra. --- ## Обратная совместимость Существующая обработка Quote, OHLC и REST Trade не изменилась. Новая функциональность добавлена изолированно и не влияет на ранее реализованные Build. --- # Критерии завершения Build Build 060.10 считается завершённым, поскольку выполнены все поставленные задачи. - ✔ реализован `ValidatedWebSocketTradeDocument`; - ✔ реализована функция `validate_dzengi_websocket_trade_schema()`; - ✔ проверяется структура транспортной оболочки; - ✔ проверяется структура payload; - ✔ проверяются обязательные поля Trade; - ✔ используется `TradeSchemaError`; - ✔ payload становится неизменяемым; - ✔ реализовано двадцать unit-тестов; - ✔ все целевые тесты успешно проходят; - ✔ регрессионное тестирование успешно завершено; - ✔ компиляция выполнена без ошибок; - ✔ `git diff --check` не выявил замечаний; - ✔ изменения не выходят за пределы согласованного scope. --- # Следующий этап Следующим этапом дорожной карты является ```text Build 060.11 — WebSocket Trade Parser ``` Цель Build: - преобразование `ValidatedWebSocketTradeDocument`; - создание транспортной модели `DzengiWebSocketTradeEvent`; - нормализация имён транспортных полей; - преобразование JSON-ключей: - `id → trade_id`; - `ts → timestamp`; - `orderId → order_id`; - сохранение исходных числовых значений без преобразования типов; - отсутствие Value Validation. После завершения Build 060.11 конвейер примет следующий вид: ```text Raw WebSocket Object │ ▼ Schema Validation │ ▼ ValidatedWebSocketTradeDocument │ ▼ WebSocket Trade Parser │ ▼ DzengiWebSocketTradeEvent ``` Build 060.11 по-прежнему не будет выполнять: - проверку диапазонов значений; - проверку корректности timestamp; - проверку корректности цены и объёма; - Mapping в каноническую модель `Trade`; - Runtime Integration. Все перечисленные задачи будут реализованы на последующих этапах дорожной карты серии 060. --- # Итог Build 060.10 завершил формирование уровня **Schema Validation** для WebSocket Trade и сделал архитектуру обработки всех WebSocket-событий Dzentra полностью симметричной. Новая реализация основана на существующем шаблоне Quote и OHLC, использует единый подход к структурной проверке сообщений, повторно применяет существующую иерархию исключений и не изменяет ранее реализованное поведение системы. Build ограничен согласованным scope, успешно прошёл целевое и регрессионное тестирование и создаёт необходимый фундамент для следующего этапа — **Build 060.11 — WebSocket Trade Parser**.