Актуальная документация (версия 2.4.0) · версионный адрес
Event Center — mobile contract v2 (wire mapping)
Обновлено: 09 Октябрь 2026
Версия: 2.4.0
Контрактные таблицы для мобильных клиентов и интеграторов Event Center / Communications Attention. Полная матрица маршрутизации не дублируется. Операционный cutover: runbook-mobile-contract-v2. Канон в репозитории ask: documentation/technical/event-center/runbook-mobile-contract-v2.md.
1. HTTP header X-ASK-EC-Contract vs outbound always dual
| Канал | Версия wire |
|---|---|
HTTP без заголовка / X-ASK-EC-Contract: 1 |
Contract 1: as-is ORM / legacy shape; unknown section → all |
HTTP с X-ASK-EC-Contract: 2 |
Contract 2: канон wire v2; секции только v2; unknown → 400 |
WebSocket (event_created / event_updated / event_removed / counters_updated) |
Всегда dual (канон v2 + migration aliases); не зависит от HTTP-заголовка |
GET /api/v1/event-center/sync/ |
Всегда dual, как WS |
Push data |
Всегда канон v2 (+ aliases); не зависит от HTTP-заголовка |
Клиент v2 обязан слать X-ASK-EC-Contract: 2 только после event_center_version ≥ 2 в bootstrap / /.well-known/ask-mobile. Feature detection — только bootstrap, не 404.
Web HTMX без заголовка → HTTP contract 1.
2. action_status: ORM vs wire; alias action_status_orm; SYSTEM_CLOSE_REASONS
ORM хранит: na | open | completed | expired | cancelled (значения auto_resolved в ORM нет).
SYSTEM_CLOSE_REASONS = {auto_resolved, ack_completed, reassigned, lost_relevance, expired_ack}.
| Условие | Wire action_status |
|---|---|
purpose ≠ action |
null / omit |
ORM open |
open (+ overdue из is_overdue) |
ORM cancelled |
cancelled |
ORM expired и reason ∈ SYSTEM_CLOSE_REASONS |
auto_resolved |
ORM expired иначе (hard deadline) |
expired |
ORM completed и reason ∈ SYSTEM_CLOSE_REASONS |
auto_resolved |
ORM completed иначе |
completed |
| Поверхность | Поле action_status |
Alias ORM |
|---|---|---|
| HTTP contract 1 | ORM (na для non-ACTION) |
dual-publish wire при необходимости |
| HTTP contract 2, WS, sync, push summary | wire | action_status_orm = сырое ORM-значение в том же envelope |
Просроченное, но ещё требуемое действие: wire open + overdue=true, не expired.
3. Inbox sections v2 + unknown_section envelope
Allowed section (contract 2): action | important | reminder | info | snoozed | all
Chat-секции EC (mentions, response_required, following, replies, action_required как имя, attention, unread, channels) при contract 2 → HTTP 400, не empty-all.
Единый 4xx envelope Inbox/execute (error и code — одно машинное значение):
{
"error": "unknown_section",
"code": "unknown_section",
"detail": "Unknown inbox section"
}
Contract 1: as-is INBOX_SECTIONS, unknown → all.
4. Counters / mobile_badge_total
Инвариант badge «Входящие» / app / push / Server Switcher:
mobile_badge_total = action_open
(action_open = action_required = attention_total в dual-publish EC counters.)
| Поле | Правило |
|---|---|
mobile_badge_total |
строго action_open; не суммировать important / reminder / info / chat / critical |
critical_open |
отдельный показатель; не входит в badge |
| Chat-поля в EC counters | stub-нули; mobile v2 читает «Разговоры» только из Communications Attention API |
Лёгкий summary: GET /api/v1/mobile/attention-summary/ — mobile_badge_total, action_open, critical_open, chat_unread, instance_id.
5. available_actions + execute URL; capability semantics
URL: POST /api/v1/event-center/events/{recipient_id}/actions/{action_key}/
Body: { "comment": "…" } (опционально; обязателен, если descriptor requires_comment).
| Правило | Значение |
|---|---|
| Descriptor | только зарегистрированный handler волны; иначе available_actions: [] |
| Terminal / non-ACTION | available_actions: [] |
Поле enabled |
в v2 нет; as-is actions[].enabled — migration alias |
| Не включать | open_entity, snooze |
style |
primary | danger | secondary |
Capability generic_approval_execute=true = протокол готов (descriptor + endpoint + идемпотентность). Не означает «все типы Матрицы уже in-inbox». Пустой список вне волны — ожидаемо; execute → 409 action_not_available.
6. Push data: as-is + purpose / severity / mobile_badge_total
As-is поля сохраняются: recipient_id, work_event_id, event_type, notification_id, entity, instance_id, account_id.
Добавляются: purpose, severity, mobile_badge_total (+ aliases attention_class, type; для ACTION на migration — type=work_event_action).
Push ≠ source of truth; после tap клиент актуализирует состояние с сервера. Delivery не мутирует Inbox.
Доставка (ops): при MOBILE_PUSH_ENABLED и credentials Gateway события уходят через transport mobile_push (очередь Celery push). В режиме cutover parallel path-A должен по-прежнему планировать MOBILE_PUSH для карточек Event Center (_ensure_policy_deliveries / dual-write) — иначе приложение не получит сигнал при «старой» ветке notify. Клиентский deep-link после tap: conversation / inbox (recipient_id + purpose) / task — см. ASK Mobile и mobile-api-overview.
7. RR wire: answered / canceled
Response Request остаётся в Communications (не EC ACTION). Wire-канон UC-M21:
| ORM | Wire канон | Migration alias |
|---|---|---|
open |
open |
— |
resolved |
answered |
resolved |
cancelled |
canceled |
cancelled |
expired |
expired |
— |
List/detail/resolve обязаны отдавать канон answered (не только ORM resolved). Expiry обновляет ту же строку; второй EC ACTION не создаётся.
8. Search: filters + snoozed breaking
GET /api/v1/event-center/search/
| Параметр | Смысл |
|---|---|
q |
title / summary / entity label |
purpose |
action\|important\|reminder\|info |
module |
entity_module OR domain |
status |
wire action_status (open\|completed\|auto_resolved\|cancelled\|expired), не inbox NEW/SEEN |
snoozed |
отдельно от status |
Breaking vs as-is («search never snoozed»):
snoozedопущен илиfalse— исключить активный snooze (как as-is)snoozed=true— толькоsnoozed_until > now()
Фильтр status=auto_resolved → ORM completed|expired + resolution_reason ∈ SYSTEM_CLOSE_REASONS.
9. Cutover waves: Pilot / Wave 2 / Wave 3
| Wave | event_type (taxonomy) |
|---|---|
| Pilot | absence.approval_required, contract.approval_assigned |
| Wave 2 | task.duedate_transfer, project.team_approval_required, project.baseline_approval_required, kb.approval_required, kb.page_acknowledge |
| Wave 3 | servicedesk.kpi_approval_required, workhour.approval_required, workhour.tech_approval_required, workhour.client_approval_required, согласование спецификации поставки (approval.action_required / trading), прочие ACTION с approve/reject в EventTypeDefinition.actions |
Порядок ops: migrate → reconcile counters → deploy → bootstrap event_center_version ≥ 2. Подробности: runbook.
Capabilities bootstrap
GET /api/v1/mobile/bootstrap/ и GET /.well-known/ask-mobile:
| Capability | Семантика |
|---|---|
semantic_purpose |
lowercase purpose / секции v2 |
available_actions |
descriptor shape в DTO |
semantic_counters |
action_open, mobile_badge_total, … |
communications_attention_separated |
«Разговоры» ≠ EC Inbox |
search |
search v2 filters |
generic_approval_execute |
generic execute protocol готов; волны handlers — отдельно |
При выключенном EC блок version/capabilities отсутствует (legacy Communications). Целевой инстанс с доработкой: event_center_version: 2.