Перейти к основному содержимому

Платформа данных и захват событий

Версия: 1.0 Дата: 26.04.2026 Статус: Готов к обсуждению

Назначение документа

Документ определяет платформу данных (data platform) Vitiana и слой захвата событий (events tracking) — два центральных компонента оси данных и интеллекта (data and intelligence spine, ось 4). Включает:

  • Каноничную модель аналитического события (AnalyticalEvent).
  • Главное правило разделения доменных событий (domain events) и аналитических событий (analytical events).
  • Поток захвата событий — точки захвата на поверхностях взаимодействия, нормализацию, обогащение.
  • Каноничную модель хранилища данных (data warehouse, DWH) — таблицы фактов, таблицы измерений, секционирование (partitioning), медленно меняющиеся измерения (slowly changing dimensions).
  • Классы приватности полей (privacy classes per data field).
  • Правила межтенантной агрегации (multi-tenant aggregation rules).
  • Ограничение цели (purpose limitation), политика хранения (retention policy) — связь с обязательствами по общему регулированию защиты данных.
  • Поток обработки данных и потоковую обработку (ETL/streaming pipelines).
  • Закрытие технического долга 8 из реализации home-to-go-api.
  • Фазы развёртывания.

Документ читается после:

В корневых документах зафиксировано что платформа данных делает и почему разделяет два класса событий. Этот документ описывает как — каноничные сущности, потоки, правила приватности, фазы.

Платформа данных — критическая инфраструктура для всех остальных слоёв интеллекта (машинного обучения, A/B-экспериментов, аналитики, биллинга по фактическому потреблению). Без зрелой платформы данных нельзя ни ранжировать поиск, ни тарифицировать партнёров, ни предотвращать возвратные платежи, ни строить рекомендации.

Правило 00000 (платформа главенствует над поставщиками) применяется здесь напрямую: каноничная аналитическая модель не подгоняется под форматы аналитики поставщиков. Платформа задаёт каноничную схему аналитики; поставщики предоставляют сырые данные, нормализуемые слоем приёма данных в каноничную форму.

Главное решение

Доменные события и аналитические события — два разных класса с разными гарантиями, разными шинами, разными хранилищами, разной политикой приватности, разной скоростью движения.

Это означает:

СвойствоДоменные события (domain events)Аналитические события (analytical events)
НазначениеИзменение каноничной доменной модели — BookingConfirmed, QuoteCreated, OfferPublished, PaymentCapturedПоведенческие следы — SearchExecuted, OfferViewed, FacetApplied, ProposalShared
ИсточникСервисы платформы (внутренние)Поверхности взаимодействия (внешние клики и запросы)
Гарантии доставкиХотя бы один раз (at-least-once) с упорядоченностью по сущностиХотя бы один раз с допустимой потерей малой доли
ШинаСобытийная шина платформы (event bus, на фазе 2 — Managed Kafka)Tracking pipeline (отдельная шина, на фазе 2 — отдельные топики или отдельный поток)
ХранилищеЖурнал событий (event log) + базы операционных контуровХранилище данных (DWH) — Snowflake / ClickHouse / BigQuery paradigm
СкоростьРеальное время (миллисекунды до секунд)Real-time + batch (секунды для streaming, часы для daily aggregations)
ПриватностьМинимальная PII (актёры идентифицированы по tenant_id + actor_id)Анонимизация на захвате (хешированные идентификаторы, обобщённая геолокация)
Срок храненияДолгий (audit trail, годы)Класс-зависимый (см. секцию политики хранения)
ПотребителиОперационные контуры платформы (booking, search, payment)Аналитика, ML-модели, A/B-эксперименты, отчётность

Это архитектурный закон, не «оптимизация». Смешение двух классов в одном хранилище разрушает свойства каждого:

  • Доменные события в DWH — теряют операционные гарантии.
  • Аналитические события в журнале операционных событий — раздувают operational store, ломают политику хранения, ломают приватность.

Это закрепляет долг 8 из реализации (см. далее).

Каноничная модель аналитического события

Сущность AnalyticalEvent

{
event_id: UUID,
event_name: string,
event_class: string,
event_version: string,
occurred_at: timestamp,
ingested_at: timestamp,
tenant_id: UUID,
surface_id: enum,
session_id: UUID,
actor_hash: string,
client_locale: string,
client_currency: string,
client_geo_class: string,
client_device_class: string,
context: object,
attributes: object,
privacy_class: string,
retention_class: string,
schema_id: string
}

