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

Domain Model — Центральная доменная модель платформы

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

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

Этот документ фиксирует центральную доменную модель vitiana-api-platform как главный смысловой каркас всей платформы.

Его задача — жёстко определить:

  • какие сущности являются каноническими;
  • какие сущности являются supplier-derived, operational или transactional;
  • где проходят границы ответственности между сущностями;
  • как сущности связаны между собой;
  • какие жизненные циклы являются ключевыми;
  • где находятся источники истины;
  • какие доменные различия нельзя больше размывать в других документах.

Пока такой документ не зафиксирован, все остальные материалы будут продолжать либо спорить друг с другом, либо подменять домен UI, API, БД или инфраструктурой.

Опорные документы

Почему Это Главный Документ Следующего Слоя

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

Практический смысл этого вывода простой:

  • без неё database-schema.md рискует быть либо слишком ранним, либо слишком механическим;
  • без неё api-contracts.md будет вынужден гадать, какие resource families являются настоящими;
  • без неё clients.md и business-services.md будут описывать разные представления одной и той же реальности;
  • без неё identity, offer, quote, booking, tour builder и governance останутся распылёнными по нескольким документам.

Поэтому этот документ должен стать смысловой опорой для следующих шагов.

Главный Доменный Принцип

Платформа строится не вокруг "отеля", не вокруг "API", не вокруг "бронирования" и не вокруг "сайта". Она строится вокруг канонического продуктового ядра, которое соединяет:

  • stable content and inventory identity;
  • supplier-specific product reality;
  • operational offer state;
  • commercial and quote context;
  • transactional booking state;
  • tour composition and proposal lifecycle.

Это означает, что доменная модель платформы должна одновременно удерживать:

  • стабильное и изменчивое;
  • каноническое и supplier-specific;
  • read-oriented и commit-oriented;
  • human-facing и machine-facing;
  • внутреннее и внешнее.

Главные Классы Доменных Сущностей

На текущем этапе сущности нужно различать по их роли в truth-модели платформы.

1. Canonical Master Entities

Это долгоживущие сущности платформенного ядра.

Сюда входят:

  • Property
  • CanonicalProduct
  • Organization
  • User
  • Partner
  • Agency
  • PolicySet
  • GovernanceDecision

2. Supplier-Derived Entities

Это сущности, которые выражают supplier reality и не должны маскироваться под canonical truth.

Сюда входят:

  • Supplier
  • SupplierProperty
  • SupplierProduct
  • SupplierPayload
  • SupplierSyncRun
  • SupplierCapabilityProfile
  • SupplierBookingReference

3. Operational Offer Entities

Это сущности краткоживущего, но доменно важного операционного слоя.

Сюда входят:

  • Offer
  • AvailabilitySnapshot
  • PriceSnapshot
  • Quote
  • RevalidationResult
  • SearchSession

4. Transactional Entities

Это сущности транзакционного и audit-critical слоя.

Сюда входят:

  • Booking
  • BookingItem
  • BookingEvent
  • PaymentIntent
  • Refund
  • AmendmentRequest

5. Composition Entities

Это сущности, связанные со сборкой составного продукта.

Сюда входят:

  • TourDraft
  • TourDraftItem
  • TourProposal
  • ProposalVersion
  • ProposalArtifact

6. Governance And Review Entities

Это сущности управления качеством, конфликтами и ручным решением.

Сюда входят:

  • ReviewCase
  • MappingDecision
  • MergeDecision
  • Anomaly
  • FieldLineage
  • SourcePrecedenceRule

7. Identity, Tenancy And Access Entities

Это сущности организационного и access-контекста.

Сюда входят:

  • Tenant
  • Workspace
  • RoleAssignment
  • CapabilityGrant
  • ApiClient
  • ApiCredential

Канонические Сущности Платформенного Ядра

Ниже зафиксированы сущности, без которых платформа не может считаться доменно определённой.

1. Property

Property — каноническая мастер-сущность объекта размещения как устойчивого объекта платформы.

