API Contracts — Surface Contracts и правила внешнего взаимодействия
Версия: 2.0
Дата: 23.04.2026
Статус: Готов к обсуждению
Назначение документа
Этот документ фиксирует не просто набор REST endpoints и не попытку заранее заморозить OpenAPI-файл для всей платформы. Его задача — определить, как промышленная платформа должна мыслить свои внешние и внутренние API-контракты, какие surface-ы у неё реально существуют, какие типы запросов они обслуживают, где проходит граница между стабильным контрактом и внутренней доменной реализацией, а также какие правила обязательны для поиска, quote, бронирования, tour builder, identity и governance-сценариев.
Иными словами, этот документ отвечает на вопрос не "как красиво оформить OpenAPI", а "какие контрактные обязательства у платформы вообще есть перед разными типами потребителей, чтобы система оставалась масштабируемой, проверяемой и пригодной для реального промышленного роста".
Опорные документы
- Архитектурная основа платформы vitrip.store
- Domain Model — Центральная доменная модель платформы
- Tenancy And Identity — Субъекты платформы, изоляция и модель доступа
- Offer Pricing Booking Semantics — Семантика предложения, цены и бронирования
- Commercial Model — Коммерческая модель, цена, settlement и канальные условия
- Partner Finance And Clearing — Балансы, лимиты, взаиморасчёты и финансовая дисциплина партнёров
- Post-Booking Lifecycle — Изменения, отмены, инциденты и сопровождение после продажи
- Tenant Configuration And Enablement — Тенантная настройка, policy и ввод в эксплуатацию
- API Metering And Usage Governance — Учёт потребления, квоты и дисциплина использования
- Offer Integrity And Publication Control — Целостность предложения и правила публикации
- Tour Builder Domain — Домен композиции, draft/proposal lifecycle и пакетного продукта
- Data Governance And Matching — Provenance, merge policy и human-in-the-loop контроль
- Business Services — Сервисная декомпозиция платформы
- Database Schema — Каноническая модель хранения платформы
- Storage Layer — Модель хранения и жизненный цикл данных
- Ingestion Layer — Приём, нормализация, маппинг и governance
- Главные выводы и проблемные зоны платформы
Что Второй Несущий Круг Требует От API Contracts
После появления второго круга документов api-contracts.md уже нельзя считать просто “правильным общим документом про surface-ы”.
Теперь контрактный слой обязан явно удерживать следующие требования:
- Domain Model — Центральная доменная модель платформы: API не может путать canonical entities, supplier-derived state, operational offers, quotes, bookings, composition objects и governance entities.
- Tenancy And Identity — Субъекты платформы, изоляция и модель доступа: любой серьёзный contract surface должен быть subject-aware, tenant-aware, workspace-aware и capability-aware.
- Offer Pricing Booking Semantics — Семантика предложения, цены и бронирования: API обязан различать
Offer,QuoteиBookingкак три разные контрактные реальности, а не как разные представления одного и того же объекта. - Commercial Model — Коммерческая модель, цена, settlement и канальные условия: контрактный слой обязан честно различать indicative price, quoted promise, policy trace, repricing semantics и settlement-relevant downstream facts.
- Partner Finance And Clearing — Балансы, лимиты, взаиморасчёты и финансовая дисциплина партнёров: контрактный слой обязан уметь честно отражать partner-side financial admissibility, blocked sales conditions и clearing-sensitive failures.
- Post-Booking Lifecycle — Изменения, отмены, инциденты и сопровождение после продажи: API должен различать booking creation и post-booking case reality, а не скрывать modifications and cancellations inside ad hoc support flows.
- Tenant Configuration And Enablement — Тенантная настройка, policy и ввод в эксплуатацию: surface contracts должны быть не просто subject-aware, но и tenant-policy-aware.
- API Metering And Usage Governance — Учёт потребления, квоты и дисциплина использования: внешние контракты должны включать честную usage and quota semantics.
- Offer Integrity And Publication Control — Целостность предложения и правила публикации: API не должен обещать quoteability or publication там, где offer ещё не прошёл integrity threshold.
- Tour Builder Domain — Домен композиции, draft/proposal lifecycle и пакетного продукта: surface для Tour Builder обязан различать draft, proposal, version и artifact publication.
- Data Governance And Matching — Provenance, merge policy и human-in-the-loop контроль: governance и review-сценарии нельзя оставлять как внутренние “неформальные экраны”, если платформа реально хочет быть explainable и operationally controllable.
- Storage Layer — Модель хранения и жизненный цикл данных: контрактный слой обязан быть честным относительно freshness, revalidation, retention-significant state и asynchronous completion semantics.
Практический вывод:
API contracts должны описывать не только surface shape, но и честные контрактные обещания относительно истины, видимости, публикации, revalidation и завершённости действия.
Что Исправляет Новый Подход
Старый вариант документа исходил из трёх неверных посылок.
Во-первых, он слишком рано объявлял, что у платформы есть единая финальная OpenAPI 3.0-спецификация для всех сценариев сразу. Для реальной платформы это опасно: на раннем этапе получается не контрактная дисциплина, а фиксация случайного чернового набора endpoint-ов.
Во-вторых, старый документ описывал мир как hotel search -> room availability -> pricing -> booking, то есть вокруг hotelId и roomTypeId. После переосмысления платформы этого уже недостаточно. Внешние контракты должны опираться на offer, quote, booking, tour draft, partner scope, agency scope, identity, commercial context.
В-третьих, старый текст смешивал разные surface-ы как будто они обязаны жить под одним и тем же контрактным лицом. Но internal operations, agency workbench, partner API, client-facing API и service-to-service взаимодействия имеют разную степень стабильности, разный ритм эволюции и разные требования к безопасности, versioning и совместимости.
Новый документ исправляет это и переводит API в правильный порядок:
- Сначала определяется surface и его контрактная роль.
- Затем определяется доменная ответственность этого surface.
- Только потом описываются ресурсы, сценарии, versioning и формат OpenAPI/AsyncAPI/внутренних IDL.
Что Такое API Contracts В Контексте Платформы
В контексте vitiana-api-platform API contracts — это совокупность формальных обязательств платформы перед любым внешним или внутренним потребителем:
- какие операции доступны;
- на каких сущностях они работают;
- какие поля считаются обязательными и стабильными;
- какие данные являются окончательными, а какие предварительными;
- какие состояния допустимы;
- какие ошибки являются бизнес-ошибками, а какие инфраструктурными;
- как обеспечиваются idempotency, traceability, access control и revalidation.
Контракт здесь не равен конкретному формату сериализации. Один и тот же контрактный смысл может быть выражен через:
- REST + JSON;
- webhook / event delivery;
- внутренний gRPC / Protobuf;
- batch export;
- async command / event pattern.
Важно не название технологии, а сохранение одного и того же контрактного смысла и одинаковых доменных гарантий.
Главный Контрактный Принцип
Платформа не должна обещать наружу то, что она ещё не способна гарантировать доменно.
Из этого следуют жёсткие выводы:
- нельзя публиковать наружу API, будто цена окончательна, если для неё ещё нужна supplier revalidation;
- нельзя выдавать hotel-level сущность как конечный transactional object, если бронируется на самом деле
offer; - нельзя путать content read API с booking API;
- нельзя смешивать internal mutation surfaces и partner integration surfaces;
- нельзя делать API versioning просто по вкусу команды, без фиксации contract stability policy.
Surface Map Платформы
В рамках текущей логики платформы нужно различать пять основных contract surfaces.
1. Internal Operational Surface
Это внутренний surface для операторов, контент-редакторов, governance-команд, support, finance, ручного review и внутренних административных инструментов.
Для него характерно:
- более богатая и техническая модель данных;
- возможность видеть lineage, source precedence, review state, anomaly flags;
- наличие mutation-операций, которых не должно быть во внешних API;
- более быстрый темп изменения контрактов;
- сильная зависимость от внутренних доменных процессов.
Это важный surface, но его нельзя считать образцом для внешнего Partner API. Internal surface может быть богаче, менее дружелюбным и более "операционным".
2. Agency Working Surface
Это рабочий surface для турагентств, агентских кабинетов и внутренних/внешних пользователей, которые собирают предложения, формируют quote, создают и сопровождают booking, работают с клиентом, ведут тур и историю изменений.
Для него характерно:
- работа с поиском, предложениями, quote и бронированиями;
- обязательная связь с identity / tenancy / commercial context;
- потребность в explainable response-ах, пригодных для работы людей;
- наличие draft/stateful сценариев;
- требования к auditability и доступу по scope.
Этот surface ближе всего к реальной ежедневной работе платформы. Он не должен быть упрощён до public search API.
3. Partner API Surface
Это внешний стабильный B2B surface для интеграций партнёров, агентств, white-label каналов, реселлеров и потенциальных downstream systems.
Для него характерно:
- более узкая и стабильная контрактная модель;
- жёсткий versioning и backward-compatibility policy;
- чёткие auth scopes, quotas, environment separation;
- ограниченный доступ к внутренним полям и процессам;
- сильная ориентация на predictable machine integration.
Partner API должен быть уже и строже, чем internal/agency surfaces. Это не "копия внутреннего API наружу".
4. B2C / Client-Facing Surface
Это surface для клиентских витрин, публичного сайта, мобильных приложений, white-label витрин, customer-facing pages.
Для него характерно:
- high-volume read-heavy traffic;
- сильная зависимость от latency и caching policy;
- минимизация внутренних деталей;
- акцент на discoverability, clarity и безопасное представление предварительных данных;
- часто отдельная presentation-oriented агрегация поверх доменного ядра.
Этот surface нельзя заставлять жить по тем же payload-ам, что internal operator UI или partner integration.
5. Service-to-Service Surface
Это внутренние технические контракты между доменными сервисными контурами.
Для него характерно:
- высокая связность с внутренней доменной моделью;
- возможность richer event/context payload-ов;
- другие требования к эволюции;
- акцент на reliability, idempotency, replayability и observability.
Этот surface не должен проектироваться как будто он сразу является public contract.
Surface-First, Not Endpoint-First
API документ должен строиться не от списка endpoint-ов, а от набора surface-ов и сценариев. Правильная последовательность такая:
- Определить тип потребителя.
- Определить, какой surface ему нужен.
- Зафиксировать доменные use cases этого surface.
- Зафиксировать разрешённые ресурсы и операции.
- Только потом описывать URI, JSON-schema, pagination и headers.
Это особенно важно для платформы, где один и тот же Offer Service может кормить:
- internal operations;
- agency UI;
- partner integrations;
- client-facing storefront;
- downstream async processing.
Сервис может быть общий. Контрактный surface — нет.
Канонические Ресурсные Семейства
На текущем этапе платформы API-контракты должны группироваться вокруг следующих ресурсных семейств.
1. Search Context
Это не просто find hotels. Это контракт на формирование search intent и получение релевантного набора candidate results.
Search contract должен уметь выражать:
- географический или destination context;
- временной интервал;
- occupancy;
- channel / tenant / user context;
- языковую и валютную локализацию;
- фильтры и сортировку;
- tracing search request;
- связь результата с последующим quote path.
Search результат не должен выдавать себя за финальное transactional commitment.
2. Property Content
Это read-oriented контракты для канонического контента объекта размещения или иного travel product-а.
Сюда входят:
- property summary;
- property detailed content;
- media;
- amenities;
- location and geography;
- policies;
- content localization.
Property content — это не booking object и не price commitment.
3. Offer
Это центральное ресурсное семейство платформы. Внешний API должен постепенно смещаться к offer-centric модели.
Offer contract должен выражать:
- какой supplier/product basis за ним стоит;
- на какие даты и occupancy он релевантен;
- какие условия включены;
- какая price view показывается текущему actor-у;
- какая freshness у offer;
- нужна ли revalidation;
- какие ограничения и policy attached;
- можно ли из него переходить к quote или booking.
Offer не равен property, room type или просто "цена от".
4. Quote
Quote — это особое ресурсное семейство между offer discovery и booking commitment.
Quote contract нужен там, где платформа обязана:
- зафиксировать конкретный коммерческий и продуктовый срез;
- выполнить расчёт цены под tenant/channel/user;
- отразить applied markups, commissions, fees, taxes, discounts;
- зафиксировать quote validity window;
- подготовить проверяемый переход к booking.
Если этот слой не выделен, booking API становится либо слишком хрупким, либо обманчиво простым.
5. Booking
Booking contract — это уже transactional surface, а не read model.
Он должен выражать:
- вход из quote или explicit booking intent;
- guest/traveler data;
- payer/commercial context;
- booking state machine;
- supplier confirmation state;
- cancellation / amendment rules;
- payment dependency;
- audit trail и trace identifiers.
Booking contract нельзя сводить к POST /bookings с набором hotel/room полей.
6. Tour Draft / Tour Proposal
Для tour builder платформе нужны stateful контракты отдельного класса.
Они должны позволять:
- создавать и изменять draft;
- добавлять продуктовые блоки;
- работать с вариантами и альтернативами;
- хранить manual decisions;
- связывать tour с offers/quotes/bookings;
- готовить proposal для клиента;
- генерировать publish/export artifacts без потери traceability.
7. Identity / Tenancy / Access
Это не техническая мелочь, а контрактное ядро.
Почти любой внешний surface должен учитывать:
- кто делает запрос;
- к какому tenant он относится;
- в каком channel/scope работает;
- какие actor capabilities ему доступны;
- какой коммерческий контекст применяется;
- какие объекты он вообще имеет право видеть и изменять.
8. Governance / Review
Эти контракты не должны быть публичными по умолчанию, но они обязательны для industrial platform.
Они нужны для:
- review cases;
- anomaly resolution;
- mapping decisions;
- conflict explanation;
- manual overrides;
- audit and reconciliation.
Типы Контрактов По Степени Стабильности
Не все API в платформе должны жить под одним compatibility regime.
Stable External Contracts
Это partner API и иные публично поддерживаемые интеграционные поверхности.
Для них обязательны:
- versioning;
- deprecation policy;
- additive-first evolution;
- documented compatibility window;
- formal changelog;
- sandbox/prod separation.
Managed Application Contracts
Это контракты для собственных UI-клиентов, agency surfaces и контролируемых first-party clients.
Для них допустима более быстрая эволюция, но при условиях:
- изменения синхронно отражаются в связанных документах;
- breaking changes проходят через release discipline;
- surface semantics не противоречат partner model;
- field meaning не меняется тихо.
Internal Service Contracts
Это внутренние сервисные и event contracts.
Для них допустима большая подвижность, но обязательны:
- strong observability;
- schema discipline;
- idempotency;
- replay safety;
- contract tests на критические потоки.
Основные Контрактные Принципы
1. Offer-Centric Over Hotel-Centric
Снаружи можно продолжать иметь property-oriented read APIs для discovery и content browsing. Но transactional и pricing-sensitive flows должны строиться вокруг offer и quote, а не вокруг hotelId и roomTypeId как якобы достаточного ключа.
2. Explicit Freshness
Любой контракт, связанный с availability, price, cancellation policy, booking feasibility или itinerary viability, должен явно показывать freshness и необходимость revalidation.
3. No Hidden Commercial Logic
Если цена зависит от tenant, partner, agency, markup policy, commission agreement, user scope или currency policy, контракт должен либо явно включать эту зависимость, либо жёстко фиксировать, какая price view возвращается.
3A. Quoted Promise Must Be Traceable
Если surface возвращает Quote, контракт обязан позволять понять:
- что именно считается quoted promise;
- какая commercial policy была применена;
- действует ли quote ещё сейчас;
- произошёл ли revalidation или repricing;
- может ли downstream consumer считать эту цену final visible promise или только intermediate working state.
4. Read Model And Commit Model Are Different
Search results, property pages, indicative offers и cached previews не должны маскироваться под commit-ready objects.
5. Actor And Scope Are Contractual
Auth недостаточно. Контракт должен учитывать actor type, tenant scope, role scope и commercial scope.
6. Publication State Must Be Honest
Контракт обязан различать:
- internal working object;
- externally visible object;
- proposal artifact;
- governance-cleared published state;
- draft or pending state, ещё не пригодный для внешнего обещания.
7. Errors Must Be Actionable
Ошибки должны быть пригодны не только для логов, но и для автоматической обработки и human recovery.
8. Contract Meaning Must Outlive Technology
REST today, gRPC tomorrow, webhooks later — но meaning offer_revalidation_required или booking_pending_supplier_confirmation не должен меняться от транспорта.
Search And Discovery Contracts
Search surface нужен как отдельный класс контрактов.
Что Он Должен Принимать
- destination context;
- travel dates;
- occupancy/travel party;
- filters;
- sorting;
- localization;
- actor/tenant/channel context;
- optional search strategy hints;
- pagination or cursor model.
Что Он Должен Возвращать
- список candidate results;
- summary content;
- indicative pricing or offer summary;
- filter facets;
- trace/search identifier;
- freshness hints;
- next action affordances.
Что Он Не Должен Обещать
- что любой result уже готов к booking;
- что price окончательная;
- что supplier availability точно жива без revalidation;
- что hotel entity сама по себе является transactional unit.
Offer And Quote Contracts
Это главный контрактный переход от "что найдено" к "что можно реально продавать и бронировать".
Offer Contract Должен Включать
offer_id;- ссылку на underlying product context;
- property/product summary;
- occupancy and date scope;
- currency and price view;
- policy summary;
- applied inclusions/exclusions;
- freshness timestamps;
- revalidation requirement;
- optional commercial labels;
- eligibility for quote/booking.
Quote Contract Должен Включать
quote_id;- source offer reference;
- quote creation time;
- quote validity window;
- actor/tenant/commercial context;
- workspace or ownership context, where applicable;
- final visible price breakdown;
- commercial policy reference or contract-safe policy descriptor;
- cancellation and change implications;
- assumptions and unresolved constraints;
- freshness / revalidation basis;
- repricing semantics or repricing-required signal;
- publication scope/readiness;
- next-step contract for booking submission.
Что Quote Contract Должен Явно Различать
- indicative price vs quoted price;
- quoted price vs booking-time confirmed price;
- quoted promise vs settlement-relevant downstream figures;
- revalidation-required vs repricing-required;
- internal monetary breakdown vs presentation-safe public view.
Практический Вывод
Для партнёров и agency surfaces цена не должна оформляться как "всегда бери hotelId и считай дальше сам". Платформа должна уметь выдавать более честный и более устойчивый transactional handoff через offer/quote.
Booking Contracts
Booking — это домен повышенной строгости.
Booking Contract Должен Строиться Вокруг
- booking intent;
- source quote or equivalent validated context;
- traveler data;
- payer data;
- contact data;
- commercial ownership;
- actor context and tenant/workspace ownership;
- supplier placement attempt;
- internal booking state;
- external supplier state;
- payment state, если применимо;
- settlement-aware follow-up, если surface имеет право это видеть;
- cancellation/amendment path.
Базовые Доменные Состояния Booking Surface
draftsubmittedpending_revalidationpending_supplier_confirmationconfirmedpartially_confirmedfailedcancel_requestedcancelledamendment_in_progresscompleted
Конкретная state machine ещё должна быть вынесена в отдельный документ второго слоя, но surface уже обязан исходить из того, что booking lifecycle сложнее, чем pending/confirmed/cancelled.
Критические Контрактные Правила Для Booking
- создание booking должно быть idempotent;
- должен существовать client-supplied idempotency key для create/confirm-like операций;
- booking response должен не скрывать pending-state;
- supplier booking identifier не может подменять platform booking identifier;
- cancellation и amendment — это отдельные управляемые операции, а не просто
DELETE; - history и audit identifiers должны быть доступны хотя бы внутренним и agency-oriented surface-ам.
- booking contract не должен делать вид, что quoted promise и settlement reality всегда совпадают без остатка.
Tour Builder Contracts
Tour builder нельзя описывать как набор случайных CRUD-операций над "турами".
Контрактный Смысл Tour Builder
Tour builder — это stateful composition surface, в котором:
- создаются draft-сценарии;
- собираются элементы маршрута;
- сопоставляются предложения и альтернативы;
- фиксируются ручные решения;
- формируется клиентский proposal;
- при необходимости отдельные части переходят в booking.
Что Должен Поддерживать Surface
- создание и чтение draft;
- patch/update draft blocks;
- variant handling;
- attaching offers/quotes;
- hotel/product replacement without loss of history;
- pricing recalculation;
- validation against itinerary rules;
- proposal versioning;
- export/publication actions;
- link to downstream booking artifacts.
Что Нельзя Делать
- сводить tour builder к одному
POST /tours; - хранить только "финальную PDF-программу";
- терять связь между draft decision и underlying offers;
- смешивать публичный клиентский proposal и внутренний рабочий draft как один и тот же объект.
Identity, Tenancy, Access And Commercial Context
API contracts платформы должны быть actor-aware по определению.
Контракт Обязан Учитывать
- user identity;
- actor type;
- tenant or agency ownership;
- partner integration identity;
- delegated access;
- role or capability scope;
- commercial profile;
- environment separation.
Практически Это Означает
- одинаковый запрос от разных actor-ов может иметь разный допустимый scope;
- одинаковый offer может вернуться с разным visible price view;
- одинаковый offer может перейти в разные quote contracts с разным breakdown visibility;
- одинаковый
quote_idне обязан быть видим или валиден вне своего tenant/workspace context; - часть mutation-операций доступна только internal/agency actors;
- часть полей должна быть скрыта на partner or client-facing surfaces;
- API key scope и user session scope не являются взаимозаменяемыми сущностями.
Commercial Context As Contract Surface Concern
После фиксации Commercial Model — Коммерческая модель, цена, settlement и канальные условия контрактный слой обязан признавать, что цена сама по себе является surface-sensitive сущностью.
Это Означает
- agency surface может получать richer price breakdown;
- partner API surface может получать contract-safe machine-readable monetary structure;
- B2C surface может получать только presentation-safe visible price;
- internal operational surface может видеть override source, policy trace и settlement preparation context.
Контракт при этом не обязан раскрывать всем один и тот же объём коммерческой информации, но он обязан честно фиксировать, какая именно price view возвращена.
Аутентификация И Авторизация
На уровне документов платформе нужно мыслить не "JWT или API key", а уровни subject authentication.
Возможные Классы Auth
- first-party user sessions;
- agency user access tokens;
- partner API keys;
- service-to-service credentials;
- webhook signing credentials;
- sandbox credentials.
Что Должно Быть Зафиксировано Для Каждого Класса
- кто является субъектом;
- какой surface доступен;
- какие scopes/capabilities доступны;
- какие rate limits применяются;
- какая rotation policy требуется;
- как происходит revocation;
- как разделяются sandbox и production.
Версионирование Контрактов
Версионирование должно идти не по внутренней структуре кода, а по public contract boundary.
Для External Partner API Обязательно
- явная major/minor version policy;
- additive changes как основной путь эволюции;
- documented deprecation window;
- дата отключения старых версий;
- release notes для интеграторов.
Для First-Party Application Surfaces
- допускается более подвижная эволюция;
- breaking changes допустимы только как управляемое изменение связанного приложения;
- всё равно нужна фиксация контрактного смысла и changelog хотя бы на уровне docs.
Для Internal Service Contracts
- допустимы schema migrations без public versioning facade;
- но критические event contracts должны иметь schema compatibility discipline.
Идемпотентность, Повторы И Безопасность Повторной Доставки
Для industrial platform это не факультативная деталь.
Контракты для create / submit / confirm / cancel / publish / dispatch-like операций должны учитывать:
- client retries;
- duplicate submissions;
- network timeouts;
- webhook redelivery;
- background job reprocessing;
- supplier-side partial response scenarios.
Обязательные Механизмы
- idempotency key для критических mutation endpoints;
- deduplication semantics;
- trace identifiers;
- retry-safe response model;
- distinction between
accepted,processing,completed,failed.
Ошибки И Отказы
Ошибки должны быть разделены по смыслу, а не только по HTTP status.
Минимальные Классы Ошибок
- validation errors;
- authentication/authorization errors;
- scope violations;
- resource state conflicts;
- revalidation required;
- supplier unavailable;
- commercial rule violation;
- rate limiting;
- transient infrastructure failure;
- asynchronous processing delay.
Error Contract Должен Давать
- machine-readable code;
- human-readable message;
- request/correlation id;
- optional field-level details;
- retry hint или явный запрет на retry;
- next action guidance, где это возможно.
Особенно важно отделять:
offer_not_foundотoffer_not_visible_for_scope;booking_conflictотbooking_revalidation_required;supplier_timeoutотplatform_processing_pending.
Пагинация, Фильтрация, Сортировка
Контрактная дисциплина здесь нужна так же, как в транзакционных flow.
Базовые Правила
- list endpoints не должны возвращать неограниченные выборки;
- pagination strategy должна быть согласованной внутри surface-а;
- для high-volume result sets предпочтителен cursor-based подход;
- filters должны быть explicit и documented;
- sort semantics должны быть стабильны внутри версии контракта.
Практический Вывод
Не нужно насильно стандартизировать весь мир под один page/pageSize, если search surface и governance review queue имеют разные operational characteristics. Но внутри каждого surface-а стратегия должна быть единообразной.
Локализация И Валюты
Контракты платформы должны быть готовы к мультиязычности и multi-currency работе, но без подмены доменной истины.
Для Локализации Нужно Различать
- source language;
- canonical language policy;
- requested presentation language;
- fallback behavior;
- localized content fields;
- non-localizable operational fields.
Для Валют Нужно Различать
- supplier/source currency;
- canonical settlement currency, где применимо;
- quote display currency;
- booking payment currency;
- conversion reference and timestamp.
Нельзя допускать ситуацию, где API возвращает цену "в EUR", но неясно, это supplier amount, converted display amount или уже tenant-specific commercial amount.
Что Commercial Model Требует От API Contracts
После фиксации коммерческого слоя api-contracts.md должен явно удерживать:
Quoteкак contract-grade commercial promise;repricingкак отдельную контрактную реальность, а не неявное изменение цены;- разные уровни видимости monetary breakdown для agency, partner, B2C и internal surfaces;
- различие между booking confirmation flow и downstream settlement-aware reporting or eventing;
- обязательную traceability applied commercial policy там, где это влияет на смысл returned price.
Webhooks И Async Delivery Contracts
Платформе почти наверняка понадобится не только request/response API.
Типовые События Для Внешних Или Полувнешних Surface-ов
- booking status changed;
- booking confirmation received;
- booking failed;
- quote expired;
- tour proposal published;
- reconciliation issue detected;
- governance review completed.
Для Webhook/Event Contracts Обязательны
- stable event type names;
- event identifiers;
- delivery timestamps;
- signature verification;
- retry/redelivery semantics;
- ordering assumptions или честное признание их отсутствия;
- versioning of payload schema.
Что Важно Для Publication And Governance Events
Если платформа публикует события вроде tour proposal published, governance review completed или booking status changed, контракт обязан быть честным относительно:
- является ли это окончательным published fact или промежуточным internal transition;
- какой actor/tenant/surface инициировал переход;
- требует ли следующий шаг дополнительной revalidation или manual review;
- может ли downstream consumer безопасно трактовать событие как final business fact.
OpenAPI, AsyncAPI И Внутренние IDL
Из этого документа не следует, что OpenAPI не нужен. Наоборот, он нужен, но как производный артефакт.
Правильный Порядок Такой
- Сначала surface contract model.
- Затем ресурсные семейства и доменные сценарии.
- Затем compatibility policy.
- Затем machine-readable specs:
- OpenAPI для REST surfaces;
- AsyncAPI для event/webhook contracts;
- protobuf/IDL для service-to-service contracts.
Что Это Меняет Практически
Новый api-contracts.md не пытается делать вид, что весь surface уже описан одной финальной YAML-спецификацией. Вместо этого он задаёт правила, по которым эти спецификации должны дальше рождаться и проверяться.
Минимальный Каркас Будущих Спецификаций
Когда платформа перейдёт к следующему уровню детализации, machine-readable спецификации нужно будет разворачивать как минимум по следующим наборам:
External Partner API
- search endpoints;
- property content endpoints;
- offer endpoints;
- quote endpoints;
- booking endpoints;
- webhook subscriptions/events;
- auth and key management surface.
Agency Working API
- search and offer workspace;
- quote operations;
- booking operations;
- tour draft/proposal operations;
- client/workspace context;
- operational history and audit-friendly reads.
Internal Operations API
- governance queues;
- mapping/review actions;
- anomaly cases;
- manual overrides;
- manual lock actions;
- reconciliation tools;
- support and finance-specific reads/actions.
Service-to-Service Contracts
- ingestion update events;
- canonical content publication events;
- offer refresh events;
- booking state events;
- governance decision events.
Что Должно Быть Перепроверено После Этого Документа
После фиксации нового подхода нужно пересмотреть и синхронизировать следующие документы:
- Clients Layer — Клиентские поверхности и рабочие модели
- Suppliers Layer — Поставщики, source boundaries и управление внешней реальностью
- Architecture Surfaces — Поверхности архитектуры и границы взаимодействия
- Domain Model — Центральная доменная модель платформы
- Tenancy And Identity — Субъекты платформы, изоляция и модель доступа
- Offer Pricing Booking Semantics — Семантика предложения, цены и бронирования
- Tour Builder Domain — Домен композиции, draft/proposal lifecycle и пакетного продукта
- Data Governance And Matching — Provenance, merge policy и human-in-the-loop контроль
- Storage Layer — Модель хранения и жизненный цикл данных
Роль Старых Черновиков
Старый вариант документа не нужно считать бесполезным. Он полезен как источник ранних идей о поиске, базовых endpoint-группах, auth-механизмах, pagination и shape response-ов. Но его нельзя больше считать актуальным архитектурным основанием, потому что он:
- преждевременно фиксировал OpenAPI как финальный слой;
- описывал hotel-centric контрактный мир;
- смешивал partner, user и internal semantics;
- слишком рано объявлял "один API для всех" как уже решённую проблему.
Старый текст сохранён в архивной версии:
Текущий Практический Вывод
Для vitiana-api-platform API больше нельзя описывать как простой список REST endpoints поверх отелей, комнат и бронирований. Платформе нужен surface-based, offer-centric, actor-aware и contract-disciplined подход.
Это означает:
- внешний API должен вырастать из доменной модели, а не заменять её;
- partner contracts должны быть уже и стабильнее внутренних;
- search/content, offer/quote и booking contracts должны быть разведены;
- quote и booking path нужно считать отдельным обязательным уровнем зрелости;
- будущие OpenAPI и AsyncAPI артефакты должны строиться уже на этой основе.
Уточнение под Фазы 4–7 (28.04.2026) — обновлённая Surface Map и связи с новыми доменами
После Фаз 4–7 каноничной архитектуры (24–27.04.2026) Surface Map платформы расширена и интегрирована с новыми доменами. Этот документ остаётся как базовый каркас контрактной дисциплины (surface-first, offer-centric, actor-aware), но детальные surface boundaries и интеграции с фазами 4–6 — в специализированных источниках.
Surface Map — обновление с 5 на 6 поверхностей
В этом документе зафиксировано 5 surfaces (Internal Operational, Agency Working, Partner API, B2C / Client-Facing, Service-to-Service). Каноничная архитектура в overview/layers.md (версия 3.0 от 25.04.2026) фиксирует 6 surfaces — добавлена Tour Builder Closed Surface как отдельный коммерческий контракт.
Каноничные 6 surface contracts (источник истины — layers.md):
| # | Surface | Тип контракта | Коммерческая модель |
|---|---|---|---|
| 1 | Internal Operational | внутренний — нет внешнего контракта | — |
| 2 | Agency Working | first-party — managed application | подписка + комиссия |
| 3 | Partner API | внешний stable contract с версионированием | dynamic pricing per tier (Free/Starter/Professional/Enterprise) |
| 4 | B2C Storefront | first-party — managed presentation | маржа платформы на туристических продуктах |
| 5 | Service-to-Service | внутренний между сервисами | — |
| 6 | Tour Builder Closed | специальный paid contract | отдельный paid tier (Professional+) |
Tour Builder Closed Surface был перечислен в этом документе как resource family (раздел «6. Tour Draft / Tour Proposal»), но в каноничной архитектуре он выделен как отдельный surface contract с собственной коммерческой моделью (не часть Partner API tier).
Соответствие с client surfaces (clients.md)
Согласно reference/clients.md (Фаза 7) и уточнению в overview/layers.md, существуют две ортогональные таксономии:
- Surface Contracts (этот документ + layers.md) — формально-контрактная сторона;
- Client Surfaces (clients.md) — продуктовая декомпозиция UI/SDK.
При проектировании контракта API использовать Surface Contracts; при проектировании UI/SDK packaging — Client Surfaces. Полное соответствие — в layers.md, секция «Уточнение под Фазу 7».
Каноничные ресурсные семейства — расширение под Фазы 4–6
В этом документе перечислены 8 ресурсных семейств (Search, Property, Offer, Quote, Booking, Tour Draft/Proposal, Identity/Tenancy, Governance/Review). После Фаз 4–6 добавились новые каноничные домены, требующие собственных contract families:
| Дополнительное ресурсное семейство | Каноничный источник | Phase |
|---|---|---|
| Payment (PaymentIntent, Refund, Chargeback, Settlement, PayoutBatch, PaymentMethod) | payment-domain.md | 4 |
| Notifications (NotificationTemplate, NotificationEvent, ConsentLog, Webhook) | notification-and-communication.md | 4 |
| Media & Content (MediaAsset, ContentBundle, ContentTranslation) | media-and-content.md | 4 |
| i18n (SupportedLanguage, SupportedCurrency, FxRateSnapshot) | internationalization-and-localization.md | 4 |
| Analytics (analytical projections, partner-facing dashboards) | analytics-and-bi.md | 4 |
| A/B Testing (Experiment, Variant, Assignment, Exposure, FeatureFlag) | ab-testing-platform.md | 4 |
| API as Product (Partner, PartnerApplication, ApiKey, Tier, Quota) | api-as-product.md | 4 |
| Search & Discovery (SearchProjection, RankingPolicy, расширение Search context) | search-and-discovery.md | 4 |
| Booking State Machine (14 каноничных состояний, transitions) | booking-state-machine.md | 5 |
| Tour Builder Operational (CompositionRule, TourBookingTransaction saga, DriftEvent) | tour-builder-operational-model.md | 5 |
| Multi-Tenant Isolation (isolation_level, IsolationBoundaryCheck, CrossTenantAccess) | multi-tenant-isolation-strength.md | 5 |
| Compliance (DSR API, ConsentLog, BreachNotificationLog) | compliance-and-legal.md | 4 |
Каждое семейство имеет свои контрактные правила (versioning, visibility, rate limits) согласно tier модели в api-as-product.md.
Принцип OpenAPI-first для polyglot
Согласно открытому proposal development/proposal-openapi-first-polyglot-codegen.md:
- все sync API контракты — single source of truth в формате OpenAPI 3.1;
- все async API — AsyncAPI;
- code generation per language (oapi-codegen для Go, OpenAPI Generator для остальных);
- documentation portal через Redoc (public) + Swagger UI (sandbox).
Этот proposal — открытый вопрос на стадию 1 implementation baseline, но фиксирует направление развития контрактной дисциплины.
Связь с программным интерфейсом как продуктом
Согласно reference/api-as-product.md:
- Partner API Surface имеет 4 tier (Free / Starter / Professional / Enterprise);
- каждый tier определяет SLA, rate limits, isolation level, DR class, certification обязательства;
- partner lifecycle — sandbox → certification → production → deprecation;
- versioning — explicit version в URL, deprecation ≥ 6 месяцев notice;
- Tour Builder Closed Surface — доступен только Professional+ tier с отдельным paid доступом.
Связь с safety / compliance / security
- Compliance (compliance-and-legal.md) — каждый external surface имеет собственные регуляторные обязательства (GDPR DSR API, PSD2 SCA для платежей, EU TOMS VAT, Package Travel Directive для Tour Builder);
- Security architecture (security-architecture.md) — каноничная STRIDE threat model, IAM RBAC+ABAC, encryption at-rest/in-transit, secret lifecycle. Каждый surface имеет своё authentication level (Internal — Level 2 MFA, Partner Machine — signed requests, B2C — Level 1 baseline + Level 2 для payment);
- IsolationBoundaryCheck (multi-tenant-isolation-strength.md) — continuous automated check для всех contract surfaces, target 0 cross-tenant breaches за rolling 90 дней.
Каноничный итог уточнения
Этот документ остаётся как базовый каркас контрактной дисциплины платформы: surface-first thinking, offer-centric over hotel-centric, explicit freshness, no hidden commercial logic, contract-disciplined evolution. Расширения и реализация:
- 6 surfaces (не 5) + Tour Builder Closed как отдельный → layers.md;
- Client surfaces (продуктовая декомпозиция UI/SDK) → clients.md;
- 12 новых ресурсных семейств Фазы 4–6 → специализированные документы (см. таблицу выше);
- OpenAPI-first для polyglot → proposal-openapi-first-polyglot-codegen.md;
- API as Product tier model → api-as-product.md;
- Compliance/security обязательства per surface → compliance-and-legal.md, security-architecture.md;
- IsolationBoundaryCheck → multi-tenant-isolation-strength.md.
При конфликте с этим документом — истина в каноничном специализированном (правило single source of truth per domain).
Уточнение выполнено через no-destruction.
Связанная Документация
- Архитектурная основа платформы vitrip.store
- Domain Model — Центральная доменная модель платформы
- Tenancy And Identity — Субъекты платформы, изоляция и модель доступа
- Offer Pricing Booking Semantics — Семантика предложения, цены и бронирования
- Tour Builder Domain — Домен композиции, draft/proposal lifecycle и пакетного продукта
- Data Governance And Matching — Provenance, merge policy и human-in-the-loop контроль
- Business Services — Сервисная декомпозиция платформы
- Database Schema — Каноническая модель хранения платформы
- Storage Layer — Модель хранения и жизненный цикл данных
- Ingestion Layer — Приём, нормализация, маппинг и governance
- Главные выводы и проблемные зоны платформы
- api-contracts-old-2026-04-23.md