Поля и их семантика

  • event_id — каноничный идентификатор события, генерируется на стороне поверхности взаимодействия для идемпотентности.
  • event_name — каноничное имя события из таксономии. Например, search.query.executed, offer.viewed, proposal.shared.
  • event_class — широкая группа: discovery / proposal / booking_funnel / post_booking / partner_intent / system_health.
  • event_version — версия схемы события. Изменения схемы — через инкремент версии без ломающих изменений старой.
  • occurred_at — момент события на стороне источника (поверхности).
  • ingested_at — момент захвата события платформой. Разница даёт задержку конвейера.
  • tenant_id — какой тенант инициировал событие (источник трафика).
  • surface_id — какая поверхность (partner_api / b2c_storefront / agency_working / tour_builder_closed / internal_admin).
  • session_id — ссылка на сессию (поисковую, пользовательскую, агентскую). Не содержит чувствительных данных.
  • actor_hash — анонимизированный идентификатор актёра. Хеш с солью, ротация соли по политике приватности.
  • client_locale, client_currency, client_geo_class, client_device_class — обобщённый клиентский контекст без точной геолокации (только страна + регион), без точной модели устройства (только класс desktop / mobile_phone / tablet).
  • context — структурированный контекст события (ссылки на сущности, к которым относится событие). Например, для search.query.executed — параметры запроса. Для offer.viewedproperty_id, offer_id, позиция в выдаче.
  • attributes — атрибуты события для аналитики и ML (без PII, без персональных идентификаторов).
  • privacy_class — класс приватности (см. ниже).
  • retention_class — класс хранения (см. ниже).
  • schema_id — идентификатор схемы события в реестре схем.

Каноничная схема — реестр схем (schema registry)

Каждое имя события (event_name) имеет формальную схему в реестре схем (schema registry). Реестр:

  • Содержит все версии каждого события.
  • Версии накапливаются — старые не удаляются.
  • Изменение схемы — только через инкремент event_version. Каноничные правила эволюции — те же, что для асинхронных контрактов (см. Реестр ломающих изменений).
  • Поверхности захвата валидируют события против схемы перед публикацией.

Связь с уже зафиксированной таксономией

В Первоначальная таксономия событий уже зафиксированы доменные события. Аналитические события — отдельная таксономия, дополняющая, не пересекающаяся.

Например:

  • booking.confirmed (доменное) — изменение каноничной сущности Booking. Публикуется операционным сервисом booking при успешной фиксации платежа и подтверждении поставщика.
  • booking_funnel.purchase.completed (аналитическое) — поведенческое событие, отражающее завершение пути «поиск → коммерческая фиксация → бронирование» на стороне поверхности взаимодействия. Несёт атрибуты для маркетинговой аналитики, не несёт операционных обязательств.

Оба возникают одновременно, но не одно и то же. Доменное публикуется внутренним сервисом и течёт по event bus в операционные контуры. Аналитическое публикуется поверхностью и течёт по tracking pipeline в DWH.

Поток захвата событий

Поверхность взаимодействия (frontend / SDK / партнёрский клиент)

Локальная буферизация на стороне поверхности

Подпись события, добавление client_geo_class и client_device_class

Отправка батчей на ingestion endpoint платформы

Валидация подписи, валидация схемы по реестру