Она отвечает за:

  • доменную идентичность объекта;
  • канонический адрес и географическую привязку;
  • устойчивые категории и классификацию;
  • базовый контентный каркас;
  • связь с регионами и destination model;
  • привязку supplier representations к одной платформенной сущности.

Property не является:

  • ценой;
  • доступностью;
  • booking unit;
  • supplier truth;
  • готовым к продаже offer.

2. SupplierProperty

SupplierProperty — supplier-specific представление того, что потенциально соответствует Property.

Оно нужно для:

  • хранения supplier IDs;
  • traceability источника;
  • различий в контенте и структуре;
  • понимания, какие поля пришли от какого source;
  • mapping and merge logic.

SupplierProperty не должен напрямую подменять canonical Property.

3. CanonicalProduct

CanonicalProduct — каноническая продуктовая единица внутри property context.

Она нужна, чтобы не мыслить всё только через room_type, потому что в реальном travel domain продуктовая единица может включать:

  • тип размещения;
  • occupancy capacity;
  • meal semantics;
  • cancellation semantics;
  • supplier-specific variants;
  • policy-sensitive distinctions.

CanonicalProduct — это не обязательно окончательная sellable единица. Но это базовый стабильный продуктовый каркас платформы.

4. SupplierProduct

SupplierProduct — supplier-specific продаваемая или квазипродаваемая единица.

Она важна для:

  • связи с supplier property;
  • mapping to canonical product;
  • понимания supplier-specific условий;
  • offer generation;
  • booking correlation.

5. Offer

Offer — центральная operational сущность платформы.

Именно Offer является основной единицей:

  • для показа;
  • для сравнения;
  • для перехода к quote;
  • для revalidation;
  • для потенциального booking intent.

Offer должен описывать:

  • product basis;
  • property context;
  • supplier basis;
  • date scope;
  • occupancy scope;
  • price view;
  • availability status;
  • cancellation and restriction summary;
  • freshness and validity hints;
  • eligibility for next action.

Offer не является:

  • stable master entity;
  • окончательным booking commitment;
  • простой hotel-card summary.

6. Quote

Quote — это фиксированный коммерческий и операционный снимок, который связывает Offer с конкретным actor/tenant/channel context.

Он нужен, когда платформа должна зафиксировать:

  • что именно было выбрано;
  • какая price view была рассчитана;
  • какие assumptions действовали;
  • как долго эта фиксация считается пригодной;
  • на каких условиях возможен переход к booking.

Quote — не просто "пересчитанная цена". Это самостоятельная доменная единица между discovery и booking commitment.

7. Booking

Booking — транзакционная сущность платформы, отражающая попытку, процесс и результат коммерческого commit-действия.

Она должна удерживать одновременно:

  • platform booking identity;
  • source quote or validated context;
  • traveler data;
  • payment/commercial context;
  • supplier-side correlation;
  • state machine;
  • audit trail;
  • failure and amendment history.

Booking не должен мыслиться как простая запись выбора отеля.

8. TourDraft

TourDraft — рабочая композиционная сущность, позволяющая собрать будущий продукт без обязательного немедленного commit-а.

Она нужна для:

  • работы агентства;
  • подготовки вариантов;
  • ручной сборки маршрута;
  • добавления и замены элементов;
  • экспериментирования с составом предложения.

9. TourProposal

TourProposal — коммерчески представляемая форма собранного продукта.

Она должна:

  • иметь versioning;
  • фиксировать состав продукта на момент предложения;
  • связываться с клиентским или partner-facing presentation;
  • сохранять trace to underlying draft, offers and quotes.

10. Organization Family

Платформа не может ограничиться одной сущностью "компания". Уже сейчас нужно различать:

  • Agency
  • Partner
  • InternalOrganizationUnit, если понадобится
  • Tenant

Потому что эти сущности имеют разную роль в:

  • коммерческой модели;
  • доступе;
  • API contracts;
  • видимости данных;
  • reporting and settlement.

11. User And Actor

