| 1 | # ADR 0142: Intercom — открытый wire, подключаемые transport и опциональные мосты |
| 2 | |
| 3 | **Статус:** Accepted |
| 4 | **Дата:** 2026-05-24 |
| 5 | |
| 6 | ## Связанные ADR |
| 7 | |
| 8 | | ADR | Роль | |
| 9 | |-----|------| |
| 10 | | [0080](0080-intercom-naming-and-multi-party-channel-model.md) | Intercom как канал; слой A (IDE) vs B (внешний контур) | |
| 11 | | [0045](0045-agent-chat-persistence-event-log-and-projections.md) | Event log и проекции — модель событий на клиенте | |
| 12 | | [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) | Multi-client, REST/WS sketch, фазы transport; **этот ADR — канон wire и стратегия адаптеров** | |
| 13 | | [0128](0128-intercom-attachment-anchors-and-code-references.md) | `AttachmentAnchor` в wire — JSON, не prose | |
| 14 | | [0134](0134-intercom-message-prepare-pipeline-v1.md) | Prepare/commit до transport | |
| 15 | | [0133](0133-commander-cockpit-shared-attention-model-and-instrument-deck.md) | MCC подписывается на transport, не владеет store | |
| 16 | | [0143](0143-intercom-feed-participant-lens.md) | **Participant lens** (All/Humans/Agents/System) — проекция UI, не wire channel | |
| 17 | | [0144](0144-intercom-team-transport-cide-sync-and-reference-service.md) | **Accepted:** reference Intercom service, team id, CIDE FederatedSync, SSE | |
| 18 | |
| 19 | ### Вне ADR |
| 20 | |
| 21 | | Документ | Роль | |
| 22 | |----------|------| |
| 23 | | [intercom-ux-reference-slack-mattermost-v1.md](../design/intercom-ux-reference-slack-mattermost-v1.md) | UX-паттерны; слой B — мосты, не клон продукта | |
| 24 | | [iop-manifest-v1.md](../iop-manifest-v1.md) | IOP: transport не подменяет git/kb/workspace truth | |
| 25 | |
| 26 | ## Резюме |
| 27 | |
| 28 | **Принято:** |
| 29 | |
| 30 | 1. **Канон командного Intercom** — **открытая схема событий** (topics, messages, roles, structured attach), версионируемая в репозитории; не привязка к одному мессенджеру. |
| 31 | 2. **Transport** — **подключаемый** (`IntercomTransport` / sync-адаптер): reference implementation (Intercom service) **и** внешние адаптеры (Matrix, Mattermost, webhooks, …) — **опционально**, без обязанности «все в Element». |
| 32 | 3. **Много клиентов у людей** — норма: CIDE, Intercom Web, MCC, Element, корп. Slack/MM — через **мосты** и capability flags, а не через выбор единственного победителя. |
| 33 | 4. **Стандарты** — на **конверте** (при необходимости CloudEvents-подобная обёртка), **не** замена доменной семантики Intercom готовым чат-протоколом «как есть». |
| 34 | 5. **CIDE** остаётся богатым клиентом: Roslyn, reveal, MCP, prepare-pipeline — **вне** transport; на wire уходит уже подготовленный JSON. |
| 35 | |
| 36 | [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) остаётся **картой фаз и multi-client**; этот ADR фиксирует **политику открытого wire** и отношение к Matrix/MM без выбора вендора в v0. |
| 37 | |
| 38 | --- |
| 39 | |
| 40 | ## Контекст |
| 41 | |
| 42 | Участники команды сидят в **разных** мессенджерах; продукт Cascade **открытый** — сторонние реализации клиента и сервера допустимы. Варианты обсуждались: |
| 43 | |
| 44 | - полностью **свой** Intercom service ([0132](0132-intercom-federated-transport-and-multi-client-boundary.md) вариант A); |
| 45 | - **Matrix** (или иной готовый сервер) + тонкий C# wrapper; |
| 46 | - **свой открытый протокол** «на стандартах». |
| 47 | |
| 48 | Риск без решения: либо **дублирование** Slack + локальный чат + JIRA ([0132](0132-intercom-federated-transport-and-multi-client-boundary.md) § «Проблема»), либо **замена** Intercom чужой моделью (rooms без topics/attach/agent), либо **вечный Proposed** без канона wire. |
| 49 | |
| 50 | --- |
| 51 | |
| 52 | ## Решение |
| 53 | |
| 54 | ### 1. Три слоя (нормативно) |
| 55 | |
| 56 | ```mermaid |
| 57 | flowchart TB |
| 58 | subgraph clients["Клиенты"] |
| 59 | CIDE["CIDE (full)"] |
| 60 | Web["Intercom Web"] |
| 61 | MCC["MCC"] |
| 62 | Ext["Element / MM / … через мост"] |
| 63 | end |
| 64 | wire["Intercom wire\nоткрытая схема событий"] |
| 65 | subgraph transport["Pluggable transport"] |
| 66 | Ref["IntercomService (reference)"] |
| 67 | Local["LocalOnly / HybridSync"] |
| 68 | Matrix["MatrixBridge"] |
| 69 | MM["MattermostBridge"] |
| 70 | Hook["WebhookIngress"] |
| 71 | end |
| 72 | subgraph workspace["Workspace — не подменяется"] |
| 73 | Git["git · kb · hybrid index · Roslyn · MCP"] |
| 74 | end |
| 75 | clients --> wire |
| 76 | wire --> transport |
| 77 | transport -.->|не заменяет| workspace |
| 78 | ``` |
| 79 | |
| 80 | - **Wire** — *что* передаётся (события [0045](0045-agent-chat-persistence-event-log-and-projections.md), поля [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) §2, attach [0128](0128-intercom-attachment-anchors-and-code-references.md)). |
| 81 | - **Transport** — *как* доставляется и хранится (REST/WS, Matrix CS API, MM REST, …). |
| 82 | - **UX** — *как* рисуется в CIDE ([0123](0123-intercom-full-skia-surface-evolution.md)) — **не** часть wire. |
| 83 | |
| 84 | ### 2. Открытый wire (канон) |
| 85 | |
| 86 | | Артефакт | Назначение | |
| 87 | |----------|------------| |
| 88 | | **Схема событий** | JSON Schema / OpenAPI для message, topic, member; версия `schema_version` | |
| 89 | | **Reference types** | human \| agent \| system; `clientKind`: cide \| web \| mcc \| agent | |
| 90 | | **Attachment** | structured JSON ([0128](0128-intercom-attachment-anchors-and-code-references.md)); prose bracket — convenience на клиенте | |
| 91 | | **Экспорт/импорт** | CIDE local log ↔ wire ([0132](0132-intercom-federated-transport-and-multi-client-boundary.md) фаза 1) | |
| 92 | |
| 93 | Публикация: канон в [`wire/intercom-wire`](../../wire/intercom-wire/README.md) ([0146](0146-intercom-wire-canonical-protocol-package.md)); лицензия совместима с открытым продуктом ([0101](0101-licensing-and-commercialization-strategy.md) при выборе зависимостей мостов). |
| 94 | |
| 95 | **Обратная совместимость wire:** при изменении полей — явная версия схемы; потребители вне репо — отдельная политика, когда появятся. |
| 96 | |
| 97 | ### 3. Pluggable transport (контракт) |
| 98 | |
| 99 | Минимальный интерфейс (имена в коде — черновик): |
| 100 | |
| 101 | | Операция | Смысл | |
| 102 | |----------|--------| |
| 103 | | `AppendMessage` | idempotent по client message id | |
| 104 | | `SubscribeTopic` | live / poll cursor | |
| 105 | | `ListTopics` | для Web/MCC | |
| 106 | | `EnsureTopic` | spine key optional | |
| 107 | |
| 108 | Реализации (не взаимоисключающие в экосистеме): |
| 109 | |
| 110 | | Реализация | Роль | |
| 111 | |------------|------| |
| 112 | | **LocalOnly** | только [0045](0045-agent-chat-persistence-event-log-and-projections.md) в CIDE (сегодня) | |
| 113 | | **IntercomService** | reference server ([0132](0132-intercom-federated-transport-and-multi-client-boundary.md) фаза 2) | |
| 114 | | **HybridSync** | local + periodic push ([0132](0132-intercom-federated-transport-and-multi-client-boundary.md) вариант B) | |
| 115 | | **MatrixBridge** | room ↔ topic; custom event `io.cascade.intercom.message` | |
| 116 | | **MattermostBridge** | channel ↔ topic ([0132](0132-intercom-federated-transport-and-multi-client-boundary.md) фаза 5) | |
| 117 | | **WebhookIngress** | уведомления в Telegram/email без полноценного клиента | |
| 118 | |
| 119 | Выбор transport на deployment — **конфиг**, не compile-time ветка в CIDE. |
| 120 | |
| 121 | ### 4. Много мессенджеров — политика мостов |
| 122 | |
| 123 | | Принцип | Содержание | |
| 124 | |---------|------------| |
| 125 | | **Одна правда по задаче** | Канон — Intercom event log на выбранном primary transport; мост **не** создаёт второй независимый store в MCC | |
| 126 | | **Read-only в чужой UI допустим** | Уведомление + deep link в Web/CIDE | |
| 127 | | **Не цель** | Заставить всех перейти на один мессенджер | |
| 128 | | **Matrix / MM** | **Адаптеры**, не замена §2 wire; mapping документируется в ADR моста при внедрении | |
| 129 | |
| 130 | ### 5. Стандарты (конверт, не семантика) |
| 131 | |
| 132 | Допустимо: |
| 133 | |
| 134 | - **CloudEvents**-подобный envelope (`id`, `time`, `type`, `data` = Intercom payload) для логов, webhooks, observability; |
| 135 | - **JSON Schema** / OpenAPI 3 для HTTP reference server. |
| 136 | |
| 137 | Не требуется: |
| 138 | |
| 139 | - полная совместимость с Matrix event types как каноном; |
| 140 | - ActivityPub/XMPP как обязательный transport v0. |
| 141 | |
| 142 | ### 6. Связь с [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) |
| 143 | |
| 144 | | [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) | Этот ADR | |
| 145 | |------------------------------------------------------------------------|----------| |
| 146 | | Фазы 0–5, multi-client, REST sketch | **Статус Accepted** для wire-политики | |
| 147 | | «Intercom service MVP» | **Reference** transport, не единственный | |
| 148 | | «Mattermost bridge optional» | Пример **pluggable** адаптера | |
| 149 | | Proposed (объём transport) | Реализация фаз остаётся по [0132](0132-intercom-federated-transport-and-multi-client-boundary.md); wire — **Accepted** здесь | |
| 150 | |
| 151 | --- |
| 152 | |
| 153 | ## Последствия |
| 154 | |
| 155 | ### Положительные |
| 156 | |
| 157 | - Открытый продукт может поставлять **схему + reference server**, сообщество — **мосты** без форка CIDE. |
| 158 | - Matrix/MM снимают ops **доставки**, не заставляя отказаться от topics/attach/agent. |
| 159 | - CIDE, Web, MCC делят **один wire**, разные capability ([0132](0132-intercom-federated-transport-and-multi-client-boundary.md) §1.1). |
| 160 | |
| 161 | ### Отрицательные / риски |
| 162 | |
| 163 | - Поддержка нескольких transport + мостов — **тестовая матрица**. |
| 164 | - Конфликты sync (local vs remote) — политика merge ([0132](0132-intercom-federated-transport-and-multi-client-boundary.md)). |
| 165 | - Лицензии SDK мостов (AGPL Matrix libs и т.д.) — [0101](0101-licensing-and-commercialization-strategy.md). |
| 166 | |
| 167 | --- |
| 168 | |
| 169 | ## Не цели |
| 170 | |
| 171 | - Выбор Matrix vs Mattermost vs own server **в этом ADR** (отдельный ADR моста при пилоте). |
| 172 | - E2EE, federation, mobile-клиенты v0. |
| 173 | - Замена Skia Intercom UI чужим WebView ([0080](0080-intercom-naming-and-multi-party-channel-model.md) §5). |
| 174 | |
| 175 | --- |
| 176 | |
| 177 | ## Anti-patterns |
| 178 | |
| 179 | | Anti-pattern | Почему | |
| 180 | |--------------|--------| |
| 181 | | Два независимых message store (MCC + Intercom) | Ломает SA и attach | |
| 182 | | «Канон = Matrix room timeline» без custom mapping | Теряются topic/spine/attach | |
| 183 | | Prose `[M:…]` как единственный wire | [0128](0128-intercom-attachment-anchors-and-code-references.md), [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) §2 | |
| 184 | | Обязательный Element для PO/Lead | Нарушает паритет [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) §1.1 | |
| 185 | |
| 186 | --- |
| 187 | |
| 188 | ## Фазы (согласовано с [0132](0132-intercom-federated-transport-and-multi-client-boundary.md)) |
| 189 | |
| 190 | | Фаза | Содержание | Wire / transport | |
| 191 | |------|------------|------------------| |
| 192 | | **1** | OpenAPI/schema + CIDE export/import | **Accepted** (этот ADR) | |
| 193 | | **2** | Reference Intercom service | `IntercomService` transport | |
| 194 | | **3** | Intercom Web | тот же wire | |
| 195 | | **4** | MCC read/compose | подписка, не свой store | |
| 196 | | **5+** | Matrix / MM / webhook bridges | адаптеры поверх wire | |
| 197 | |
| 198 | --- |
| 199 | |
| 200 | ## Отклонённые альтернативы (кратко) |
| 201 | |
| 202 | | Альтернатива | Почему не канон | |
| 203 | |--------------|-----------------| |
| 204 | | Только Matrix как единственный backend | Привязка к room model и ops homeserver; mapping всё равно нужен | |
| 205 | | Только свой closed server | Открытый продукт без wire затрудняет мосты и сторонние клиенты | |
| 206 | | «Ничего не писать» — только embed Element | Две правды, слабый attach/reveal ([0080](0080-intercom-naming-and-multi-party-channel-model.md)) | |
| 207 | | Mesh/CRDT v0 | [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) вариант C — отложить | |
| 208 | |
| 209 | --- |
| 210 | |
| 211 | <a id="adr0142-history"></a> |
| 212 | |
| 213 | ## История |
| 214 | |
| 215 | | Дата | Изменение | |
| 216 | |------|-----------| |
| 217 | | 2026-05-24 | Accepted: открытый wire, pluggable transport, мосты опциональны; уточнение к [0132](0132-intercom-federated-transport-and-multi-client-boundary.md). | |
| 218 | |