Применение rate limiting (защита от спама и atak'и на конвейер)

Анонимизация actor_hash (если ещё не анонимизирован)

Применение privacy_class и retention_class по правилам

Публикация в tracking pipeline (отдельная шина)

├── Real-time потребители (deduplication → enrichment → ML feature store)
├── Streaming-обработка (агрегации в реальном времени)
└── Batch-загрузка в DWH (микро-партиции по событию + времени)

Точки захвата

  • Партнёрский клиент — программный интерфейс или SDK партнёра отправляет события через специализированный канал отчётности (опциональный, для тарифов с partner-facing analytics).
  • Потребительская витрина — встроенный JavaScript-клиент с буферизацией.
  • Поверхность для агентств — встроенный клиент с акцентом на рабочий поток агента.
  • Tour Builder Closed Surface — отдельный канал для композиционных событий конструктора туров.
  • Внутренние сервисы платформы — публикуют аналитические события для системных метрик (system_health класс) через тот же tracking pipeline.

Endpoint захвата (ingestion endpoint)

  • Адрес — отдельный поддомен, например events.<домен> для разделения сетевой нагрузки от программного интерфейса.
  • Протокол — HTTPS, типично POST с пакетным телом (batch payload).
  • Аутентификация — отдельный ключ доступа поверхности, не основной программный ключ. Это снижает блаsт-радиус компрометации.
  • Rate limiting — отдельная политика, защищающая от подрывного трафика без блокировки основного программного интерфейса.

Идемпотентность захвата

event_id — главная единица идемпотентности. Tracking pipeline на ingestion обнаруживает дубликаты по (tenant_id, event_id) и отбрасывает их. Это критически важно для:

  • Локальной буферизации на стороне поверхности (повторная отправка после потери соединения).
  • Партнёрской переотправки (партнёр повторил запрос из-за тайм-аута).
  • Replay-сценариев при отладке tracking-пайплайна.

Каноничная модель хранилища данных (DWH)

Принцип отдельного класса хранилища

Хранилище данных — отдельный класс хранилища от operational layer и transactional layer, как зафиксировано в Хранение и Ось данных и интеллекта. Свойства:

  • Оптимизировано для аналитических запросов (агрегации, оконные функции, сложные соединения по большим объёмам).
  • Колоночное хранение (columnar storage) — типично 10–100× быстрее операционных запросов на агрегации.
  • Партиционирование по времени и тенанту.
  • Низкая стоимость хранения за единицу — много данных хранится дёшево.
  • Eventual consistency приемлема — задержка минут/часов между событием и доступностью в DWH допустима.

Звёздная схема (star schema)

Каноничная модель DWH — звёздная схема с таблицами фактов в центре и таблицами измерений по краям.

Таблицы фактов (fact tables)

  • fact_search_events — поведенческие события поиска.
  • fact_proposal_events — события презентации предложений (просмотр, шаринг, отбрасывание).
  • fact_booking_funnel — события пути от поиска до бронирования.
  • fact_post_booking — события после бронирования (изменения, отмены, возвраты).
  • fact_partner_usage — потребление платформы партнёром (вызовы, метрики тарификации).
  • fact_payment_events — события платёжного контура.
  • fact_supplier_health — здоровье поставщиков (задержки, доля отказов, свежесть данных).
  • fact_system_health — внутренняя операционная метрика платформы.

Каждая таблица фактов:

  • Партиционирована по event_date (день события) и tenant_id.
  • Содержит ссылки на ключи измерений (foreign keys).
  • Содержит числовые меры (measures) — продолжительность, количество, сумма.
  • Не содержит обновляемых полей — только append-only вставки.

Таблицы измерений (dimension tables)

  • dim_tenant — информация о тенантах с историей изменений (тип медленно меняющегося измерения 2, slowly changing dimension type 2).
  • dim_property — каноничная информация об объектах размещения с историей.
  • dim_supplier — поставщики с историей профилей.
  • dim_partner — партнёры с историей тарифов и классов.
  • dim_geo — иерархия регионов.
  • dim_calendar — календарь дат с признаками (день недели, праздник, сезон).
  • dim_currency — валюты с курсами на конкретные даты.
  • dim_event_schema — версии схем событий с историей изменений.

Медленно меняющиеся измерения (slowly changing dimensions)

Для измерений, чьи атрибуты меняются со временем (например, тариф партнёра), применяется тип 2 медленно меняющихся измерений:

  • При изменении атрибута создаётся новая строка с новым surrogate_key.
  • Старая строка остаётся, но получает valid_to дату.
  • Связи фактов с измерениями делаются по surrogate_key, что даёт корректный исторический контекст для каждого факта.

Например, если партнёр перешёл со Starter на Professional 1 марта, факты до 1 марта связаны с измерением «Starter», после — с «Professional». Это критично для финансовой отчётности.

Партиционирование (partitioning)

  • По времени — таблицы фактов партиционированы по дню (или часу для очень больших объёмов).
  • По тенанту — для крупных тенантов выделена отдельная сабпартиция.
  • Жизненный цикл — старые партиции (старше политики хранения) автоматически перемещаются в холодное хранилище (cold storage) или удаляются.

Запросы кросс-тенантной агрегации

См. секцию «Правила межтенантной агрегации» ниже.

Классы приватности полей (privacy classes per data field)

Каждое поле в аналитическом событии и в DWH помечается классом приватности:

КлассОписаниеПример
pii_strictПрямой персональный идентификатор. Запрещён в аналитике.Имя, фамилия, email, телефон, паспорт, IP-адрес как есть
pii_indirectКосвенный идентификатор, который в комбинации может идентифицировать. Допустимо только как хеш.Хеш email, хеш номера телефона
quasi_identifierАтрибут, который в сочетании с другими может позволить ре-идентификацию. Требует k-анонимизации (k-anonymity) при экспорте.Точный возраст, точный почтовый индекс, редкая профессия
behavioralПоведенческий след — что пользователь делал. Не идентифицирует напрямую, но может быть привязан к актёру в системе.Просмотренные предложения, применённые фасеты, время сессии
aggregate_onlyАгрегированные данные, не привязанные к индивидуальному актёру.Среднее время сессии по тенанту, гистограмма цен
publicПубличные данные, не относящиеся к персоналиям.Каноничные имена отелей, регионы, валюты

Правила обработки по классу

КлассХранится в DWHВидно MLВидно партнёрской аналитикеСрок хранения
pii_strict❌ Никогда❌ Никогда❌ НикогдаТолько в operational layer с retention правилами
pii_indirect✅ Только как хеш✅ Только как хешПо правилам ниже
quasi_identifier✅ С k-анонимизацией✅ С агрегацией✅ Только в агрегатахПо правилам ниже
behavioral✅ С actor_hash✅ Через feature store✅ Только в агрегатахПо правилам ниже
aggregate_onlyДолгосрочно
publicБессрочно

Запрет на повышение класса

Поле, отнесённое к классу pii_strict, не может быть переведено в более низкий класс без явного процесса повторной классификации с обоснованием в реестре схем. Понижение класса требует одобрения от владельца платформы.

Каноничная анонимизация при захвате

Аналитическое событие проходит обязательную анонимизацию на ingestion endpoint:

  • IP-адрес → отбрасывается (или заменяется на client_geo_class).
  • Прямые идентификаторы (email, телефон) → отбрасываются.
  • Косвенные (если переданы) → хеш с солью.
  • User agent → парсится в client_device_class, оригинал отбрасывается.

После анонимизации событие попадает в pipeline. Восстановить исходные данные невозможно — это design choice, не временное упрощение.

Правила межтенантной агрегации (multi-tenant aggregation rules)

Главный принцип

Тенант не видит данные другого тенанта. Это закреплено в Тенантная идентичность и изоляция. DWH следует тому же правилу.

Однако платформа может строить кросс-тенантные агрегаты для:

  • Внутренней аналитики платформы (производительность, инциденты, экономика).
  • Маркетинговых отчётов агрегированного характера (например, «средняя длительность бронирования по платформе»).
  • ML-моделей, обучаемых на данных всех тенантов (без раскрытия индивидуальных данных).

Правила доступа к кросс-тенантным запросам

СценарийКому разрешеноУсловия
Свои данные тенантаТенант, авторизованный сотрудник тенантаБез условий
Кросс-тенантные агрегаты для платформыКоманда платформы (data engineering, finance, leadership)Через специальные роли с журналом аудита
Кросс-тенантные агрегаты для тенантаТенант (только агрегаты, не индивидуальные данные)Минимум N тенантов в агрегате (k_min_tenants), типично 5–10
Кросс-тенантные индивидуальные данныеНикомуЗапрещено архитектурно
ML-модели, обучаемые на всех тенантахКоманда MLТолько модели; результаты модели возвращаются в области применения тенанта

k-анонимность для агрегатов тенантам

При предоставлении кросс-тенантной аналитики тенанту (например, «как ваша конверсия сравнивается с медианой платформы»):

  • Минимальное число тенантов в агрегате: k_min_tenants (типично 5).
  • Минимальное число событий в каждом тенанте: k_min_events (типично 100).
  • Если меньше — агрегат не возвращается; вместо этого возвращается ответ «недостаточно данных для сравнения».

Это защищает от ре-идентификации малых тенантов в агрегатах.

Журнал аудита кросс-тенантных запросов

Все кросс-тенантные запросы (от команды платформы или от тенантов через программный интерфейс аналитики) журналируются в audit log:

  • Кто запросил.
  • Когда.
  • Какой запрос (с параметрами).
  • Какой ответ (метрики результата, не сами строки).

Журнал доступен:

  • Для внутреннего ревью раз в квартал (compliance review).
  • Для регулятора при запросе.
  • Для тенанта — на свои собственные запросы.

Ограничение цели и политика хранения

Ограничение цели (purpose limitation)

По принципу общего регулирования защиты данных — данные собираются и хранятся только для определённой цели. Каждое событие в момент захвата помечается целью использования (purpose):

ЦельОписаниеКакие данные требуются
service_deliveryПредоставление услуги конечному клиентуПолная необходимая информация для бронирования
partner_billingБиллинг партнёра по фактическому потреблениюМетрики потребления, без поведенческих следов конечных клиентов
platform_analyticsВнутренняя аналитика платформыАгрегаты + поведенческие следы с анонимизацией
ml_trainingОбучение ML-моделей платформыПоведенческие данные с анонимизацией
partner_facing_analyticsАналитический продукт для партнёров (тарифы Professional, Enterprise)Агрегаты с k-анонимностью
compliance_auditХранение для регулятора (audit trail)Минимально необходимое; долгосрочно
security_incidentРасследование инцидентов безопасностиТехнические следы; ограниченное по времени хранение

Каждое поле в DWH доступно только для целей, для которых оно было захвачено. Запрос аналитики, требующий поля, не разрешённого для текущей цели, отбрасывается на уровне query layer.

Политика хранения (retention policy)

Срок хранения определяется классом хранения (retention_class):

КлассСрок храненияПрименимость
tx_audit7 летТранзакционные события (платежи, бронирования) — для соответствия фискальным требованиям
compliance_log10 летЖурнал согласия (consent log), журнал доступа к персональным данным
behavioral_long25 месяцевПоведенческие данные для долгосрочной аналитики (типичный максимум по общему регулированию защиты данных)
behavioral_short13 месяцевПоведенческие данные для краткосрочной операционной аналитики
system_metric13 месяцевСистемные метрики (производительность, инциденты)
aggregate_longБессрочноАгрегированные данные без PII
temp_processing30 днейВременные данные для текущей обработки

После истечения срока хранения данные физически удаляются из DWH (DROP partition). Это автоматический процесс, журналируется. Ручное удлинение срока запрещено — изменение политики возможно только через согласованный процесс с фиксацией в реестре политик.

Право быть забытым (right to be forgotten)

При запросе на удаление от субъекта данных (по общему регулированию защиты данных):

  • Поиск всех записей с этим actor_hash (если соль ротируется регулярно — поиск по нескольким текущим солям).
  • Удаление или анонимизация в operational layer.
  • В DWH — анонимизация (замена actor_hash на специальный «forgotten» хеш) с сохранением агрегационной целостности.
  • Журнал удаления — для доказательства регулятору.

Подробности — в Соответствие требованиям регуляторов.

Поток обработки данных и потоковая обработка

Архитектурные слои обработки

[Источники] → [Bronze layer] → [Silver layer] → [Gold layer] → [Потребители]
События Сырой Очищенный Агрегаты,
захват + обогащение готовые витрины

Бронзовый слой (bronze layer) — сырой захват

  • Все аналитические события записываются как есть, после анонимизации на ingestion.
  • Партиционирование по времени и тенанту.
  • Срок хранения — типично 30–90 дней.
  • Используется как источник для re-processing при изменении логики обработки.

Серебряный слой (silver layer) — очищенный и обогащённый

  • Дедупликация по event_id.
  • Обогащение измерениями (lookup в dim_* таблицы).
  • Обогащение производными атрибутами (например, is_first_session_for_actor, time_since_last_event).
  • Партиционирование как в бронзовом слое.
  • Срок хранения — по retention_class каждого события.

Золотой слой (gold layer) — агрегаты и витрины

  • Готовые таблицы фактов с агрегациями за день/час.
  • Готовые витрины для конкретных потребителей (отчёты, дашборды, ML feature store).
  • Срок хранения — долгий или бессрочный (агрегаты не несут PII).

Real-time vs batch обработка

Real-time (streaming) — для событий, требующих мгновенной обработки:

  • Системные метрики и инциденты (наблюдаемость).
  • Метрики тарификации в реальном времени (учёт потребления).
  • Сигналы для ML-моделей с быстрым обновлением (anti-fraud, dynamic pricing).
  • Алерты по аномалиям.

Batch — для остального:

  • Дневная/часовая агрегация в gold layer.
  • Долгосрочная аналитика.
  • Обучение ML-моделей (training).

Технологический выбор по фазам

ФазаBronze layerSilver layerGold layer / DWHReal-time
BootstrapPostgreSQL отдельная схемаPostgreSQL viewsPostgreSQL агрегатыПростой polling
2 (Production)Object Storage (Parquet)Управляемый ETL (managed pipeline)Управляемый ClickHouse / OpenSearch для аналитикиУправляемый Kafka + streaming consumer
3 (ML & analytics)Object Storage с Lake-форматом (Delta / Iceberg)Spark / Flink streamingSnowflake / BigQuery / отдельный ClickHouse кластерРасширенный streaming
4 (Multi-region)Multi-region Object StorageFederated processingMulti-region DWH с репликациейMulti-region Kafka

Конкретный выбор технологий — открытая развилка, эскалируется при выходе с фазы Bootstrap.

Закрытие технического долга 8

В Связь с реализацией → «Долг 8. Mixed domain и analytical events в events_themes» зафиксировано:

  • Текущее состояние: схема events_themes (DDL 2026-04-24) — единое хранилище для разных типов событий (доменных и аналитических смешанно).
  • Целевое состояние: разделение на domain_events через event bus + analytical_events через tracking pipeline в DWH.

План миграции

Этап 1. Параллельный захват (фаза Bootstrap → 2)

  • Развернуть tracking pipeline и DWH (фаза 2).
  • Все новые события писать параллельно в events_themes (как раньше) и в новый pipeline.
  • Период проверки — 2–3 месяца, сравнение данных.

Этап 2. Переключение потребителей (фаза 2)

  • Аналитические потребители переключаются на новый DWH.
  • Доменные потребители переключаются на event bus (Managed Kafka).
  • events_themes остаётся как fallback ещё 1–2 месяца.

Этап 3. Архивирование старой схемы (фаза 3)

  • events_themes помечается как deprecated.
  • Содержимое экспортируется в архивное хранилище для compliance.
  • Схема удаляется из активного использования.

Запрет на возврат к смешанной схеме

После завершения миграции — запрет на возврат к единому хранилищу. Это закрепляется как архитектурное правило, проверяется на каждом ревью.

Партнёрский продукт аналитики

Платформа предоставляет тенантам тарифа Professional и выше партнёрский продукт аналитики (partner-facing analytics product):

Что доступно

  • Свои метрики потребления (вызовы, бронирования, конверсия).
  • Свои метрики экономики (стоимость по тарифу, прогноз счёта).
  • Кросс-тенантные агрегаты для бенчмаркинга (с k-анонимностью).
  • Воронка от поиска до бронирования.
  • Качество поиска (CTR, доля отказов).

Как доступно

  • Дашборды в партнёрской консоли (см. Программный интерфейс как продукт).
  • Программный интерфейс аналитики (analytics API) для партнёров, желающих интегрировать в собственные системы.
  • Экспорт данных (data export) — выгрузка в формате CSV / Parquet для партнёров с большим объёмом (только тариф Enterprise).

Свежесть данных

  • Real-time метрики (метрики потребления, текущие вызовы) — задержка десятки секунд.
  • Дневные агрегаты — задержка часы (готовы на следующий день).
  • Длинные метрики (тренды) — задержка дни (еженедельная пересборка).

События платформы данных

Слой захвата событий и хранилища данных публикует операционные события (для собственного контура наблюдаемости):

СобытиеКогдаГлавные потребители
tracking.batch.receivedПри приёме батча событий на ingestionКонтур наблюдаемости
tracking.batch.validatedПосле валидации схемыКонтур наблюдаемости
tracking.event.droppedПри отбрасывании события (схема, rate limit, дубликат)Контур наблюдаемости, для аномалий — алерты
dwh.partition.materializedПосле материализации партиции в gold layerКонтур аналитики
dwh.retention.executedПосле выполнения политики хранения (удаление партиций)Контур compliance
dwh.privacy.anonymizedПосле анонимизации по запросу права быть забытымКонтур compliance
analytics.query.executedПосле выполнения аналитического запросаКонтур аудита

Фазы развёртывания

Фаза Bootstrap (0–6 месяцев)

Что разворачивается:

  • Каноничная модель AnalyticalEvent зафиксирована.
  • Простой tracking endpoint в основной службе платформы.
  • Хранение в отдельной схеме PostgreSQL (не в events_themes смешанной).
  • Реестр схем в виде набора JSON Schema файлов в репозитории.
  • Базовая анонимизация на захвате.
  • Простые дашборды через Grafana.

Триггер выхода:

  • Объём событий превышает 10 миллионов в день.
  • Появляются первые партнёрские запросы на аналитический продукт.

Фаза 2 — Production analytics (6–18 месяцев)

Что разворачивается:

  • Управляемый Kafka для tracking pipeline отдельно от event bus.
  • Управляемый ClickHouse или аналог как DWH-движок.
  • Потоковая обработка (streaming) для real-time метрик.
  • Полная политика хранения с автоматическим жизненным циклом партиций.
  • Партнёрский продукт аналитики для тарифа Professional.
  • Audit log кросс-тенантных запросов.
  • Запуск миграции с events_themes (этапы 1–2 закрытия долга 8).

Триггер выхода:

  • Готовность к обучению ML-моделей на данных платформы.
  • Расширение в новые регионы — нужны региональные требования к локализации данных.

Фаза 3 — ML и расширенная аналитика (18–30 месяцев)

Что разворачивается:

  • Lake-формат (Delta или Iceberg) на Object Storage.
  • Spark или Flink для серьёзной streaming-обработки.
  • ML feature store, интегрированный с DWH (см. Платформа машинного обучения, фаза 3).
  • Партнёрский программный интерфейс аналитики.
  • Экспорт данных для тарифа Enterprise.
  • Завершение миграции с events_themes (этап 3).

Фаза 4 — Многорегиональная зрелость (30+ месяцев)

Что разворачивается:

  • Многорегиональный DWH с репликацией.
  • Локализация данных по регионам (data residency) для регуляторных требований.
  • Federated query layer — запросы по нескольким регионам.
  • Snowflake или BigQuery как опция для крупнейших партнёров.

Архитектурные решения с тезисным обоснованием

Решение 1. Разделение доменных и аналитических событий — архитектурный закон

Цель: обеспечить операционную целостность доменного контура и аналитическую гибкость аналитического контура одновременно.

Тезисы:

  1. Доменные события — основа операционных контуров (booking, payment). Их потеря или дублирование ведёт к финансовым ошибкам.
  2. Аналитические события — основа маркетинговой и продуктовой аналитики. Их строгие гарантии не нужны, а гибкость схемы критична.
  3. Современные платформы верхнего уровня (Stripe, Twilio, Algolia) разделяют эти классы как стандарт.
  4. Это закреплено в Ось данных и интеллекта как главный принцип.

Альтернатива: единая шина событий для обоих классов. Отклонено: либо теряется операционная целостность, либо раздувается стоимость хранения и операционная нагрузка.

Принимаемые компромиссы:

  • Дублирование инфраструктуры (две шины, два хранилища). Это часть архитектуры, не накладные расходы.
  • Согласование между классами требует дисциплины — событие не должно дублироваться в обоих классах без обоснования.

Решение 2. Каноничная схема аналитического события с реестром схем

Цель: обеспечить эволюцию схемы без ломающих изменений и согласованную обработку всеми потребителями.

Тезисы:

  1. Аналитические события собираются из множества поверхностей разными командами (frontend, backend, партнёрские SDK). Без формальной схемы — хаос.
  2. Реестр схем с версионированием — стандарт индустрии (Confluent Schema Registry paradigm, AWS Glue Schema Registry paradigm).
  3. Без реестра невозможно безопасно эволюционировать аналитику — каждое изменение требует ревью и блокирует команды.

Решение 3. Анонимизация при захвате, не позже

Цель: минимизировать blast-радиус утечки и упростить compliance.

Тезисы:

  1. Если PII попадает в DWH в неанонимизированном виде — весь DWH становится PII-системой со всеми обязательствами.
  2. Анонимизация при захвате означает: даже при компрометации DWH персональные данные не утекут.
  3. Common Architecture Practices (Stripe, Twilio) — все так делают.

Принимаемые компромиссы:

  • Невозможность восстановить исходные данные. Это design choice, не недостаток.
  • Сложность реализации права быть забытым (требует ротации соли). Решается процессом.

Решение 4. Звёздная схема в DWH с медленно меняющимися измерениями

Цель: обеспечить корректный исторический контекст для аналитики и совместимость с большинством BI-инструментов.

Тезисы:

  1. Звёздная схема — стандарт DWH со времени Кимбола. Все BI-инструменты её понимают.
  2. Тип 2 медленно меняющихся измерений — единственный корректный способ обрабатывать исторические тарифы партнёров и подобное.
  3. Без типа 2 финансовая отчётность неточна (факт привязан к текущему атрибуту, не историческому).

Решение 5. Классы приватности и политика хранения как первоклассные сущности схемы

Цель: сделать соответствие нормативам автоматическим, не процессом.

Тезисы:

  1. Если приватность — это процесс ревью, она ломается под давлением. Если архитектурно — она работает.
  2. Каждое поле помечено классом приватности и классом хранения в момент создания. Изменение требует процесса.
  3. Политика хранения автоматически удаляет старые данные — без человеческого вмешательства.

Открытые развилки

Развилка 1. Конкретный движок DWH

OpenSearch / ClickHouse / Snowflake / BigQuery / Druid — выбор движка зависит от профиля нагрузки и стоимости. На фазе 2 — управляемый ClickHouse как разумный baseline; на фазе 3 — может потребоваться расширение или замена.

Эскалируется: при подготовке к фазе 2 (Production analytics).

Развилка 2. Конкретные сроки хранения внутри классов

behavioral_long — 25 месяцев максимум по общему регулированию защиты данных (типичная норма). Конкретный срок внутри допустимого диапазона зависит от бизнес-потребностей.

Эскалируется: при создании детальной таблицы политик с привязкой к конкретным метрикам.

Развилка 3. Партнёрский экспорт данных — формат и канал доставки

Для тарифа Enterprise возможен экспорт сырых поведенческих данных партнёру (с анонимизацией). Конкретный формат (CSV / Parquet / JSON) и канал доставки (S3 share / SFTP / managed API) — открыто.

Эскалируется: при появлении первых корпоративных партнёров с запросом на экспорт.

Развилка 4. Платформа экспериментов A/B — единая или раздельная

Платформа A/B-экспериментов (см. Платформа A/B-тестирования, фаза 4) использует часть инфраструктуры платформы данных. Развилка — насколько она самостоятельна или встроена.

Эскалируется: при создании документа A/B-платформы.

Развилка 5. Real-time ML feature serving — архитектурный путь

ML-модели платформы могут потреблять данные либо через периодическую выборку из DWH (фаза 3 baseline), либо через real-time feature store, обновляемый из streaming pipeline (фаза 4). Выбор зависит от ML-профиля и стоимости.

Эскалируется: при создании Платформа машинного обучения.

Связанная документация

Корневые архитектурные документы

Связанные доменные документы

Документы развития

Операционная сторона

Архитектурные правила

Уточнение под Фазы 5–6 (28.04.2026) — связь с booking state machine, isolation, security, DR

Документ опубликован 26.04.2026 в Фазе 4. После Фаз 5–6 (caнoничные углубления и операционная зрелость) платформа данных получила новые потоки событий и обязательств, которые должны быть явно зафиксированы для интеграции потребителями.

Связь со статусной машиной бронирования

reference/booking-state-machine.md (Фаза 5) фиксирует 14 каноничных состояний Booking. Каждое transition генерирует доменное событие:

  • booking.created (state: draft);
  • booking.submitted (state: submitted);
  • booking.revalidation_started (state: pending_revalidation);
  • booking.supplier_confirmation_started (state: pending_supplier_confirmation);
  • booking.supplier_confirmed (state: supplier_confirmed);
  • booking.platform_confirmed (state: platform_confirmed);
  • booking.partially_confirmed (state: partially_confirmed);
  • booking.unknown_external_state (state: unknown_external_state) — критическое событие, target SLI менее 1%;
  • booking.failed (state: failed);
  • booking.cancel_requested, booking.cancel_in_progress, booking.cancelled;
  • booking.amendment_in_progress;
  • booking.completed.

Все эти события — доменные события (domain events) с persistent journal, не аналитические. Они являются источниками истины для downstream consumers (operational dashboards, billing, compliance audit, SLA measurement).

booking_state_transition table — отдельный canonical persistent log в Tier 1 storage class (см. database-schema.md).

Связь с saga Tour Builder

reference/tour-builder-operational-model.md (Фаза 5) генерирует saga events:

  • tour.composition.created;
  • tour.composition.rule_violation_detected;
  • tour.booking_transaction.started;
  • tour.booking_transaction.compensation_triggered;
  • tour.drift.detected;
  • tour.drift.resolved;
  • tour.proposal.published;
  • tour.proposal.shared;
  • tour.proposal.viewed;
  • tour.proposal.accepted_for_conversion.

Saga events — гибрид domain + analytical: persistent для transaction integrity, но также используются для analytics (accepted_for_conversion rate, drift frequency per supplier).

Связь с уровнями тенантной изоляции и k-anonymization

reference/multi-tenant-isolation-strength.md (Фаза 5) определяет 3 уровня изоляции, прямо влияющие на платформу данных:

  • logical — события всех tenants в общем DWH, partitioned by tenant_id, RLS policies на queries;
  • dedicated_compute — отдельный DWH namespace per tenant, или схема в shared cluster;
  • dedicated_infrastructure — отдельный DWH cluster per tenant (Enterprise mandatory для regulated).

Cross-tenant aggregation rules:

  • запрос с агрегацией по нескольким тенантам — минимальный размер группы k=10 (k-anonymity);
  • если cohort менее k — запрос отклоняется или возвращается с suppressed values;
  • audit log каждого cross-tenant aggregation request (включая identity делавшего запрос).

IsolationBoundaryCheck (continuous automated проверка) — отдельный канал событий:

  • isolation.check.started, isolation.check.completed, isolation.check.breach_detected;
  • target: 0 successful breaches за rolling 90 дней.

Связь с security architecture и audit logging

reference/security-architecture.md (Фаза 10) фиксирует canonical audit log как immutable storage (WORM-grade). Audit events — отдельный класс между domain и analytical:

Каноничные security/audit events:

  • auth.login.success, auth.login.failed, auth.mfa.required, auth.mfa.success, auth.mfa.failed;
  • auth.token.issued, auth.token.revoked, auth.session.expired;
  • authz.action.executed, authz.action.denied, authz.privilege.escalated;
  • data.sensitive.accessed (PII access — обязательно для GDPR);
  • data.exported (bulk export — для exfiltration monitoring);
  • data.cross_tenant.attempted;
  • admin.user.created, admin.role.modified, admin.config.changed;
  • admin.secret.rotated, admin.secret.revoked;
  • security.suspicious_activity.detected, security.brute_force.detected, security.data_breach.detected.

Audit log — отдельный pipeline, не смешивается с analytical events. Retention 7 лет (Tier 1), tamper detection через hash chains, доступ только через explicit roles.

Связь со SLA измерением

operations/sla-and-on-call-model.md (Фаза 6) использует data platform для измерения SLI:

Каноничные SLI metrics, источник — data platform:

  • availability per surface (на основе analytical event request_received + status code);
  • latency p95 (на основе request_completed events);
  • webhook delivery (на основе webhook.delivery.attempted / webhook.delivery.completed);
  • search freshness (на основе search response cache age);
  • booking confirmation latency (на основе booking state transitions);
  • unknown_external_state ratio (на основе booking state events);
  • payment success rate (на основе payment events);
  • restoration success rate (на основе DR events — см. ниже);
  • MTTR (на основе incident events);
  • support response time (на основе support ticket events).

Data platform — базовая инфраструктура для SLI/SLO measurement; без неё SLA — формальное обещание без измерения.

Связь с DR и capacity events

operations/disaster-recovery-and-capacity.md (Фаза 6) генерирует отдельный класс операционных событий:

DR events:

  • dr.recovery.declared, dr.recovery.point_selected, dr.recovery.restored_to_staging;
  • dr.recovery.smoke_tests_passed, dr.recovery.promoted_to_production, dr.recovery.completed;
  • dr.recovery.postmortem_completed;
  • dr.backup.created, dr.backup.verified, dr.backup.expired;
  • dr.drill.scheduled, dr.drill.started, dr.drill.completed_successful, dr.drill.completed_with_issues, dr.drill.failed.

Capacity events:

  • capacity.forecast.created, capacity.forecast.updated;
  • capacity.threshold.warning_triggered, capacity.threshold.critical_triggered;
  • capacity.provisioning.requested, capacity.provisioning.completed;
  • capacity.degradation.activated, capacity.degradation.deactivated.

Эти события — operational class между domain и analytical: persistent для audit, но также используются для capacity forecasting и SLA reports.

Связь с runbooks и incident events

operations/runbooks-incident-playbooks.md (Фаза 6) генерирует:

  • incident.detected, incident.runbook.started, incident.runbook.step_completed;
  • incident.escalated, incident.resolved;
  • incident.postmortem.scheduled, incident.postmortem.completed;
  • incident.action_item.created, incident.action_item.resolved.

Incident events — operational class, retention в audit log (7 лет для regulated incidents).

Связь с compliance событиями

reference/compliance-and-legal.md (Фаза 4) определяет:

  • compliance.dsr.received (Data Subject Request);
  • compliance.dsr.responded;
  • compliance.consent.collected, compliance.consent.withdrawn;
  • compliance.retention.cleanup_executed;
  • compliance.breach.detected, compliance.breach.notified;
  • compliance.dpa.signed;
  • compliance.audit.started, compliance.audit.completed.

Compliance events — regulatory class, обязательны для GDPR audit trail.

Каноничный итог уточнения

Платформа данных и events tracking теперь интегрирована со всеми операционными доменами Фаз 5–6:

Класс eventsИсточникStorageRetention
Domain events (caнoничные state transitions)сервисыevent log + transactional layerдолгий (audit)
Analytical events (поведение)поверхности взаимодействияDWH (ClickHouse/PostgreSQL)class-зависимый
Saga events (Tour Builder)tour-builder-serviceгибрид event log + DWHдолгий
Audit events (security)все servicesimmutable WORM storage7 лет (Tier 1)
Operational events (DR, capacity, incidents)runbooks, capacity service, DR serviceevent log + DWHдолгий (regulated)
Compliance events (GDPR/audit)compliance pipelineimmutable audit log7+ лет

Все классы потребляют общую infrastructure (event bus, schema registry, retention enforcement), но имеют разные guarantees и разные access controls.

При создании контрактов consumers — использовать каноничные имена событий из специализированных документов (см. ссылки выше), не «придумывать локально».

Уточнение выполнено через no-destruction.