User как identity-сущность недостаточен сам по себе. В платформе важно различать:

  • identity субъекта;
  • организационную принадлежность;
  • рабочий контекст;
  • capability scope;
  • actor type в конкретном сценарии.

Поэтому User и ActorContext должны мыслиться раздельно, даже если в БД часть этого хранится совместно.

Связи Между Главными Сущностями

Ниже — не ERD, а смысловая карта связей.

Property ↔ SupplierProperty

  • один Property может иметь много SupplierProperty;
  • один SupplierProperty должен вести к одному canonical mapping outcome в конкретный момент времени;
  • mapping может быть auto, reviewed or unresolved.

Property ↔ CanonicalProduct

  • один Property содержит один или много CanonicalProduct;
  • CanonicalProduct не обязан один в один соответствовать supplier room type.

CanonicalProduct ↔ SupplierProduct

  • один canonical product может иметь много supplier products;
  • один supplier product может быть unmapped, ambiguously mapped or explicitly mapped.

SupplierProduct ↔ Offer

  • один supplier product может порождать много Offer по датам, occupancy и policy combinations;
  • Offer всегда должен сохранять trace to supplier basis.

Offer ↔ Quote

  • один offer может порождать много quote-ов;
  • quote всегда фиксирует actor/channel/commercial context;
  • quote должен уметь стареть и истекать.

Quote ↔ Booking

  • booking ideally должен возникать из quote или equivalent validated basis;
  • один quote может привести к нулю, одному или нескольким booking-related actions, в зависимости от домена;
  • booking не должен терять связь с quote basis.

TourDraft ↔ Offer / Quote / Booking

  • draft может включать offers and quotes;
  • proposal может ссылаться на несколько underlying quote snapshots;
  • часть draft/proposal элементов может перейти в booking artifacts;
  • при этом композиционный слой не должен терять traceability.

Organization / Tenant / User ↔ Quote / Booking / Proposal

  • quote виден и валиден в конкретном actor context;
  • booking имеет ownership and responsibility context;
  • proposal создаётся не "анонимным UI", а конкретным actor в конкретном tenancy/commercial scope.

Truth Boundaries Между Сущностями

Одна из самых важных задач этого документа — развести truth boundaries.

Stable Master Truth

К ней относятся:

  • Property
  • часть CanonicalProduct
  • Organization / Tenant / User identity
  • PolicySet
  • reviewed governance outcomes

Supplier Truth

К ней относятся:

  • SupplierProperty
  • SupplierProduct
  • SupplierPayload
  • supplier-specific policy fragments
  • source-side availability and price signals

Operational Truth

К ней относятся:

  • Offer
  • AvailabilitySnapshot
  • PriceSnapshot
  • Quote
  • RevalidationResult

Transactional Truth

К ней относятся:

  • Booking
  • BookingEvent
  • PaymentIntent
  • Refund
  • AmendmentRequest

Governance Truth

К ней относятся:

  • ReviewCase
  • MergeDecision
  • MappingDecision
  • FieldLineage
  • SourcePrecedenceRule

Эти truth layers нельзя смешивать в одни и те же поля и одни и те же API-объекты без явного указания.

Главные Доменные Границы

1. Property Boundary

Это граница stable identity and content.

Она не должна включать:

  • quote state;
  • booking state;
  • volatile price truth.

2. Offer Boundary

Это граница между stable product basis и short-lived commercially meaningful opportunity.

Именно здесь сходятся:

  • supplier-derived signals;
  • availability;
  • pricing;
  • restrictions;
  • actionability.

3. Quote Boundary

Это граница между actionable opportunity и actor-specific commercial fixation.

Без этой границы platform contracts будут либо нечестными, либо нестабильными.

4. Booking Boundary

Это граница commit-oriented transactional state.

Здесь уже нельзя мыслить сущность как read model.

5. Tour Composition Boundary

Это граница составного продукта, который живёт поверх offer/quote/booking, но не редуцируется к ним.

6. Governance Boundary

Это граница, где автоматизация заканчивается и начинается управляемое объяснимое решение.

