Пришла пора расчехлить своего внутреннего спикера. Буду докладывать на митапе https://zeldev.ru/agentikus через неделю. Доклад на основе моих, так сказать, апрельских тезисов — полгода почти прошло, есть чем их дополнить.
В последний раз публично что-то докладывал году наверно в 2015м. Так что придётся готовиться: рисовать презентацию буду с камнями во рте аки Демосфен. Надеюсь, получится интересно.
На днях удалось как следует поработать над Ботопотамами.
Во-первых, добавил нового публичного бота: знакомьтесь, Валютопотам. Берет из Центробанка XML с курсами валют, парсит и показывает вам. Таких ботов много, но этот мой мулька в том, что этот, в интервал когда ЦБ обычно выкатывает новые курсы, стучится туда постоянно. И если подписаться — сразу отправит уведомление как курсы вышли.
Это может быть полезно для принятия решений, например, в турбизнесе. Срочно бежать оплачивать заявки сейчас, или отложить на завтра? Валютопотам расскажет в Telegram или в Максе.
Во-вторых, основательно доработал саму платформу. Сделал модульную архитектуру — теперь каждый ботопотам добавляется отдельной директорий со всей своей логикой, изолированной внутри. С доступом к общим функциям: крону, кэшу, очередям, событиям, статистике и так далее. При этом модуль — это некая фича бота, а сами боты добавляются из админки: вставил реквизиты телеги и макса, накликал какие функции нужны — и бот готов.
Добавил локализацию: язык детектится из сообщения юзера, если в боте несколько языков, то можно вручную менять.
Немного улучшил бот мониторов: теперь если какой-то сайт падает, бот некоторое время дёргает его чаще — чтобы быстрее задетектить когда сайт встанет обратно.
Запилил под эти изменения новый лендос Ботопотамов. Старый был чисто про бот мониторинга, новый — про разработку ботов. Ну и публичные боты получили по мини-лендингу. Claude design неплохо справился по-моему, лично я все время залипаю с летающего слоника.
Продолжаем работу, на очереди еще парочка полезных ботов.
Вчера считал эстимейты на группу из ~40 тикетов. Все сделаны по отчету ИИ об анализе кода большого проекта на Drupal. Проекту около 10 лет, кодовая база развивалась все это время, 20 поддоменов, интеграции, апишки, синхронизация контента, в общем прикольный проект.
Отчет структурированный, нейросеть проверяла всех четырёх всадников попокалипсиса в проекте: Уязвимости, Баги, Тормоза и Грязный код. Изначально из переданного отчета получалось гораздо больше задач, но процентов на 30% я сразу won't fix навесил. Там и глюки нашлись, и непонимание контекста. Но 40 тикетов тем не менее осталось.
Среди них тоже в основном таски с минимальнейшим приоритетом, типа
в кастомном модуле не проставлена зависимость от чего-нибудь типа paragraphs;
где-то в коде наглый программист вызвал \Drupal::service() вместо инъекции зависимостей;
где-то deprecated-версии Друпала не убраны из поддерживаемых версий и тому подобное.
Нашлось и несколько более серьезных претензий:
парочка проблем N+1;
несколько XSS-уязвимостей (доступных только админам, но всё же);
несколько мест, где отсутствуют проверки на наличие ключа в массиве (спамит в лог предупрежденими);
и даже одна уязвимость типа timing oracle.
Да, грязненький код — признак грязненьких мыслей :) Да, хорошо бы всё это почистить. Но за вычетом 3–4 претензий, это получается больше ста часов работы суммарно, а выхлоп — немножко более чистый код, причёсанное legacy, немножко меньше техдолга и warning/debug-записей в логе. Хорошо конечно, когда заказчик не против провести такую генеральную уборку. И честь и хвала аккаунтам, которые могут убедить заказчика в необходимости такой уборки при примерно нулевой ценности для конечного пользователя.
А ощущения от таких отчетов по-прежнему странные. Вроде и находит что-то. Но суеты с этими отчетами пока куда больше, чем пользы.
Коллеги, если занимаетесь разработкой или просто завели ботов в Max, напоминаю, что с завтрашнего дня необходимо использовать новый URL для общения с API: https://platform-api2.max.ru.
Кроме того, необходимо будет установить сертификаты Минцифры в доверенные на хост, так как новый URL апишки работает именно с этими сертификатами.
Как обновить сертификаты
В данных примерах я скачиваю сертификаты в build/certs/ потому что потом оттуда добавляю в докер-контейнеры, но вы можете скачать куда хотите.
Скачать актуальные файлы (официальный источник — gu-st.ru, у него самого
сертификат подписан этим же УЦ, поэтому проверку приходится отключать флагом -k):
Залили на Доктурист внутрисистемные уведомления. В первую очередь работают внутри агентств, если кто-то добавил, поменял, удалил бронь, платеж, дедлайн, или статус поменял, остальным агентам (у которых есть доступ) приходит уведомление. Но и для соло-агентов — если они применяют интеграции с банком или сервисом подписания документов — тоже пригодятся.
Уведомления приходят на иконку колокольчика, сопровождаются анимацией, полупрозрачной всплывашкой на 5 секунд, и нежным ненавязчивым «пыком» из динамика. Всплывашку и «пык» при желании можно отключить.
Генеративные нейросети и код-агенты конечно позволяют ворочать значительно большими смысловыми блоками при разработке ПО. Первый предложенный вариант реализации был еще более массивным shotgun surgery, чем прошлая фича — десятки изменений по 3–4 одинаковых строчки, утечки деталей реализации в контроллеры. 60+ измененных файлов (включая тесты). Предложил клоду более элегантное решение, практически без повторений, DI и event-driven, всё как в лучших домах Рио плюс де-Жанейро. Получилось решение более красивое, чистое как слеза Роберта Мартина — но уже на 100+ измененных файлов.
Работает хорошо, надо бы теперь пуши к этому прикрутить. И выделить время, чтобы расписать в виде небольших кейсов.
Когда-то давно описывал довольно простой способ виртуализации проектов, над которыми работаю, чтобы было удобно переключаться и они друг другу не мешали. Прошло уже 7 лет и способ конечно эволюционировал. Когда-то использовать отдельные контейнеры, запускаемые по `docker run` было быстрее и удобнее и поэтому я докерфайлы и docker-compose-файлы не писал. Но прогресс конечно добрался до меня в этом вопросе и победил. Теперь я для локальной разработки тоже использую docker compose.
Инструментами со всякими пресетами типа lando или ddev я, тем не менее, стараюсь не пользоваться. В основном потому что когда с ними сталкивался, они нормально работали — до тех пор пока не надо было что-то в них поменять или сделать нестандартно. После чего начинался вынос мозга, иногда такой, что проще было самому пересобрать сразу.
Кроме того, если собирать «чистые» окружения, есть шанс лучше понять, как это всё работает, а если пользоваться lando, forge, ddev и прочими — наоборот.
Добрые люди из команды Qui-Quo — плагина без которого обходится мало какой уважающий себя турагент — добавили наш Доктурист в список интеграций.
Теперь пользователям Доктуриста не нужно копировать в настройки интеграции загадочные адреса редиректов, а достаточно просто поставить галочку и интеграция заработает. Продолжаем развивать сервис!
Турагенты могут вести десятки броней одновременно. Каждый день — новые оплаты от туристов, каждый день нужно вручную открыть банк, найти платёж, отметить в CRM оплату по туру (иначе как отслеживать что ничего не забыл?) Звучит как мелочь — но это копится ежедневно, сбивает с ритма и иногда порождает ошибки. И в целом это довольно нудно — переписывать руками из одного места в другое. А что нудно — нам делать не очень хочется.
Поэтому мы добавили в Доктурист возможность импорта платежей из банков и начали с интеграции API банка Точка. Здесь рассмотрим кейс о том, как подключили Точку к Доктуристу: сделали автоматические уведомления о платежах, умную привязку к бронированиям и создание платёжных ссылок прямо со страницы брони. И о нескольких нетривиальных вещах, с которыми пришлось разобраться по дороге. Технических и не очень.
Дано
Турагенты постоянно работают с деньгами, основных операций при этом две: принять (пред)оплату от туриста, отправить оплату оператору. Доктурист уже умеет вести историю платежей и показывать их в симпатичном таймлайне:
Задача: нужно сделать что-то более автоматизированное, чем старательно переписывать входящие платежи из банк-клиента. То есть получать входящие платежи в Доктуристе.
Кроме того, агенты часто принимают оплату по ссылкам: создают в банковском приложении ссылку на оплату определенной суммы картой и/или СБП и отправляют туристу. Это такой облегченный эквайринг, когда можно не делать полноценную форму оплаты. И банк не против (если соблюсти определенные правила). Задача 2: почему бы не дать пользователям возможность создавать ссылки на оплату прямо из интерфейса Доктуриста. Чтобы они могли копировать их и отправлять клиентам, а банковское приложение открывать было не нужно.
Вот что конкретно мы научили Доктурист делать:
— получать уведомления от банка о каждом входящем платеже;
— автоматически привязывать платеж к бронированию (если это возможно);
— давать пользователю привязывать платеж к бронированию вручную (если автоматически не вышло);
— создавать ссылки на оплату картой и/или СБП.
С чем столкнулись в процессе
Для входящих платежей Точка отправляет уведомления на зарегистрированные вебхуки, причем вебхуки регистрировать можно программно. Пользователю нужно лишь добавить токен для интеграции и проставить несколько разрешений в банк-клиенте. Уведомления по вебхукам приходят практически мгновенно.
Вебхуки как подписанный JWT
Первое, с чем пришлось разобраться — формат входящих уведомлений от банка. В отличие от сервисов, которые присылают простой JSON с подписью в заголовке, Точка отправляет тело вебхука целиком как подписанный JWT. Это значит, что нельзя просто прочитать JSON — нужно сначала верифицировать подпись публичным ключом банка.
Контроллер читает сырое тело запроса и декодирует JWT через библиотеку firebase/php-jwt:
При любой ошибке декодирования — логируем и тем не менее отвечаем http 200. Это важно: Точка интерпретирует любой не-200 как сбой и будет повторно доставлять уведомление. А так — бизнес-логика не выполняется, но и банк не уходит в цикл отправки.
Тестирование этой механики потребовало отдельных настроек инфраструктуры: RSA-пара генерируется прямо в тестовом классе, публичный ключ подставляется в конфиг, и тогда мы подписываем тестовый пейлоад так же, как это делает Точка и расшифровываем как живое приложение.
Умная авто-линковка
Когда платёж приходит от банка, система пытается найти бронь автоматически — по тексту назначения платежа (например, «Оплата по бронированию ДЕМ-001»). Здесь возникает классическая проблема строкового поиска: если в агентстве есть брони ДЕМ-10 и ДЕМ-100, то поиск ДЕМ-10 найдёт обе. Но мы не хотим ошибиться при связи броней с платежами, поэтому автоматически связываем только если найден ровно 1 результат.
Если есть хотя бы еще одна бронь, чей номер начинается с найденного — линковка не происходит, платёж остаётся непривязанным. Пользователь увидит его в ленте и привяжет вручную. Для удобства привязки, поиск отфильтровывает старые, выполненные, оплаченные и отмененные брони.
Очень умная авто-линковка
Чтобы пользователи не забывали включать в назначение платежа номер брони, сделали, чтобы дефолтный текст при генерации платежной ссылки уже включал номер. Но боевое использование показало, что почти все платежи проходят мимо и ни с чем не линкуются.
После некоторых исследований оказалось, что хотя платежи в банк-клиенте показываются с нормальным назначением типа Оплата тура ФИО, номер брони, как мы задумали, в вебхук почему-то вместо этого прилетает Оплата по QR-коду ID QRABCD12345678 …. Пришлось реализовать дополнительный метод из API, который при получении платежа с таким описанием дергает Точку еще раз, чтобы получить инфу о данном QR-коде. В этой информации назначение платежа уже правильно отражается и по нему можно линковать платеж к брони.
Валютная конвертация при привязке
Точка естественно присылает суммы в рублях, поскольку расчёты в России могут быть только рублевые. Но брони в Доктуристе могут быть заведены и в USD, и в EUR, так как туроператоры могут работать в этих единицах, а платежи принимать по курсу. Когда пользователь вручную привязывает рублёвый платёж к заявке в EUR, система должна рассчитать сумму в EUR, чтобы записать её в правильной валюте. При этом у каждого туроператора свой курс конвертации.
Для этих случаев сделали два сценария:
Валютная заявка + override → пользователь вводит вручную, какое количество USD/EUR получается из платежа (например, «150 EUR»), мы используем это значение в сохраняемом платеже по брони и вместе с ним сохраняем расчетный курс валюты.
Валютная заявка, без override → берём последний курс ЦБ (он обновляется каждый день). В таком случае мы отмечаем связанный платеж как требующий внимания, поскольку авторасчет по курсу ЦБ это примерный расчет, а курс у операторов всегда выше.
Дефолтные значения при создании платежных ссылок
В процессе использования интеграции оказалось, что во многих случаях пользователи хотят создавать платежные ссылки с одним и тем же пресетом, например «Карта выключена, СБП включен». Ошибка в выборе средства оплаты может привести к денежным потерям (комиссия банка на эквайринге и СБП очень разная), что конечно недопустимо.
Пришлось реализовать дефолтную настройку для пользователей, указывающую, какие способы оплаты по умолчанию включены и какие выключены, чтобы снизить вероятность ошибки.
Песочница
В самом начале разработки из документации на API Точки выяснилось, что у них нет полноценной песочницы, позволяющей проводить «игрушечные» платежи, есть только фиксированный набор тестовых запросов, которые, если сделаны верно, возвращают фиксированные ответы. Тестовые запросы конечно небесполезны, но без песочницы невозможно, например, провести полный тестовый цикл: генерация платежной ссылки → её оплата → получение платежа → разбор и линковка к брони. Только по частям.
Собственно, создание ссылок пришлось по большей части тестировать наживую, поскольку оно работает только на аккаунтах, для которых уже активирован эквайринг, а для остальных аккаунтов кидает ошибку 403 "Forbidden by consent".
Но зато в банке есть линия поддержки по интеграции API, которая действительно отвечает по имейлу и даже дает подробную информацию, которой в документации не нашлось.
Результаты
100+ тестов на разные случаи жизни. Мы сделали верификацию JWT-подписи, дедупликацию, авто-линковку с граничными случаями, валютную конвертацию, права доступа. Интеграция API работает с Laravel Horizon, то есть все входящие и исходящие процессы (уведомления о платежах, создание платежной ссылки, регистрация пользователя в системе, регистрация вебхуков) запускаются асинхронно в очередях. А для уведомления ожидающих пользователей используются вебсокеты через Reverb.
Реализация позволила создать и протестировать логику для импорта платежей и создания платежных ссылок, которая не обязана привязываться к одному банку. Теперь необходимо добавить уровень абстракции между платежами/ссылками и API банка, и можно подключать другие банки к системе уже с меньшими трудозатратами. Следующий кандидат на интеграцию — Альфа.
Интеграция уже работает в продакшене. Агенты создают платёжные ссылки прямо со страницы брони и отправляют их туристам — без переключения в банковское приложение. Входящие платежи появляются в системе автоматически и в большинстве случаев сами привязываются к нужному бронированию. Руками нужно разбирать только то, что система не смогла распознать однозначно.
На днях в новостях сообщили, что разработчики Symfony закрыли 19 уязвимостей, найденных моделью Claude Mythos Preview. Что особенно интересно:
A few days later, and following Symfony's security disclosure process, we received a ZIP file with all their findings. In total, Claude Mythos reported 19 security vulnerabilities in Symfony and Twig codebases. The Symfony Core Team reviewed every report manually, and all 19 findings turned out to be real vulnerabilities, with no false positives.
ни одного ложноположительного результата.
Раньше я уже сталкивался с AI-отчетами по безопасности разных web-проектов. Обычно коллеги, или даже заказчики присылали для изучения и доработки. Тогда эти отчеты состояли из ложноположительных срабатываний чуть менее чем полностью. Но даже так затраченное на изучение отчета время того стоило: за 20 «ненастоящими» уязвимостями находилась одна-две-три актуальных. Что само по себе круто, ведь теперь можно их самому не искать, достаточно отсеять из отчета всякую фигню.
А тут — почти два десятка подтвержденных дырок и ни одной ошибки. И хотя Claude Mythos Preview еще не доступен каждому простолюдину — идет закрытое тестирование — это, видимо, успешный успех.
Что тут можно сказать. В наши дни нужно внимательно, ещё внимательнее относиться к регулярным обновлениям ваших программ, пакетов, фреймворков. Claude Mythos Preview может быть доступен и не всем, но исследовать код программы на уязвимости с помощью Claude Code уже сейчас может любой. И на входе не спрашивают, с какими намерениями.
А находить уязвимости умеет и он: XSS, утечки API-токенов, idorы всякие, господипрости. Так что был бы инструмент для поиска, а дырочка найдется. Как говорил нам классик, — There is a crack in everything. That's how the light gets in.
Как понять, что у какого-то проекта клёвая инфраструктура?
Ты прочитал письмо в рассылке, что у проекта через несколько дней выйдет обновление безопасности. Добавил в календарь, чтоб не забыть обновить всё и всех. Потом получил письмо СРОЧНО ВАЖНО от одного хостера. Потом от другого и третьего. Всё про это обновление безопасности.
Потом прочитал напоминание в тематическом телеграм-канале. Потом ожили коллеги в джире, каждый тоже написал о будущем обновлении. Вслед за коллегами ожили клиенты: они тоже получили уведомления от своих хостеров и теперь переживают. В общем ВСЕ уже знают, что у Друпала завтра вечером выйдет патч безопасности. Все знают, все готовятся.
Так что и я глаголю вам: да, завтра с 17 до 21 UTC должен выйти патч безопасности Drupal 10 и 11, вот страничка об этом. Обновление обозначено как высоко критичное, набрало 20 из 25 баллов по шкале трэша, угара и содомиии рисков безопасности. В воздухе запахло озоном, на теле заныли шрамы, полученные в ходе Друпалгеддона I и II.
Обновляйтесь, друзья, как можно скорее — это нужно. А если вы хотите сначала посмотреть, чо там будет, ответственно заявляю: всегда лучше обновиться, и посмотреть, чо там будет с теми, кто не стал, чем наоборот ;)
И да — вот такая клёвая инфраструктура сейчас у Drupal. Отдельная рассылка по обновлениям безопасности. Команда, которая этими дырками занимается. Проверки дырочек не только в ядре, но и в контрибных модулях. Патчи выкладываются в определенный день с предварительным уведомлением.
И да — Drupal при этом совершенно бесплатный.
Отправить письмо
На нашем сайте используются куки-файлы, потому что без них всё плохо работает. А с ними — хорошо. Нажмите на кнопку «Согласен», если согласны с условиями обработки куки и данных на сайте. Если не согласны, можете отключить куки в настройках браузера.