Мост к склейке: user_id и двухкуковые пары #73

Closed
opened 2026-08-07 20:44:27 +03:00 by ddmitry · 1 comment
Owner

Part of #69.

Вопрос

Откуда берётся user_id заказа и как он согласуется с двухкуковыми парами генератора событий?

Мастер-спека (раздел 5) обещает: карта соответствий кука↔пользователь строится только из покупок, и каждый двухкуковый покупатель делает минимум по одному заказу с каждой куки — иначе вторая кука в карту не попадает и лаба uniq(посетителей) > uniq(людей) не воспроизводится.

Сегодня это обещание не обеспечено ничем: пары живут в генераторе событий, а user_id придёт из генератора заказов. Решить, кто из них хозяин соответствия и как оно переживает раздельные прогоны.

Part of #69. ## Вопрос Откуда берётся `user_id` заказа и как он согласуется с двухкуковыми парами генератора событий? Мастер-спека (раздел 5) обещает: карта соответствий кука↔пользователь строится **только из покупок**, и каждый двухкуковый покупатель делает минимум по одному заказу с каждой куки — иначе вторая кука в карту не попадает и лаба `uniq(посетителей) > uniq(людей)` не воспроизводится. Сегодня это обещание не обеспечено ничем: пары живут в генераторе событий, а `user_id` придёт из генератора заказов. Решить, кто из них хозяин соответствия и как оно переживает раздельные прогоны.
ddmitry added the wayfinder:grilling label 2026-08-07 20:44:27 +03:00
ddmitry self-assigned this 2026-08-16 11:07:58 +03:00
Author
Owner

Резолюция

Линза. Менти учится не устройству генератора, а данным и лабам: генератор имитирует поток Метрики и второй источник магазина. Внутренняя конструкция оправдана только тогда, когда даёт наблюдаемый правдоподобный эффект; проверки ради проверок и универсальные гарантии стенду не нужны.

Причинная модель

План состава порождает человека. Человеку принадлежат одна или две куки; каждая наблюдается в кликстриме как отдельный посетитель (ClientID). Визит может оформить заказ, и тогда заказная сторона представляет того же человека как пользователя магазина (user_id).

Это не автомат состояний и не модель аккаунта: регистрация не появляется, люди, которые никогда не посетят сайт, не порождаются, а внутреннее знание о человеке наружу не выдаётся. Значение принятого термина «покупатель» не меняется: это скрытая склонность покупать, а не факт заказа.

Кто владеет связью

План состава владеет устойчивой личностью человека и отношением «кука принадлежит человеку». Минимальная форма — один непрозрачный внутренний person_id, выровненный по кукам: у двух кук пары он одинаков. Богатой сущности Person с состоянием и поведением не заводится.

Заказная проекция владеет представлением этой личности: то же числовое значение выходит в записи заказа под родным именем user_id и типом UInt64. В кликстрим ни person_id, ни user_id не попадает. ID назначается всем людям состава, но наблюдаемым становится только через заказ; это не утверждение, что вся аудитория зарегистрирована.

Раздельные прогоны ничего не хранят и не согласуют: генератор событий и команда слепка заново спрашивают один и тот же план и при одинаковых зерне и версии мира получают тот же person_id.

Откуда берётся ID

person_id — последний обычный бросок существующего потока случайности когорты, после уже принятых свойств. Поэтому добавление личности не сдвигает нынешние куки, пары, возвраты и паспорта. Для второй куки повторяется ID её человека. Значения остаются в безопасном для обычных средств чтения JSON диапазоне ниже 2^53.

Нового подпотока, структурной упаковки дня и номера человека, глобального реестра и отдельного обещания стабильности между версиями мира нет. Межкогортные столкновения принимаются по той же дисциплине, что у случайных ClientID: бесконечная ось не доказывается, принимается конкретный канонический мир по внешнему результату. Смена предшествующих бросков — смена мира и может сменить ID вместе с описью.

Граница и наблюдаемое обещание

Внутренний ключ идёт рядом с дневной аудиторией и структурой заказа, но не становится временной колонкой 47-полевого события: так анонимность формата держится формой, а не забывчивостью сериализатора.

На выходе достаточно четырёх свойств:

  • назначенные заказы двухкуковой пары с разных ClientID несут один user_id;
  • событие Метрики не раскрывает user_id;
  • отдельные прогоны с одним миром дают то же соответствие;
  • принятый мир воспроизводит наблюдаемый эффект склейки без случайных ложных объединений; конкретные числа пар и известных пользователей контрактом описи не являются.

Ранее принятое решение «назначенные покупки не теряются и назначенные заказы не опаздывают» защищает мост от модельной порчи после отправки обеих сторон. На свежем стенде последний слепок намеренно ещё не выгружен, поэтому часть пар появится в dds.identity_map после следующего хода мира; граница решена в «Месте заказов в стартовом мире».