Жизненные Циклы, Которые Нужно Считать Основными

Обновление под Фазы 5–6 каноничной архитектуры (28.04.2026)

После Фаз 4–6 каноничной архитектуры (25–27.04.2026) ряд жизненных циклов и составов сущностей этого документа дополнен и углублён в специализированных документах второго круга. Этот документ остаётся как сводный базовый каркас, но детальная истина по жизненным циклам теперь живёт в специализированных документах ниже.

Booking lifecycle — каноничная истина в booking-state-machine.md

Запись в этом документе («draft intent → submitted → pending revalidation → pending supplier confirmation → confirmed / failed → amended / cancelled / completed») — упрощённая для смыслового каркаса. Каноничная истина — 14 состояний в reference/booking-state-machine.md:

draft_intent → submitted → pending_revalidation
→ pending_supplier_confirmation
→ supplier_confirmed → platform_confirmed
→ partially_failed
→ failed
→ unknown_external_state ← критическое 8-е состояние
→ cancel_requested → cancel_pending → cancelled
→ amendment_requested → amendment_in_progress
→ completed

Ключевые отличия каноничной модели от упрощённой записи выше:

  • confirmed разделён на supplier_confirmed (ack от поставщика) и platform_confirmed (запись в платформенной transactional truth) — это разные истины, нельзя смешивать (правило 00000);
  • появилось каноничное состояние unknown_external_state — поставщик не отвечает или ответил некорректно, платформа не знает существует ли бронирование. Это базовый SLI платформы (см. operations/sla-and-on-call-model.md, SLI 6, target менее 1%);
  • cancelled разделён на 3 шага (cancel_requested → cancel_pending → cancelled) для корректной обработки supplier-side delays;
  • amendment разделён на 2 шага (amendment_requested → amendment_in_progress).

Все internal/agency/operator контракты обязаны различать эти состояния.

TourDraft / TourProposal lifecycle — каноничная истина в tour-builder-operational-model.md

Запись в этом документе («draft → iterated → proposed → versioned → partially consumed / archived») — упрощённая. Каноничная истина в overview/canonical-domain-spine.md и reference/tour-builder-operational-model.md:

TourDraft lifecycle:

created → editing → structured
→ awaiting_repricing ← подождать актуализацию цен
→ awaiting_revalidation ← подождать revalidation underlying offers
→ ready_for_proposal
→ archived

TourProposal lifecycle:

prepared → published → shared → viewed
→ superseded → expired → accepted_for_conversion → archived

Ключевое отличие: появились состояния ожидания (awaiting_repricing, awaiting_revalidation) — отражают, что Tour Builder работает поверх operational truth (Offer/Quote), которая может устареть, и композиция должна явно ждать обновления, не публиковать stale данные.

Composition entities — расширение состава

В этом документе перечислены: TourDraft, TourDraftItem, TourProposal, ProposalVersion, ProposalArtifact.

Каноничный состав в overview/canonical-domain-spine.md дополнительно включает DraftVariant — альтернативный вариант элемента композиции, нужен для exploration вариантов в agency workflow и saga-coordinated swap при drift detection (см. reference/tour-builder-operational-model.md).

Identity / Tenancy / Access entities — расширение состава

В этом документе перечислены: Tenant, Workspace, RoleAssignment, CapabilityGrant, ApiClient, ApiCredential.

Каноничный состав в overview/canonical-domain-spine.md дополнительно включает ActorContext — текущий рабочий контекст identity. Один и тот же User может быть в разных actor-контекстах (внутренний оператор, сотрудник партнёра-агентства, customer success agent) с разным capability set. Без ActorContext capability-aware surfaces (см. reference/clients.md) не могут работать корректно.

Sub-states из Фазы 5 — расширения

Фаза 5 каноничной архитектуры зафиксировала ряд дополнительных понятий, которые опираются на эту модель и не противоречат ей:

Каноничный итог обновления

