Что из задуманного можно сделать на стороне MAX, как подписывать титулы, как бот связывает участников одной перевозки и на каком стеке собирать MVP к заморозке 27 сентября. Каждый пункт сверен с документацией и OpenAPI-схемой MAX, постановлением № 931 и форматом ФНС; там, где можно, проверен руками.
Весь сценарий Т1 → Т4 собирается в MAX: личные диалоги с ботом, кнопки, ссылки-приглашения, подтверждённый номер телефона, геоточка, файлы и мини-приложение, которое узнаёт пользователя без логина и пароля.
Общего чата перевозки не будет. Бот не умеет создавать групповые чаты, а метод добавления в них участников MAX удаляет 30 сентября 2026, в день сдачи. Поэтому схема «звезда»: у каждого участника своя личка с ботом, у всех одна и та же «живая карточка», общая лента событий в мини-приложении.
Настоящая подпись через «Госключ». Бот присылает XML-титул, участник пересылает его официальному боту @goskey_bot, подписывает УНЭП или УКЭП и пересылает ответ обратно. XML этот бот принимает.
Подпись проверяем сами. OpenSSL с открытым модулем gost-engine сегодня проверил цепочку сертификатов УЦ «Госключа» на корневых сертификатах с goskey.ru («OK»); без модуля проверка падает. Пункт «без проверки подписи» из известных ограничений можно убрать.
Отправить документ «в Госключ» из нашего бота программно. Подпись по запросу компании — закрытая интеграция для организаций, в Bot API её нет. Это путь после хакатона.
API MAX переехал на platform-api2.max.ru с сертификатом Минцифры. Официальный SDK ходит туда по умолчанию. Без корневого сертификата Минцифры в контейнере бот не подключится: «platform-api2 не отвечает» из комментария в HAKATON-6 объясняется именно этим.
Стек из техплана верный по сути, но Node 20 снят с поддержки 30.04.2026. Берём Node 24 LTS и актуальные версии остального. React для MAX UI фиксируем строго на 19.2.8.
Что проверено руками сегодня. TLS обоих доменов API: platform-api2 отвечает, если доверять Russian Trusted Root CA. Цепочка сертификатов УНЭП «Госключа» проверена OpenSSL с пакетом libengine-gost-openssl. Официальные XSD титулов Т1–Т4 скачаны из документации Диадока и разобраны: у Т1 62 обязательных элемента, у Т2–Т4 по 6. Исходный код SDK @maxhub/max-bot-api 0.3.1 прочитан. Сайт nalog.gov.ru с нашего сервера отдаёт 403, поэтому XSD взяли у Диадока: это те же файлы ФНС.
Возможности, на которые опирается продукт, с методом, лимитами и выводом для нас. Источник по каждой строке — схема Bot API и страницы dev.max.ru из списка в конце.
| Возможность | Статус | Как в API и какие лимиты | Что это значит для нас |
|---|---|---|---|
| Написать участнику в личку | можно | POST /messages?user_id=…. Личный диалог адресуется по user_id, а не по chat_id (иначе 404 chat.not.found). До 2 сообщений в секунду в один диалог и 30 запросов в секунду всего. | Поиска человека по телефону в API нет: user_id мы узнаём, только когда он сам открыл бота. Поэтому каждого участника приводим по ссылке. |
| Групповой чат перевозки | нельзя | Метода создания чата нет. POST /chats/{chatId}/members ограничен с 09.09 и удаляется 30.09.2026. GET /chats убран в июне 2026. | «Звезда» вокруг бота, раздел «Как бот связывает участников». |
| Ссылка-приглашение | можно | https://max.ru/<бот>?start=… — до 128 символов, приходит в bot_started.payload. ?startapp=… — до 512 символов из A–Z a–z 0–9 _ -, приходит в start_param мини-приложения. | Одноразовые токены для водителя и получателя. В ссылке только случайный токен, никаких данных. |
| Подтверждённый номер | можно | Кнопка request_contact → вложение contact с vcf_info и hash; сверка: HMAC-SHA256 от vcf_info на токене бота. В мини-приложении WebApp.requestContact() → {phone, authDate, hash}. | Водитель делится номером, и бот сам находит его рейсы в данных учётной системы. |
| Геоточка погрузки | с оговоркой | Кнопка request_geo_location с quick: true → вложение location (широта, долгота). До 3 таких кнопок в ряду. В MAX Bridge геолокации нет. | В мобильном MAX работает; в web.max.ru и на десктопе — подтверждение адреса без точки. |
| «Живая карточка» | можно | PUT /messages?message_id=… меняет текст и кнопки. POST /answers?callback_id=… по нажатию меняет сообщение и/или показывает всплывающее уведомление. | У каждого участника одно сообщение на перевозку, бот обновляет его при каждом событии. |
| Отправить XML, PDF, QR | можно | POST /uploads?type=file|image → токен → POST /messages. Файл должен быть единственным вложением сообщения. Сразу после загрузки бывает attachment.not.ready, нужен повтор с паузой. Файл до 4 ГБ, картинка до 50 МБ. | Документ и кнопки уходят двумя разными сообщениями. |
| Принять файл, в том числе пересланный | можно | message_created. У пересланного message.link.type = "forward", есть link.sender и link.message.attachments[].payload.url. | Принимаем .sig от @goskey_bot и видим, из какого бота переслано. На живом боте проверить в первый день. |
| Мини-приложение без логина | можно | window.WebApp.initData; подпись HMAC-SHA256, ключ равен HMAC-SHA256("WebAppData", токен бота). Документация советует считать auth_date годным час. | На сервере проверяем initData и выдаём сессию; роли берём из своей базы. |
| Кнопка «Открыть карточку» | можно | Кнопка open_app: web_app — имя бота, payload до 512 символов. | Любое уведомление открывает нужную перевозку в мини-приложении. |
| Сканер QR | с оговоркой | WebApp.openCodeReader(fileSelect): камера или картинка из галереи. | На десктопе — ручной ввод кода. QR приглашения сканируется и обычной камерой телефона. |
| Поделиться приглашением | с оговоркой | WebApp.shareMaxContent({text, link}) или ссылка https://max.ru/:share?text=… (на десктопе пока нет). shareContent работает только на iOS и Android. | Диспетчер пересылает приглашение получателю прямо из MAX. |
| Яркость экрана под QR | можно | WebApp.requestScreenMaxBrightness() — максимальная яркость на 30 секунд. | Экран с кодом для получателя или инспектора. |
| Вебхук | с оговоркой | POST /subscriptions {url, secret, update_types}: только порт 443 и сертификат доверенного УЦ, ответ 200 за 30 секунд, до 10 повторов (60 с, дальше ×2,5). После 8 часов ошибок подписка снимается сама. Подписки копятся, старые надо удалять. Long polling одновременно с вебхуком не работает. | Отвечаем 200 сразу после записи в inbox. Воркер раз в 10 минут проверяет подписку и восстанавливает её. |
| Адрес API | с оговоркой | С 19.07.2026 — platform-api2.max.ru, сертификат от Russian Trusted Root CA (Минцифры). Старый platform-api.max.ru пока отвечает. | Корневой сертификат кладём в образ и включаем через NODE_EXTRA_CA_CERTS. |
| Уведомления по инициативе бота | с оговоркой | Правила платформы (ред. 11.06.2026) называют их «сервисными сообщениями», а п. 1.5 Требований разрешает слать их через API только по договору с MAX. | На хакатоне бот организаторов, это не мешает. Для пилота уточнить у MAX, покрывает ли их лицензионный договор. |
| Цифровой ID | нельзя | Только для верифицированных юрлиц и ИП; сценарии возраста и льготных статусов. | Не используем. |
| Подпись через «Госключ» | с оговоркой | Руками через @goskey_bot: PDF, TXT, XML, PNG, JPEG, TIFF; до 20 файлов и 100 МБ за раз. Нужны подтверждённая учётная запись Госуслуг и приложение «Госключ». Программного запроса подписи в Bot API нет. | Следующий раздел. |
Юридическая рамка — пункт 3 Правил направления ЭТрН в ГИС ЭПД, утверждённых постановлением Правительства № 931 от 21.05.2022. Там прямо сказано, чьей подписью закрывается каждый файл. Для нас важны две вещи: УНЭП «Госключа» допустима на всех четырёх обязательных титулах, а подпись водителя дополнительная и не заменяет подпись перевозчика.
| Титул и файл ФНС | Кто обязан подписать | Чем | Что можно добавить | Как в MVP |
|---|---|---|---|---|
Т1ON_TRNACLGROT | Грузоотправитель: уполномоченное лицо или тот, кто грузит | УКЭП или УНЭП; сотруднику нужна МЧД | — | Диспетчер: УНЭП через @goskey_bot живое или демо-подпись. Номер МЧД — поле в XML, реестр ФНС не проверяем модель |
Т2ON_TRNACLPPRIN | Перевозчик | УКЭП или УНЭП | Водитель после сверки груза: ПЭП или УНЭП, «при условии последующего подписания» перевозчиком | Водитель: ПЭП в MAX, по желанию УНЭП «Госключа». Перевозчик: демо-подпись в эмуляторе модель |
Т3ON_TRNACLGRPO | Грузополучатель: уполномоченное лицо | УКЭП или УНЭП; сотруднику нужна МЧД | Приёмщик может дополнительно подтвердить приёмку своей УНЭП | Получатель: УНЭП через @goskey_bot живое или демо-подпись |
Т4ON_TRNACLPVYN | Перевозчик | УКЭП или УНЭП | Водитель: ПЭП или УНЭП | Как Т2 |
Титулы сцеплены подписями. В XSD у Т2 обязательный атрибут ИдИнфГО/@ЭП — это подпись Т1; у Т3 ИдИнфПрвПрием/@ЭП — подпись Т2; у Т4 ИдИнфГП/@ЭП — подпись Т3. Поэтому эмулятор оператора хранит сами подписи, а не флаг «подписан», и следующий титул собирается из подписи предыдущего. Формат — приказ ФНС от 09.12.2021 № ЕД-7-26/1065@, версия 5.01, кодировка windows-1251; имя файла Т1, например, ON_TRNACLGROT_A_E_O_W_ГГГГММДД_GUID.xml.
https://max.ru/goskey_bot и инструкция в три шага.payload.url и проверяет его командой openssl cms -verify -engine gost -binary -inform DER -in Т.xml.sig -content Т.xml -CAfile goskey-roots.pem -purpose any. Из сертификата достаёт ФИО и СНИЛС и сверяет ФИО с полем «Подписант» в XML.ЭП следующего титула.user_id, подтверждённый телефон, время, геоточка, хеш титула, callback_id и mid сообщения. Силу ПЭП даёт соглашение участников с оператором: в MVP это модель, в пилоте договор.Проверить руками в первые сутки (подойдёт HAKATON-9, как только у кого-то заработает «Госключ»):
1) переслать тестовый XML в @goskey_bot и посмотреть, что вернулось: есть ли .sig, как назван файл; прогнать команду openssl выше. 2) Переслать ответ нашему боту и посмотреть сырое обновление: есть ли link.type = "forward", link.sender и вложения. 3) Загрузить анимированный GIF через /uploads?type=image и проверить, анимируется ли он в чате: это нужно для настоящего QR на пилоте.
participant хранит, кто в какой роли, с какого момента и как пришёл: по ссылке, по номеру или по QR. Права на каждое действие проверяются по роли пользователя из callback.user, а не по тому, что прислала кнопка.mid карточки для каждого участника и при любом событии перерисовывает их все через PUT /messages. Все видят одно состояние, чат не засоряется.?start=trip_<токен> или QR на воротах, который он сканирует камерой. Бот просит поделиться номером и сверяет его с водителем из учётной системы. Получателю — ссылка ?startapp=rcv_<токен> от диспетчера или QR на экране водителя при выгрузке, с максимальной яркостью.payload кнопки лежит номер версии перевозки. Если состояние уже изменилось, бот отвечает всплывающим уведомлением и перерисовывает карточку. Повторы вебхука отсекаются по callback_id и mid.| Шаг | Кто действует | Что видит и нажимает | Что получают остальные | Под капотом |
|---|---|---|---|---|
| 1 | Учётная система | — | Диспетчер: карточка «Черновик Т1» с проверками реквизитов и кнопками «Подписать Т1», «Исправить», «Нужна ли накладная?» | вебхук erp-emu → app; проверки ИНН, массы, адресов, срока МЧД |
| 2 | Диспетчер | Подписывает Т1 («Госключ» или демо), жмёт «Пригласить водителя» и получает ссылку и QR | — | XML Т1 по XSD → эмулятор оператора |
| 3 | Водитель | Открывает ссылку, жмёт «Поделиться номером» | Диспетчер: «Водитель Петров в боте» | bot_started.payload; contact.hash сверяется HMAC |
| 4 | Водитель | «Я на погрузке» → сверка груза → «Принял без замечаний» или «Есть замечания» + геоточка | Диспетчер: «Груз принят водителем» | ПЭП водителя; request_geo_location с quick |
| 5 | Перевозчик (модель) | — | Водитель: QR и «Можно ехать»; диспетчер: «УИД получен, машину можно выпускать» | эмулятор подписывает Т2 демо-УЦ, выдаёт УИД и демо-QR |
| 6 | Все | Реплики через бота | Лента перевозки | таймеры: нет QR 20 минут, простой |
| 7 | Водитель | «На выгрузке» → «Показать код получателю» | Получатель открывает мини-приложение по QR или ссылке | ?startapp=rcv_…, requestScreenMaxBrightness() |
| 8 | Получатель | «Принято без расхождений» или «Есть расхождения» с фото → кто подписывает (ФИО, должность, МЧД) → подпись Т3 | Диспетчер и водитель: «Т3 подписан» | XML Т3 → @goskey_bot → .sig → проверка ГОСТ |
| 9 | Водитель, перевозчик (модель) | «Груз сдан» (ПЭП) | Все: «Перевозка закрыта»; учётная система получает статус | Т4 → эмулятор; writeBack в учётку |
| Условие | Кому | Кнопка |
|---|---|---|
| Т1 не подписан за 2 часа до погрузки | Диспетчер отправителя | «Подписать сейчас» |
| Нет QR через 20 минут после приёма груза | Диспетчер и водитель | «Проверить статус у оператора» |
| Т3 не подписан 24 часа после выгрузки | Получатель, затем диспетчер | «Напомнить получателю» |
| Т4 не подписан 24 часа после Т3 | Перевозчик (модель), затем диспетчер | «Открыть перевозку» |
| МЧД диспетчера истекает через 5 дней | Диспетчер | «Обновить данные МЧД» |
В техплане бот и API — два сервиса. Им нужны одно и то же ядро и одна база, поэтому лучше один образ и два процесса с разными ролями. app принимает всё входящее: вебхук MAX, запросы мини-приложения, вебхуки учётной системы и эмулятора оператора. worker делает всё исходящее и отложенное: сообщения в MAX с ограничением скорости, таймеры, обмен с оператором. Тогда медленный ответ MAX или оператора никогда не задерживает ответ на вебхук, а схема на слайде остаётся простой.
Ядро не знает ни про MAX, ни про МойСклад, ни про конкретного оператора. Всё, что меняется при переносе на другой завод, регион или оператора, сидит за четырьмя интерфейсами:
interface ErpAdapter { // emulator | moysklad | 1c-odata
getShipment(ref: string): Promise<ErpShipment>
writeBack(ref: string, status: WaybillStatus): Promise<void>
}
interface EpdOperator { // emulator | diadoc | taxcom
submit(title: TitleFile, signatures: Cms[]): Promise<{ operatorDocId: string }>
status(operatorDocId: string): Promise<OperatorStatus> // sent | registered(УИД) | error(коды ГИС)
qr(operatorDocId: string): Promise<Gif>
}
interface SignatureProvider { // pep_max | goskey_relay | demo_ca | (пилот) operator_cloud
request(title: TitleFile, signer: Participant): Promise<SignRequest>
accept(evidence: Evidence): Promise<Signature> // проверка и данные подписанта
}
interface Messenger { // MAX; в тестах заглушка
upsertCard(userId: number, card: Card): Promise<void> // PUT /messages или новая карточка
notify(userId: number, text: string, buttons: Button[]): Promise<void>
}
callback_id, mid или bot_started:user:timestamp) и сразу отвечает 200. Обработка начинается тут же; упавшие строки подбирает периодический «подметальщик». Встроенный вебхук SDK так не умеет: он отвечает 200 до обработки, и при падении событие теряется.attachment.not.ready. Ответ на нажатие (POST /answers) отправляется сразу, без очереди.SELECT … FOR UPDATE по перевозке, проверка версии, запись событий, постановка сообщений в outbox.GET /subscriptions; если нашего адреса нет — POST /subscriptions, лишние подписки — DELETE. Если за рабочий час не пришло ни одного обновления, это тревога.app.post('/bot/webhook', async (req, reply) => {
if (!safeEqual(req.headers['x-max-bot-api-secret'], env.MAX_WEBHOOK_SECRET)) return reply.code(401).send()
const update = req.body as Update
const key = dedupeKey(update) // callback_id | message.body.mid | bot_started:user:ts
const fresh = await db.insert(inbox).values({ key, update }).onConflictDoNothing().returning()
reply.code(200).send('ok') // не позже 30 с, иначе MAX повторит
if (fresh.length) setImmediate(() => processInbox(key))
})
| Таблица | Что хранит |
|---|---|
org | ИНН, КПП, название; роли (отправитель, перевозчик, получатель); вид учётки и оператора; признак демо |
person | max_user_id (уникальный), подтверждённый телефон, имя из MAX, время согласия на обработку данных |
membership | человек × организация, роль (диспетчер, водитель, приёмщик, админ), МЧД: номер и срок |
shipment | ссылка на отгрузку в учётке, стороны, адреса, груз, машина, водитель, состояние, версия, УИД, идентификатор у оператора |
participant | перевозка × роль × человек (пусто, пока не вошёл), хеш токена приглашения, как пришёл |
title | Т1…Т8, ИдФайл, XML в windows-1251, хеши SHA-256 и по Стрибогу, ссылка на предыдущий титул |
signature | титул, роль подписанта, вид (ПЭП в MAX, УНЭП «Госключа», демо-УЦ), CMS целиком, ФИО и СНИЛС из сертификата, результат проверки, доказательства |
card | перевозка × человек → mid живой карточки и хеш последней отрисовки |
event | журнал: тип, кто (человек, учётка, оператор, таймер), данные. Из него лента в мини-приложении и метрики пилота |
inbox | обновления MAX с ключом дедупликации и статусом обработки |
pgboss.* | очереди outbox и таймеров; схему создаёт сам pg-boss |
X-Max-Bot-Api-Secret, сравнение через timingSafeEqual, тело не больше 1 МБ.initDataUnsafe ни на какие решения не влияет..env; в логах pino скрывает Authorization и токены; в репозитории .env.example.Боевой бот один, его выдали организаторы, а long polling с вебхуком одновременно не работает. Поэтому живой бот смотрит только на сервер, а разработчики работают локально с заглушкой MAX: записанные настоящие обновления в JSON проигрываются в /bot/webhook, исходящие вызовы пишутся в лог. Мини-приложение локально открывается в браузере с dev-входом: initData подписывается тестовым токеном.
Переключатель MAX_MODE=webhook | polling | off. У проверяющего по умолчанию off: всё поднимается, мини-приложение открывается в браузере. polling — если у него есть свой токен.
Сервер слабый и почти полный: 2 ядра, 7,8 ГБ памяти, свободно 7,6 ГБ диска (занято 93%). Образы на нём не собираем: их собирает CI (например, GitHub Actions с публикацией в GHCR) или Mac mini, а сервер делает docker compose pull && docker compose up -d. Логи docker ограничиваем (max-size: 10m), pg_dump раз в сутки, держим всё до 14.10.
/bot/webhook и /api → app, / → статика мини-приложения, сертификат Let's Encrypt (MAX такой принимает).node:24-bookworm-slim (gost-engine есть в Debian bookworm, в trixie его нет), postgres:18-alpine, nginx:alpine.postgres:18 поменялась раскладка: том монтируется в /var/lib/postgresql, а не в /var/lib/postgresql/data, как в скелете compose из техплана.FROM node:24-bookworm-slim AS base
RUN apt-get update \
&& apt-get install -y --no-install-recommends openssl libengine-gost-openssl libxml2-utils ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# корневой сертификат Минцифры: без него не открыть platform-api2.max.ru
COPY certs/russian_trusted_root_ca.pem /usr/local/share/ca-certificates/russian_trusted_root_ca.crt
RUN update-ca-certificates
ENV NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt
| Слой | Берём | Почему | Не берём |
|---|---|---|---|
| Среда | Node.js 24 LTS (24.21.0 от 07.09.2026) | Поддержка до 30.04.2028. SDK MAX требует Node ≥ 20.19, pg-boss 12 — ≥ 22.12 | Node 20 снят с поддержки 30.04.2026; Node 26 станет LTS только 28.10 |
| Язык | TypeScript 6.0; tsx 4 для разработки, esbuild 0.28 собирает бэкенд в один файл для образа | Сборка бэкенда занимает секунды, сборка образа укладывается в 5 минут | TypeScript 7 (нативный) — можно для tsc --noEmit, но инструменты ещё догоняют |
| HTTP | Fastify 5.12, zod 4.6, pino 10 | Быстрый, схемы на zod, JSON-логи | NestJS — тяжёлый для пяти дней |
| MAX | @maxhub/max-bot-api 0.3.1 (официальный, MIT) | Типы, клавиатуры, загрузки; по умолчанию ходит на platform-api2 | Его встроенный вебхук: он отвечает 200 до обработки — делаем свой маршрут с inbox |
| База | PostgreSQL 18.6, Drizzle ORM 0.45, drizzle-kit 0.31 | uuidv7() из коробки, SQL-миграции лежат в репозитории | Prisma — лишний шаг генерации клиента при сборке образа |
| Очереди и таймеры | pg-boss 12.33 | Повторы, отложенные задания, singletonKey — на той же базе | Redis и BullMQ — лишний сервис |
| Мини-приложение | React 19.2.8 строго, @maxhub/max-ui 0.5.0, Vite 8.3, TanStack Query 5; MAX Bridge скриптом st.max.ru/js/max-web-app.js | MAX UI 0.5.0 требует ровно react 19.2.8 в peerDependencies, с 19.3 npm install упадёт. TanStack Query обновляет карточку опросом раз в 3–5 секунд | Next.js — не нужен, это одностраничное приложение |
| Документы | fast-xml-parser 5 и iconv-lite 0.7 (windows-1251); xmllint и официальные XSD; pdfmake 0.3 со шрифтом с кириллицей под OFL; qrcode 1.5, gifenc 1.0 для анимированного демо-QR | Формат ФНС и проверка по официальной схеме, а не «похожий XML» | — |
| Криптография | OpenSSL 3 + libengine-gost-openssl из Debian, вызов через child_process | Проверка CMS «Госключа» и демо-подпись по ГОСТ | КриптоПро — проприетарный, закрытые библиотеки использовать нельзя |
| Тесты | vitest 5 | Машина состояний, проверки ИНН и XSD, HMAC initData и контакта, проверка CMS на тестовых файлах — без MAX | — |
| Сборка и запуск | npm workspaces, один package-lock.json; Docker Compose | Одна команда запуска, зависимости с точными версиями | — |
apps/app вебхук MAX, API мини-приложения, ядро, адаптеры (процессы app и worker)
apps/web мини-приложение: React + MAX UI
apps/erp-emu модель учётной системы: отгрузки, вебхук, /demo
apps/epd-emu модель оператора и ГИС: титулы, УИД, QR, ручки сбоев
packages/domain типы, машина состояний, правила «чей ход» — без ввода-вывода
packages/etrn сборка XML Т1–Т4, XSD ФНС, PDF, обёртки openssl
platform-api.max.ru → platform-api2.max.ru и сертификат Минцифры в образе. Хост не «не отвечает», просто без Russian Trusted Root CA не проходит проверка TLS. Поправить комментарий в HAKATON-6, README и CLAUDE.md.?start= несёт до 128 символов, а не 512. 512 — это ?startapp= для мини-приложения.ЭП): в модель данных добавить таблицу signature с CMS целиком.postgres:18: том в /var/lib/postgresql./demo для новой отгрузкиПредложение, как разложить модули по людям; календарь и синки — в HAKATON-15.
/demo (24.09). XML Т1–Т4 по XSD и демо-УЦ (25.09). Outbox, таймеры, обратная запись в учётку (26.09). Прогон на чистом клоне и замер сборки (27.09)./start, сессия по initData, сертификат Минцифры (22.09). Карточка диспетчера, приглашения, request_contact (23.09). Водитель: погрузка, геоточка, ПЭП, QR (24.09). Мост с «Госключом» (25.09, не больше дня). Мини-приложение: список, карточка, лента, получатель (26.09). Запасные пути для web (27.09).