Отклонено

  • Заказная сторона сама назначает личность: родство двух кук всё равно пришлось бы спрашивать у плана, владелец вышел бы номинальным.
  • Материализованный реестр кука↔пользователь: состояние между прогонами, жизненный цикл и рассинхронизация без нового внешнего эффекта.
  • Первая кука как ID человека: магазин оказался бы замаскированным продолжением трекера, а человек — своим первым браузером.
  • Структурная координата, хеш, отдельный подпоток или глобальная последовательность: больше механики и обещаний, но те же данные на выходе; глобальная последовательность вдобавок ломает постоянную стоимость дня.
  • Полная модель аккаунтов и регистрации: менти её не наблюдает, а генератор и без неё уже даёт нужную причинную связь.

Словарь

В CONTEXT.md разведены три взгляда: человек — скрытая истина состава мира, посетитель — наблюдаемая кука и единица uniq(ClientID), пользователь магазина — представление человека в заказе. Термин «покупатель» не переопределён.

## Резолюция **Линза.** Менти учится не устройству генератора, а данным и лабам: генератор имитирует поток Метрики и второй источник магазина. Внутренняя конструкция оправдана только тогда, когда даёт наблюдаемый правдоподобный эффект; проверки ради проверок и универсальные гарантии стенду не нужны. ### Причинная модель План состава порождает **человека**. Человеку принадлежат одна или две куки; каждая наблюдается в кликстриме как отдельный **посетитель** (`ClientID`). Визит может оформить заказ, и тогда заказная сторона представляет того же человека как **пользователя магазина** (`user_id`). Это не автомат состояний и не модель аккаунта: регистрация не появляется, люди, которые никогда не посетят сайт, не порождаются, а внутреннее знание о человеке наружу не выдаётся. Значение принятого термина «покупатель» не меняется: это скрытая склонность покупать, а не факт заказа. ### Кто владеет связью План состава владеет устойчивой личностью человека и отношением «кука принадлежит человеку». Минимальная форма — один непрозрачный внутренний `person_id`, выровненный по кукам: у двух кук пары он одинаков. Богатой сущности `Person` с состоянием и поведением не заводится. Заказная проекция владеет представлением этой личности: то же числовое значение выходит в записи заказа под родным именем `user_id` и типом `UInt64`. В кликстрим ни `person_id`, ни `user_id` не попадает. ID назначается всем людям состава, но наблюдаемым становится только через заказ; это не утверждение, что вся аудитория зарегистрирована. Раздельные прогоны ничего не хранят и не согласуют: генератор событий и команда слепка заново спрашивают один и тот же план и при одинаковых зерне и версии мира получают тот же `person_id`. ### Откуда берётся ID `person_id` — последний обычный бросок существующего потока случайности когорты, после уже принятых свойств. Поэтому добавление личности не сдвигает нынешние куки, пары, возвраты и паспорта. Для второй куки повторяется ID её человека. Значения остаются в безопасном для обычных средств чтения JSON диапазоне ниже `2^53`. Нового подпотока, структурной упаковки дня и номера человека, глобального реестра и отдельного обещания стабильности между версиями мира нет. Межкогортные столкновения принимаются по той же дисциплине, что у случайных `ClientID`: бесконечная ось не доказывается, принимается конкретный канонический мир по внешнему результату. Смена предшествующих бросков — смена мира и может сменить ID вместе с описью. ### Граница и наблюдаемое обещание Внутренний ключ идёт рядом с дневной аудиторией и структурой заказа, но не становится временной колонкой 47-полевого события: так анонимность формата держится формой, а не забывчивостью сериализатора. На выходе достаточно четырёх свойств: - назначенные заказы двухкуковой пары с разных `ClientID` несут один `user_id`; - событие Метрики не раскрывает `user_id`; - отдельные прогоны с одним миром дают то же соответствие; - принятый мир воспроизводит наблюдаемый эффект склейки без случайных ложных объединений; конкретные числа пар и известных пользователей контрактом описи не являются. Ранее принятое решение «назначенные покупки не теряются и назначенные заказы не опаздывают» защищает мост от модельной порчи после отправки обеих сторон. На свежем стенде последний слепок намеренно ещё не выгружен, поэтому часть пар появится в `dds.identity_map` после следующего хода мира; граница решена в [«Месте заказов в стартовом мире»](https://git.dementev.space/ddmitry/clickstream-data-platform/issues/74). ### Отклонено - *Заказная сторона сама назначает личность*: родство двух кук всё равно пришлось бы спрашивать у плана, владелец вышел бы номинальным. - *Материализованный реестр кука↔пользователь*: состояние между прогонами, жизненный цикл и рассинхронизация без нового внешнего эффекта. - *Первая кука как ID человека*: магазин оказался бы замаскированным продолжением трекера, а человек — своим первым браузером. - *Структурная координата, хеш, отдельный подпоток или глобальная последовательность*: больше механики и обещаний, но те же данные на выходе; глобальная последовательность вдобавок ломает постоянную стоимость дня. - *Полная модель аккаунтов и регистрации*: менти её не наблюдает, а генератор и без неё уже даёт нужную причинную связь. ### Словарь В `CONTEXT.md` разведены три взгляда: человек — скрытая истина состава мира, посетитель — наблюдаемая кука и единица `uniq(ClientID)`, пользователь магазина — представление человека в заказе. Термин «покупатель» не переопределён.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: ddmitry/clickstream-data-platform#73