Этот документ остаётся как смысловой каркас (что есть Property, Offer, Quote, Booking и так далее, какие границы между ними). Детальные жизненные циклы и расширения составов — в специализированных документах фазы 5. При конфликте между этим документом и специализированным фазы 5 — истина в специализированном (single source of truth per domain, согласно development/documentation-governance.md).

Это обновление выполнено согласно правилу no-destruction: текст этого документа выше не правится; уточнение добавлено как explicit секция-обновление с явными ссылками на канонические источники.

1. Property Lifecycle

candidate -> mapped -> canonicalized -> enriched -> revised -> governed

2. Offer Lifecycle

computed -> surfaced -> compared -> quoted -> expired / revalidated / superseded

3. Quote Lifecycle

created -> active -> revalidated / stale -> expired / consumed

4. Booking Lifecycle

draft intent -> submitted -> pending revalidation -> pending supplier confirmation -> confirmed / failed -> amended / cancelled / completed

5. TourDraft / Proposal Lifecycle

draft -> iterated -> proposed -> versioned -> partially consumed / archived

6. Review Lifecycle

detected -> queued -> reviewed -> decided -> applied / rejected -> audited

Эти жизненные циклы потом нужно будет развернуть в отдельные специализированные документы, но уже здесь они должны быть названы как часть canonical domain thinking.

Что Нельзя Больше Путать В Других Документах

После фиксации этой модели следующие смешения должны считаться ошибкой:

  • Property и Offer
  • SupplierProperty и Property
  • CanonicalProduct и SupplierProduct
  • Offer и Quote
  • Quote и Booking
  • TourDraft и TourProposal
  • User identity и Actor context
  • Partner и Agency
  • supplier truth и platform canonical truth
  • cached preview и commit-ready state

Как Эта Модель Связана С Уже Переписанными Документами

Overview

Архитектурная основа платформы vitrip.store уже задаёт базовый канонический набор сущностей. Этот документ делает его жёстче и доменно точнее.

Business Services

Business Services — Сервисная декомпозиция платформы выводит сервисные контуры из этой модели. Без неё сервисная декомпозиция повисает в воздухе.

Database Schema

Database Schema — Каноническая модель хранения платформы должен трактоваться как persistent projection этой доменной модели, а не как её замена.

Storage

Storage Layer — Модель хранения и жизненный цикл данных раскрывает, как truth layers из этой модели живут физически и operationally.

API Contracts

API Contracts — Surface Contracts и правила внешнего взаимодействия должен опираться на resource families, выведенные из этой модели, а не из старого списка endpoint-ов.

Clients

Clients Layer — Клиентские поверхности и рабочие модели должен строить рабочие поверхности вокруг use cases этих сущностей, а не вокруг случайных UI-страниц.

Suppliers And Ingestion

Suppliers Layer — Поставщики, source boundaries и управление внешней реальностью и Ingestion Layer — Приём, нормализация, маппинг и governance отвечают за то, как supplier reality доходит до границ этой модели.

Что Должно Быть Перепроверено После Этого Документа

После фиксации центральной доменной модели следующий порядок должен быть таким:

  1. зафиксировать identity / tenancy / roles / access как отдельную доменную систему;
  2. зафиксировать offer / pricing / booking semantics;
  3. зафиксировать tour builder как домен композиции;
  4. зафиксировать data governance and matching;
  5. затем вернуться к дополнительной синхронизации API, storage, schema и client-facing semantics.

Текущий Практический Вывод

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

Теперь смысловой каркас должен быть таким:

  • Property и CanonicalProduct держат стабильную доменную основу;
  • SupplierProperty и SupplierProduct держат supplier reality;
  • Offer и Quote держат operational and commercial transition;
  • Booking держит transactional commitment;
  • TourDraft и TourProposal держат composition layer;
  • Tenant, Agency, Partner, User, ActorContext держат организационный и access-контекст;
  • ReviewCase, MergeDecision, FieldLineage и связанные сущности держат governance layer.

Именно от этой модели дальше должны зависеть API, storage, services, clients и будущие специализированные документы.

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