<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>ru</language>
    <title>API</title>
    <description>Рекомендации по использованию API популярных веб-сервисов и не только.</description>
    <link>https://tproger.ru/tag/api</link>
    <atom:link href="https://tproger.ru/tag/api/feed" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Sat, 03 Oct 2026 09:30:04 GMT</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>12</sy:updateFrequency>
    <image>
      <title>API</title>
      <link>https://tproger.ru</link>
      <url>https://tproger.ru/apple-touch-icon.png</url>
    </image>
    <item>
      <title>OpenAI на DevDay выпустила GPT-6.1 Sol по цене в пять раз ниже Astra</title>
      <link>https://tproger.ru/news/openai-na-devday-vypustila-gpt-6-1-sol-po-cene-v-pyat-raz-nizhe-a</link>
      <comments>https://tproger.ru/news/openai-na-devday-vypustila-gpt-6-1-sol-po-cene-v-pyat-raz-nizhe-a?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/openai-na-devday-vypustila-gpt-6-1-sol-po-cene-v-pyat-raz-nizhe-a</guid>
      <description><![CDATA[<p>GPT-6.1 Sol за $2 и $10 за млн токенов, Ultrafast до 8 раз быстрее, Pro 500, Codex в облаке, computer use в Agents API и MCP Events: главное с DevDay.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/openai-na-devday-vypustila-gpt-6-1-sol-po-cene-v-pyat-raz-nizhe-a">OpenAI на DevDay выпустила GPT-6.1 Sol по цене в пять раз ниже Astra</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Облачные технологии]]></category>
      <category><![CDATA[OpenAI]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 29 Sep 2026 14:59:05 GMT</pubDate>
      <content:encoded><![CDATA[<p>OpenAI 29 сентября <a href="https://openai.com/index/devday-2026-recap/">показала</a> на конференции DevDay в Сан-Франциско больше 20 новинок, и среди анонсов для разработчиков — модель <a href="https://openai.com/index/introducing-gpt-6-1-sol/">GPT-6.1 Sol</a>. По замерам компании, она почти догоняет GPT-6 Astra в программировании, работе с компьютером и профессиональных задачах, а стоит в пять раз меньше: $2 за миллион входных токенов и $10 за миллион выходных. В API модель доступна как gpt-6.1-sol.</p><p>Для агентов в API подешевел кэшированный вход: $0,10 за миллион токенов, вдвое меньше, чем у GPT-6 Sol. Кроме модели, OpenAI обновила инструменты: Codex работает в облаке с общими окружениями, Codex CLI принимает голосовые команды, Agents API научился управлять компьютером, а плагины ChatGPT встраиваются в боковую панель и реагируют на события во внешних сервисах. Запись трансляции выложена <a href="https://www.youtube.com/watch?v=Fls_onRviPM">на YouTube</a>.</p><ul><li>GPT-6.1 Sol: $2, $0,10 и $10 за миллион входных, кэшированных и выходных токенов; в ChatGPT Work и Codex — на Plus, Pro, Business, Enterprise и Edu, в обычном чате пока нет.</li><li>По замерам OpenAI, на DeepSWE 1.1 GPT-6.1 Sol решает 75,2% задач при $0,65 за задачу, Astra — 74,1% при $4,43.</li><li>Ultrafast ускоряет генерацию до 8 раз в Codex и до 6 раз в API; в подписке он есть только на Pro 500 за $500 в месяц и на подходящих тарифах Enterprise и Edu.</li><li>Codex в облаке доступен с тарифа Plus, обновлённый Codex CLI и Code Review — на всех тарифах.</li><li>Agents API получил computer use, а MCP Events запускает автоматизации плагинов по вебхукам из внешних сервисов.</li></ul><h2>GPT-6.1 Sol стоит в пять раз меньше Astra</h2><p>GPT-6.1 Sol — обновление GPT-6 Sol, которую OpenAI <a href="https://tproger.ru/news/openai-vypustila-gpt-6-sol-i-gpt-6-luna-v-api">выпустила в API 22 сентября</a>. Стандартные цены у новой модели в пять раз ниже, чем у <a href="https://tproger.ru/news/openai-nachala-vypusk-gpt-6-astra-ceny-benchmarki-i-kiber-ograni">GPT-6 Astra</a>. GPT-6.1 Sol уже работает в ChatGPT Work и Codex на Plus, Pro, Business, Enterprise и Edu со стандартной скоростью, а режим Fast, по документации, доступен там, где позволяют тариф, клиент, настройки рабочего пространства и раскатка; в обычном чате ChatGPT её пока нет.</p><h3>Что показывают бенчмарки OpenAI</h3><p>Результаты моделей OpenAI ниже — замеры самой компании, независимых подтверждений нет; результаты конкурентов она взяла из их публичных отчётов. На графиках по горизонтали — стоимость одной задачи в долларах, по вертикали — результат в процентах, точки на линии — уровни рассуждения от low до max. Чем точка левее и выше, тем выгоднее модель.</p><p>На DeepSWE 1.1, где модели решают длинные задачи в реальных кодовых базах, лучший результат GPT-6.1 Sol — 75,2% на уровне high при $0,65 за задачу. У Astra максимум 74,1% на xhigh при $4,43, у GPT-6 Sol — 68,8% на max при $2,74. На max GPT-6.1 Sol набирает меньше, чем на high, так что предельный уровень рассуждения здесь не нужен.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/25f5aa1e-c533-498a-b7d8-14d84e4eea7b.webp" alt="График DeepSWE 1.1: результат в процентах против стоимости задачи в долларах для GPT-6.1 Sol, GPT-6 Sol и GPT-6 Astra на уровнях рассуждения от low до max" /><figcaption>График: Tproger по данным OpenAI (замеры компании)</figcaption></figure><p>AutomationBench 1.0.6 проверяет сквозные бизнес-процессы с 47 инструментами. На уровне medium GPT-6.1 Sol на 2,2 п. п. выше Opus 5.5 примерно за треть цены, но на max впереди другие: Opus 5.5 с резервными моделями — 42,5% при $1,44, Astra — 41,4% при $1,73, GPT-6.1 Sol — 36,1% при $0,30. Цену Fable 5.1 ($2,45 за задачу) OpenAI в сноске называет заниженной: в неё не вошли вызовы резервной модели, которые понадобились примерно в 40% задач.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/c9487fa7-e28d-4f0e-8aad-721eab144847.webp" alt="График AutomationBench: результат в процентах против стоимости задачи для GPT-6.1 Sol, GPT-6 Sol, GPT-6 Astra, Opus 5.5 и отдельной точки Fable 5.1" /><figcaption>График: Tproger по данным OpenAI; результат Opus 5.5 и Fable 5.1 взят из публичных отчётов их разработчиков</figcaption></figure><p>На OSWorld 2.0, где агент работает с обычными программами (частичная оценка на offline-наборе версии v2026.08.08), GPT-6.1 Sol на max набирает 71,4% при $1,27, Astra — 73,5% при $9,44, GPT-6 Sol — 64,4% при $3,37. Разница с Astra — 2,1 п. п. при цене примерно в 7 раз ниже.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/a000412f-5dd9-46d7-977a-baae013a3a5b.webp" alt="График OSWorld 2.0: результат в процентах против стоимости задачи для GPT-6.1 Sol, GPT-6 Sol и GPT-6 Astra" /><figcaption>График: Tproger по данным OpenAI (замеры компании)</figcaption></figure><p>На Terminal-Bench Science 0.1 (анализ данных, симуляции, доказательство теорем в терминале) GPT-6.1 Sol получает 57,0% при $5,47 за задачу, больше чем вдвое выше GPT-6 Sol. Лидирует Astra с 68,1% при $23,80, и OpenAI сама советует брать её для самых трудных научных задач.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/2cb0839c-4365-4c18-a9f5-8932b9cc7331.webp" alt="График Terminal-Bench Science 0.1: результат в процентах против стоимости задачи для GPT-6.1 Sol, GPT-6 Sol, GPT-6 Astra и Opus 5.5" /><figcaption>График: Tproger по данным OpenAI; результат Opus 5.5 взят из публичного отчёта Anthropic</figcaption></figure><p>На GDP.pdf, где нужно отвечать на вопросы по сложным PDF, GPT-6.1 Sol на max сравнялась с Astra — по 31,0% — при цене $0,42 против $2,08. Доля ответов с фактической ошибкой на уровне low снизилась с 11,4% до 7,7%, но замер сделан на специально трудных диалогах, нетипичных для обычной работы.</p><h2>Ultrafast ускоряет генерацию токенов до 8 раз, но в подписке только на Pro 500</h2><p>Ultrafast — платный уровень скорости: по данным OpenAI, в Codex это до 300 токенов в секунду, до 8 раз быстрее обычного режима, в API — до 6 раз быстрее. Широко он доступен только для GPT-6 Astra, для GPT-5.6 Sol в API есть превью. В API режим <a href="https://developers.openai.com/api/docs/guides/ultrafast-mode">включается параметром</a> service_tier, лимиты — от 500 тыс. до 5 млн токенов в минуту в зависимости от уровня аккаунта, региональные эндпоинты вроде европейского не поддерживаются, цены вынесены в отдельную таблицу. В Codex, <a href="https://learn.chatgpt.com/docs/agent-configuration/speed">по документации</a>, Ultrafast расходует включённый в подписку лимит в 8 раз быстрее обычного режима.</p><p>Подписка Pro <a href="https://help.openai.com/en/articles/9793128-about-chatgpt-pro-tiers">теперь бывает трёх видов</a>: Pro 100 за $100, Pro 200 за $200 и Pro 500 за $500 в месяц, последний с Ultrafast и лимитом в 25 раз выше, чем у Plus. Pro 200 снова открыт для новых подписчиков, но с сокращённым лимитом. Подписчики, попавшие под условия сохранения, держат прежний лимит до 29 октября 2026 года. Ultrafast это не даёт, и покупка кредитов на Pro 100 или Pro 200 его тоже не открывает.</p><h2>Codex получил облачные окружения, а CLI начал слушать голос</h2><p><a href="https://learn.chatgpt.com/docs/cloud">Codex в облаке</a> запускает задачи на удалённой машине, а ставить и проверять их можно с компьютера, телефона или из браузера. Вы выбираете репозитории GitHub, Codex сам ставит зависимости и инструменты и прогоняет проверки, а опубликованное окружение с настройками сети и секретами команда может выбирать для своих задач. Каждая задача работает в своём пространстве, даже когда ноутбук спит. Тарифы — от Plus.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/afeba39f-f050-4011-a93a-88ed1f8031cc.webp" alt="Мобильный интерфейс Codex: вкладки All, Cloud и ноутбук пользователя, под ними список проектов" /><figcaption>Облачные проекты Codex на телефоне. Изображение: OpenAI</figcaption></figure><p>В <a href="https://learn.chatgpt.com/docs/codex/cli">Codex CLI</a> задачи можно ставить и направлять голосом (голосовые диалоги <a href="https://tproger.ru/news/codex-cli-0-155-0-poluchil-golosovye-dialogi-i-podtverzhdenie-mcp">появились ещё в версии 0.155.0</a>), а новый экран /agents показывает сразу несколько делегированных задач. OpenAI также улучшила возобновление сессий и работу с git worktree. Доступно на всех тарифах, обновление ставится той же командой, что и сам CLI:</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/1ec81c64-c5c2-4815-b2e1-e92a38017f95.webp" alt="Окно Codex CLI: агент на GPT-6 Astra добавляет горячие клавиши в дашборд пулл-реквестов, правит файл и запускает тесты" /><figcaption>Codex CLI выполняет задачу в терминале. Изображение: OpenAI</figcaption></figure><p><a href="https://learn.chatgpt.com/docs/code-review?surface=app">Code Review</a> в десктопном приложении ChatGPT показывает сводку и диффы и позволяет спросить Codex о проблемах до комментария в пулл-реквесте GitHub или мерж-реквесте GitLab; в автоматическом режиме Codex делает первый проход в облаке сам. Функция есть на всех тарифах.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/b896793c-6fb7-47cd-ac68-ef5e2f136d90.webp" alt="Экран Code Review в приложении ChatGPT: замечание Codex с приоритетом P2 к строке кода и чат с просьбой поправить интерфейс" /><figcaption>Code Review в приложении ChatGPT. Изображение: OpenAI</figcaption></figure><p><a href="https://learn.chatgpt.com/docs/security/setup">Codex Security Cloud</a> сканирует репозитории GitHub по запросу или расписанию, следит за новыми коммитами, сам отсеивает дубли и готовит исправления, которые можно оформить черновым пулл-реквестом. В него входит доступ к моделям программы Daybreak Blue без отдельной заявки. Тарифы — Pro, Business, Enterprise и Edu.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/e51c9047-240b-4f95-9d0a-b462866bb75d.webp" alt="Дашборд Codex Security Cloud: счётчики находок по критичности, воронка от обнаружения до исправления и таблица находок с кнопками Fix" /><figcaption>Дашборд Codex Security Cloud с находками. Изображение: OpenAI</figcaption></figure><h2>Какие API OpenAI дала для собственных агентов</h2><p><a href="https://openai.com/index/introducing-the-agents-api/">Agents API</a> получил <a href="https://developers.openai.com/api/docs/guides/agents-api/tools/computer-use">computer use</a>: агент на нём может сам работать с программами. Туда же перенесли возможности Codex — несколько агентов в одной задаче, поиск инструментов, сжатие контекста, а инфраструктуру держит OpenAI. Песочницу для команд и файлов может дать OpenAI или ваш провайдер. В Codex и ChatGPT Work функция доступна на Pro 500 и Enterprise. По словам OpenAI, отдельной платы за сам Agents API нет: оплачиваются токены и инструменты.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/abdc50c3-47ab-4dd4-b62e-5dd86caf778b.webp" alt="Схема Agents API: приложение отправляет задачи, Agents API с управляемой обвязкой Codex вызывает инструменты в песочнице и возвращает события и результат" /><figcaption>Схема работы Agents API с computer use. Изображение: OpenAI</figcaption></figure><p>Decisions API сводит работу модели Luna к ответам на заданные вопросы с фиксированными вариантами: так можно классифицировать контент, маршрутизировать запросы или выбирать следующий шаг агента. Пока это ограниченное превью. <a href="https://aws.amazon.com/bedrock/managed-agents-openai/">Bedrock Managed Agents</a>, сделанные вместе с Amazon, запускают агентов OpenAI целиком внутри AWS.</p><p>Sign in with ChatGPT даёт тратить лимит подписки Plus или Pro в 16 сторонних сервисах, среди них Devin, Notion, Vercel и T3, с отдельным потолком для каждого.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/2ad74cf9-de82-4c52-9c47-6f05e381eb33.webp" alt="Окно Connect ChatGPT and Devin с переключателем, разрешающим Devin тратить лимит подписки ChatGPT" /><figcaption>Окно подключения ChatGPT к Devin. Изображение: OpenAI</figcaption></figure><p>Для компаний OpenAI собрала набор Private Intelligence: <a href="https://developers.openai.com/api/docs/guides/private-safety-processing">Private Safety Processing</a> вместе с нулевым хранением данных позволяет проводить автоматические проверки безопасности без доступа сотрудников OpenAI к содержимому запросов, а превью Private Inference на конфиденциальных вычислениях обещано осенью.</p><h2>Плагины встраиваются в интерфейс ChatGPT и реагируют на события</h2><p><a href="https://developers.openai.com/plugins/build/extensions">Plugin extensions</a> открывают сторонним разработчикам платформу, на которой OpenAI делает функции ChatGPT: плагин получает пункт в боковой панели, панель рядом с диалогом, свой просмотрщик для форматов файлов, формы и упоминания в поле ввода. Точки входа объявляются в метаданных MCP-сервера ключом openai/ui, SDK есть для TypeScript и Python. Canva, Figma и Adobe уже используют расширения.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-29/8c61b18a-c2e3-4add-a4a1-2285ac5d113b.webp" alt="Плагин Canva открыт в боковой панели ChatGPT: стартовый экран с шаблонами презентаций и категориями дизайна" /><figcaption>Расширение Canva в боковой панели ChatGPT. Изображение: OpenAI</figcaption></figure><p>Для авторов <a href="https://developers.openai.com/plugins">плагинов</a> появились Plugin Creator и обновлённая подача в каталог с более понятной обратной связью, а сами плагины можно подключать к Sites на тарифах Business, Enterprise, Healthcare и Edu.</p><p><a href="https://developers.openai.com/plugins/build/mcp-events">MCP Events</a> — поддержка предложенной спецификации событий MCP. ChatGPT подписывается на события сервера и выполняет инструкцию пользователя: например, на каждый баг-репорт в канале #product-feedback открывает черновой пулл-реквест. Серверу нужны протокол MCP версии 2026-07-28, методы events/list, events/subscribe и events/unsubscribe и доставка вебхуками с подписью Standard Webhooks, не больше 256 КиБ на событие. Опрос и стриминг не поддерживаются, события могут прийти не по порядку, поэтому инструменты записи должны быть идемпотентными.</p><h2>Dots — агенты на GPT-6 Astra, которые работают круглосуточно</h2><p><a href="https://openai.com/index/introducing-dots/">Dots</a> — постоянно работающие агенты на GPT-6 Astra со своим облачным компьютером и браузером; через плагины они подключаются к более чем 4000 приложений и доступны в ChatGPT, Slack и Teams. OpenAI приводит сценарий для разработчика: агент следит за отзывами клиентов, сам делает мелкие исправления с тестами и приносит готовые пулл-реквесты. В фоне он работает только с инструментами на чтение. Первый dot входит в Pro и Business Premium без доплаты, раскатка идёт в поддерживаемых странах; у Enterprise, Edu и Healthcare это бета, которую включает администратор.</p><h2>Что OpenAI добавила в ChatGPT для командной работы</h2><ul><li>ChatGPT Space — общее пространство команды, ChatGPT и агента dot; Pro, Business и Enterprise, создавать и править можно в десктопном приложении и вебе, на телефоне пока только искать, читать и делиться.</li><li>Pages — документы, которые вместе правят люди и агенты; Pro, Business и Enterprise.</li><li>Совместные слайды с экспортом в PowerPoint и Google Slides — в ближайшие недели для Pro, Business и Enterprise.</li><li>Команды и <a href="https://learn.chatgpt.com/docs/enterprise/team-tasks">общие задачи</a>, которые запускаются по расписанию или по событию, например новому письму; Business и Enterprise.</li><li>@ChatGPT в Slack и Microsoft Teams, коллегам не нужна своя лицензия; Business и Enterprise.</li><li>Плагин Meetings пишет заметки со встреч, аудио удаляется после подготовки заметок; бета на macOS для Pro и Business.</li><li>Профили, где можно делиться своими Sites и плагинами; Business и Enterprise.</li><li>OpenAI Marketplace: подходящие корпоративные клиенты могут подать заявку и направить часть действующего обязательства перед OpenAI на одобренный софт 32 партнёров, от Adobe и Figma до Salesforce и CrowdStrike.</li></ul><h2>Что ещё не вышло и что можно сделать сегодня</h2><p>GPT-6.1 Sol Ultrafast обещан в ближайшие дни, широкий доступ к Decisions API — тоже, совместные слайды — в ближайшие недели, превью Private Inference — осенью. Точных дат OpenAI не назвала.</p><ul><li>В API достаточно заменить имя модели на gpt-6.1-sol; в Codex CLI модель меняется командой /model, режим Fast включается командой /fast.</li><li>14 октября 2026 года GPT-5.5 уйдёт из ChatGPT, ChatGPT Work и Codex на всех тарифах; в API она останется.</li><li>Подписчикам Pro 200 стоит проверить почту: письмо о сохранённом до 29 октября лимите получат только те, кого коснулось изменение.</li></ul><p>Источники: <a href="https://openai.com/index/devday-2026-recap/">OpenAI: DevDay 2026 Recap</a>, <a href="https://openai.com/index/introducing-gpt-6-1-sol/">OpenAI: Introducing GPT-6.1 Sol</a>, <a href="https://openai.com/index/introducing-dots/">OpenAI: Introducing dots</a>, <a href="https://help.openai.com/en/articles/9793128-about-chatgpt-pro-tiers">OpenAI Help Center: About ChatGPT Pro tiers</a>, <a href="https://developers.openai.com/api/docs/guides/ultrafast-mode">OpenAI API: Ultrafast mode</a>, <a href="https://learn.chatgpt.com/docs/agent-configuration/speed">ChatGPT Learn: Speed</a>, <a href="https://learn.chatgpt.com/docs/cloud">ChatGPT Learn: Codex Cloud</a>, <a href="https://learn.chatgpt.com/docs/codex/cli">ChatGPT Learn: Codex CLI</a>, <a href="https://learn.chatgpt.com/docs/code-review?surface=app">ChatGPT Learn: Code review</a>, <a href="https://learn.chatgpt.com/docs/security/setup">ChatGPT Learn: Codex Security Cloud setup</a>, <a href="https://openai.com/index/introducing-the-agents-api/">OpenAI: Introducing the Agents API</a>, <a href="https://developers.openai.com/plugins/build/extensions">OpenAI Plugins: Extensions</a>, <a href="https://developers.openai.com/plugins/build/mcp-events">OpenAI Plugins: MCP Events</a>, <a href="https://developers.openai.com/api/docs/guides/private-safety-processing">OpenAI API: Private Safety Processing</a>, <a href="https://www.youtube.com/watch?v=Fls_onRviPM">Трансляция OpenAI DevDay 2026</a></p><p>Изображение на обложке: Кадр трансляции: OpenAI</p>]]></content:encoded>
    </item>
    <item>
      <title>Идемпотентность и Outbox: как не выполнить одну операцию дважды</title>
      <link>https://tproger.ru/articles/idempotentnost-i-outbox-kak-ne-vypolnit-odnu-operaciyu-dvazhdy</link>
      <comments>https://tproger.ru/articles/idempotentnost-i-outbox-kak-ne-vypolnit-odnu-operaciyu-dvazhdy?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/idempotentnost-i-outbox-kak-ne-vypolnit-odnu-operaciyu-dvazhdy</guid>
      <description><![CDATA[<p>Как сделать ручку идемпотентной, где ломается наивная проверка ключа и зачем нужен transactional outbox. Забирайте код на Python, SQL и Node.js и чеклист.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/idempotentnost-i-outbox-kak-ne-vypolnit-odnu-operaciyu-dvazhdy">Идемпотентность и Outbox: как не выполнить одну операцию дважды</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Микросервисы]]></category>
      <category><![CDATA[Архитектура ПО]]></category>
      <category><![CDATA[Node.js]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[PostgreSQL]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 09 Sep 2026 05:00:35 GMT</pubDate>
      <content:encoded><![CDATA[<p>История, с которой начинает автор одного из разборов ниже, звучит буднично. Платёжный шлюз не ответил вовремя, клиентская библиотека повторила запрос, и покупателя списали дважды. Сумма небольшая, а возврат, тикет в поддержку и восстановление доверия заняли недели.</p><p>Виноват тут не шлюз. Виноват сервер, который исходил из того, что каждый запрос приходит ровно один раз. В сети, где теряются ответы, это допущение неверно всегда.</p><p>Идемпотентность — свойство операции, при котором повторное выполнение приводит к тому же состоянию, что и однократное. Сам ответ при этом может отличаться: повторный DELETE вернёт 404 вместо 200, и метод от этого идемпотентным быть не перестаёт. У HTTP это закреплено на уровне методов: <a href="https://www.rfc-editor.org/rfc/rfc9110">RFC 9110</a> относит к идемпотентным PUT, DELETE и безопасные методы, а POST идемпотентным по своей природе не является. Бизнес-операции почти всегда отправляют именно через POST.</p><p>Клиент не может отличить «сервер не получил запрос» от «сервер выполнил операцию, но ответ потерялся», поэтому повтор придёт в любом случае.</p><p>Ключ идемпотентности генерирует клиент, а сервер хранит связку ключа со слепком запроса и с готовым ответом, чтобы повтор получил тот же результат, а не новый.</p><p>Проверка «посмотреть и вставить» неатомарна: два одновременных повтора оба увидят отсутствие ключа. Нужен уникальный индекс или условная запись.</p><p>Запись в базу и отправка в очередь в одну транзакцию не помещаются. Обёртывать сетевой вызов в BEGIN и COMMIT вредно вдвойне: корректности не даёт, а пул соединений выедает.</p><p>Transactional outbox решает это одной таблицей: событие пишется в той же транзакции, что и бизнес-запись, а отдельный процесс доставляет его в очередь.</p><h2>Почему повтор неизбежен</h2><p>Сеть отказывает так, что установить факт доставки невозможно в принципе. Есть три типовых сценария, и внешне они неразличимы:</p><ul><li>Сервер обработал запрос, но ответ потерялся по дороге назад.</li><li>Сервер всё ещё считает, а у клиента уже сработал таймаут.</li><li>Балансировщик повторил запрос сам, никого об этом не уведомив.</li></ul><p>Для GET повтор безвреден. Для POST /payments это второе списание. Отсюда и правило: одна логическая операция должна приводить к одному записанному итоговому состоянию, сколько бы раз её ни отправили. Осознанно новая операция обязана прийти с новым ключом.</p><h2>Два способа сделать ручку идемпотентной и один в довесок</h2><h3>Способ первый: ключ идемпотентности</h3><p>Самый распространённый вариант: клиент генерирует уникальный идентификатор на одну логическую операцию и повторяет его при каждой попытке. Сервер хранит соответствие ключа и ответа, а на дубликате возвращает сохранённый результат вместо повторного выполнения работы.</p><p>Три детали, на которых ошибаются чаще всего. Ключ генерирует клиент, а не сервер: смысл в том, что сервер сам по себе не отличит новый запрос от повтора. Ключ должен быть с высокой энтропией, обычно это UUID v4; выводить его из изменяемого или малоразнообразного поля вроде номера клиента нельзя, потому что это повышает риск коллизии и переигрывания чужой операции.</p><p>И последнее: повтор должен получить <b>тот же самый ответ</b>. Если первая попытка вернула 201 с идентификатором платежа, то и повтор возвращает те же 201 и тот же идентификатор, а не 409 и не пустую двухсотку. Иначе клиент решит, что операция не прошла, и попробует ещё раз.</p><h3>Способ второй: сделать операцию идемпотентной по смыслу</h3><p>Иногда ключ не нужен вовсе, потому что семантику можно спроектировать идемпотентной с самого начала. Классический пример — PUT /users/42, который задаёт полное представление ресурса: отправьте его дважды, и состояние будет одним и тем же.</p><p>Для операций создания трюк в том, чтобы выводить идентификатор из самого запроса, а не генерировать случайный на каждый вызов:</p><p>Идентификатор детерминированно выводится из почты, поэтому повторный запрос даёт того же пользователя без дублирующей строки. Плата за простоту — необходимость естественного уникального ключа: почты, артикула, внешнего идентификатора. Хеш при этом считается от точной строки, поэтому почту нужно привести к нижнему регистру и обрезать пробелы до хеширования: иначе один и тот же ящик с заглавной буквы даст второго пользователя. И ключ должен быть неизменным: если пользователь сменит почту, выведенный из неё идентификатор либо останется прежним и перестанет соответствовать данным, либо изменится и оторвётся от всех ссылок на него в соседних таблицах. Нет подходящего ключа, возвращайтесь к первому способу.</p><h3>Довесок: оптимистичная блокировка</h3><p>Этот приём идемпотентности не даёт и в списке стоит по другой причине. Ключ защищает от повторов одного и того же запроса, но ничего не делает с двумя <b>разными</b> запросами, которые правят одну запись. Здесь работает проверка версии: клиент присылает версию, которую видел, а сервер отклоняет обновление при несовпадении.</p><p>Обратите внимание, что проверка версии живёт внутри самого UPDATE. Разнести её на отдельное чтение и последующую запись означало бы воспроизвести ровно ту гонку, о которой пойдёт речь в следующем разделе: два запроса с одной устаревшей версией оба прошли бы проверку и оба записали бы результат. Идемпотентным одиночный запрос этот приём не делает, зато закрывает частый источник задвоенных эффектов: двух писателей, затирающих работу друг друга.</p><h2>Где наивная реализация ключа разваливается</h2><h3>Гонка в проверке</h3><p>Последовательность «проверить наличие ключа, потом вставить» содержит зазор, в который помещаются оба одновременных повтора: обе стороны видят, что ключа нет, и обе выполняют работу. Резервировать ключ нужно атомарно, через уникальное ограничение базы, условную запись или транзакционный compare-and-set (атомарное сравнение с записью).</p><p>Это же относится и к примеру с платежом выше: замена словаря в памяти на Redis гонку не закрывает, пока проверка и вставка остаются двумя отдельными командами. Нужен атомарный примитив резервирования, вроде SET key value NX или INSERT ... ON CONFLICT DO NOTHING.</p><p>Проверяется это только настоящей конкуренцией. Юнит-тест, вызывающий функцию дважды подряд, гонку не поймает никогда. Отправьте полсотни одновременных запросов с одним ключом и убедитесь, что побочный эффект произошёл ровно один раз.</p><h3>Слепок запроса, а не только ключ</h3><p>Хранить один ключ недостаточно. Сервер канонизирует поля, определяющие бизнес-смысл операции, и считает от них хеш. Канонизация означает приведение к единому виду порядка полей, форматов чисел и дат, опущенных значений по умолчанию и незначащих пробелов. Если повторный вызов обязан воспроизвести решение, принятое по прежним правилам, в слепок включают ещё и версию политики. Пример: между первой попыткой и повтором поменялись тарифы, и повтор обязан вернуть старую цену, а не пересчитать по новой. Без версии в слепке сервер этого различия не увидит.</p><p>Когда тот же ключ приходит с другим слепком, это ошибка на стороне клиента, и отдавать ему старый результат нельзя. <a href="https://dev.to/seo_optimization_591fad6c/designing-idempotent-decision-endpoints-that-survive-real-retries-6c1">Разбор проектирования идемпотентных ручек</a> предлагает отвечать 409 Conflict; <a href="https://dev.to/sirmax/3-ways-to-make-your-api-requests-idempotent-with-working-code-4inl">автор практического руководства</a> в этом случае возвращает 422. Важно, чтобы выбранный код был задокументирован и никогда не подменяется молчаливой отдачей чужого ответа.</p><h3>Состояния и коды ответа</h3><p>Минимальная модель состояний записи выглядит так: PROCESSING, SUCCEEDED, FAILED_RETRYABLE и FAILED_FINAL. Рядом хранятся ключ операции, слепок, отметки времени, идентификатор решения, снимок ответа и версия политики. Клиенту нужна детерминированная карта из состояния в код ответа:</p><ul><li>201 или 200 — первый успешно завершённый результат.</li><li>200 с явной пометкой о повторе — проигрывание сохранённого ответа.</li><li>202 со ссылкой на статус — работу уже выполняет другой обработчик, начинать вторую не нужно.</li><li>409 — ключ переиспользован с другим содержимым.</li><li>Задокументированная финальная ошибка — обработка провалилась, и автоматическое продолжение небезопасно.</li></ul><p><b>Срок жизни ключей:</b><br />Хранить их вечно не нужно, это медленная утечка. Сутки покрывают практически любое реальное окно повторов, но выбирать срок стоит от риска предметной области: у платежей и у рекомендаций он разный. И помните, что ключ приходит снаружи: ограничьте длину и набор символов, привяжите его к арендатору и не дайте одному пользователю вытащить результат чужой операции.</p><h2>Вторая половина задачи: база и очередь</h2><p>Допустим, ручка стала идемпотентной. Остаётся более коварная проблема: почти всякая бизнес-операция пишет не в одно место. Заказ сохраняется в базу и публикует событие в очередь, чтобы склад начал сборку, почтовый сервис отправил подтверждение, а антифрод посмотрел на транзакцию.</p><p>Обе половины статьи растут из одного факта: ни HTTP, ни очередь не обещают доставку ровно один раз, они обещают её хотя бы один раз. Поэтому защищаться приходится дважды, на входе и на выходе.</p><p>Это две записи в две разные системы, и общей транзакции у них нет. Упал процесс, моргнула сеть, выкатился деплой между двумя вызовами — одна сторона зафиксирована, вторая нет. Заказ подтверждён на экране покупателя, а склад о нём не знает. Ошибка при этом нигде не залогирована и алерт не сработал.</p><h3>Почему обернуть это в транзакцию нельзя</h3><p>Соблазнительный и заведомо неверный вариант выглядит так:</p><p>Транзакция базы не имеет власти над очередью и умеет откатывать только операции базы. Если отправка прошла, а COMMIT упал, сообщение уже в очереди и забрать его оттуда нельзя.</p><p>Есть и вторая беда, чисто эксплуатационная. Такой код держит открытое соединение и блокировки строк всё время сетевого вызова. Обычно очередь отвечает быстро, но под нагрузкой, ретраями или деградацией вызов растягивается на секунды, и все запросы к тем же строкам стоят в очереди. Это надёжный способ исчерпать пул соединений и уронить заодно ни в чём не повинные части сервиса.</p><h3>Outbox: событие как строка в той же транзакции</h3><p>Идея паттерна в том, чтобы перестать считать публикацию второй записью. Вместо вызова очереди приложение вставляет строку в таблицу outbox в той же транзакции, что и бизнес-запись. Отдельный процесс читает таблицу и публикует сообщения дальше.</p><p>Откатилась транзакция, и вместе с ней исчезла строка outbox: осиротевшего сообщения в очереди не осталось. Упало приложение сразу после фиксации — строка на месте со статусом pending, и доставщик заберёт её на следующем проходе. Паттерн опирается ровно на одну гарантию, которую база и так даёт: атомарность одной транзакции.</p><p>Доставщик выбирает пачку необработанных строк и помечает их отправленными только после подтверждения очередью. Ключевая деталь здесь одна:</p><p>Этот SELECT и последующая простановка статуса выполняются в одной транзакции: блокировка живёт до фиксации. Благодаря SKIP LOCKED доставщик масштабируется горизонтально из коробки, каждый экземпляр берёт свой набор строк. А если он упадёт посреди пачки, вся пачка откатится и уйдёт повторно, что даёт ещё один довод в пользу идемпотентного потребителя.</p><p>Может показаться, что здесь мы делаем ровно то, что осудили выше: держим блокировку на время сетевого вызова. Разница в том, что блокируется не бизнес-таблица и соединение берётся не из пула, обслуживающего пользовательские запросы, а SKIP LOCKED не даёт одной медленной строке задержать остальные.</p><h3>Потребитель обязан быть идемпотентным</h3><p>Если доставщик упал посреди прохода, на следующем он переотправит те же строки. Очереди вроде SQS и Kafka в типовой конфигурации гарантируют доставку «хотя бы один раз», поэтому дедупликация на приёмной стороне обязательна, и уникальным ключом служит идентификатор события или решения.</p><p>Делает это условная запись. Важная деталь, на которой легко ошибиться: сама по себе она пустой операцией не становится. При несовпадении условия драйвер бросает исключение, и его нужно поймать явно, отличив штатный повтор от настоящей ошибки:</p><p>Настройки продюсера и подтверждения брокера снижают количество повторов, но не снимают с приложения ответственность за однократность бизнес-эффекта.</p><h3>Что добавить перед продакшеном</h3><p>Двух статусов мало. Нужен статус failed и счётчик попыток: после N неудач строка помечается провалившейся и перестаёт крутиться в цикле вечно. На стороне очереди настраивается очередь недоставленных сообщений, чтобы то, что потребитель не смог обработать, оседало в наблюдаемом месте, а не исчезало молча.</p><p>Когда задержка опроса становится критичной, полагающийся на периодический опрос доставщик заменяют захватом изменений: инструменты вроде Debezium читают журнал предзаписи PostgreSQL и публикуют изменения без паузы на опрос. Таблица outbox и потребитель при этом не меняются. Но это заметно более тяжёлое эксплуатационное обязательство, поэтому начинать почти всегда стоит с опроса.</p><h2>Что забрать с собой</h2><p>Обе части задачи выглядят избыточными ровно до первого инцидента. Тридцать строк кода с ключом идемпотентности стоят дешевле одного тикета с заголовком «вы списали дважды», а таблица outbox дешевле расследования, почему заказ есть у клиента и отсутствует на складе.</p><p>Коварство проблемы двух записей в том, что наивная реализация работает правильно почти всегда. Она отказывает в зазоре между двумя системами, и зазор этот становится виден только когда что-то пошло не так в самый неподходящий момент. К моменту, когда расхождение заметят в продакшене, данные уже разъехались, и красивого способа их починить не будет.</p><p>Как одно неверное допущение о порядке вызовов обернулось эпидемией задвоенных операций, показано в <a href="https://tproger.ru/articles/skrytyj-sboj-idempotentnosti-v-finteh-sisteme-razbor-incidenta">разборе реального инцидента в финтех-системе</a>.</p><p>Материалы, на которых основан разбор: <a href="https://dev.to/sirmax/3-ways-to-make-your-api-requests-idempotent-with-working-code-4inl">три паттерна идемпотентности с рабочим кодом</a>, <a href="https://dev.to/seo_optimization_591fad6c/designing-idempotent-decision-endpoints-that-survive-real-retries-6c1">проектирование ручек, переживающих реальные повторы</a> и <a href="https://www.freecodecamp.org/news/how-to-fix-the-dual-write-problem-in-node-js-with-the-outbox-pattern/">пошаговая сборка outbox на Node.js</a>.</p><p>Откройте самый денежный обработчик в своём сервисе и попробуйте отправить в него один и тот же запрос дважды. Если во второй раз что-то произошло, вы уже знаете, с чего начать понедельник.</p>]]></content:encoded>
    </item>
    <item>
      <title>Fable 5.1, GPT-6 Astra и дешёвые Flash: что брать в API в сентябре 2026</title>
      <link>https://tproger.ru/articles/fable-5-1-gpt-6-astra-i-dewyovye-flash-chto-brat-v-api-v-sentyab</link>
      <comments>https://tproger.ru/articles/fable-5-1-gpt-6-astra-i-dewyovye-flash-chto-brat-v-api-v-sentyab?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/fable-5-1-gpt-6-astra-i-dewyovye-flash-chto-brat-v-api-v-sentyab</guid>
      <description><![CDATA[<p>Fable 5.1 и GPT-6 Astra по $10/$50, Gemini 3.8 Flash за $0,75, Mercury 2.5 за $0,20, MAI-Transcribe-2 за $0,10 в час: цена задачи, уровни усилия и команды API.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/fable-5-1-gpt-6-astra-i-dewyovye-flash-chto-brat-v-api-v-sentyab">Fable 5.1, GPT-6 Astra и дешёвые Flash: что брать в API в сентябре 2026</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Машинное обучение]]></category>
      <category><![CDATA[Нейронные сети]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[OpenAI]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 08 Sep 2026 18:43:41 GMT</pubDate>
      <content:encoded><![CDATA[<p>За первую неделю сентября 2026 года вышли две флагманские модели с одинаковым прайсом $10 за миллион входных токенов и $50 за миллион выходных: Claude Fable 5.1 от Anthropic 1 сентября и GPT-6 Astra от OpenAI 3 сентября. Рядом появились дешёвые быстрые модели (Gemini 3.8 Flash, Mercury 2.5, DeepSeek V4.1 Flash, Muse Spark 1.3), обновлённая Qwen3.8-Max, две картиночные модели и модель распознавания речи. Ниже по каждой: что умеет по замерам вендора и независимых лабораторий, где лежит и сколько стоит.</p><p>Главный вывод недели: цена за миллион токенов больше не говорит, во что обойдётся задача. Astra стоит за токен в 2,5 раза дороже GPT-5.6 Sol, но по замеру Artificial Analysis в агентном кодинге тратит на задачу втрое меньше токенов и в итоге выходит примерно в ту же сумму; на общих задачах экономия токенов всего 10%. Fable 5.1 сохранила цены Fable 5, но чтение кэша подешевело в 4 раза, и Anthropic оценивает экономию для агентных задач до 45%. Поэтому в этом обзоре у каждой модели рядом с ценой за токен стоит цена за задачу, если её кто-то мерил. Августовские релизы разобраны в <a href="https://tproger.ru/news/fable-5-1-qwen3-8-max-i-deepseek-v4-chto-brat-v-api-za-avgust">прошлом обзоре</a>, здесь они не повторяются.</p><ul><li>Claude Fable 5.1 и Mythos 5.1 — одна модель с разными ограничителями. Цена $10/$50 за миллион токенов, чтение кэша $0,25 вместо $1. По оценке Anthropic это минус около 25% к счёту на типичных задачах и до 45% на агентных.</li><li>GPT-6 Astra стоит те же $10/$50. На Terminal-Bench 4.0 по замеру OpenAI она набирает 57,9% против 55,8% у Fable 5.1 при цене задачи на 63% ниже. В индексе Artificial Analysis v4.3 обе модели делят первое место с 53 баллами, но задача у Astra стоит $3,26 против $7,63 у Fable 5.1.</li><li>Уровень рассуждений стал главным рычагом цены: у Fable 5.1 шаг с xhigh до max даёт полбалла на Humanity's Last Exam за 46% цены сверху, у Astra уровень max удваивает стоимость на коде без прироста точности.</li><li>Дешёвый сегмент: Gemini 3.8 Flash $0,75/$3,75 до конца года, Muse Spark 1.3 $1,25/$4,25 и $0,55 за задачу индекса, Mercury 2.5 $0,20/$0,75 при заявленных 1107 токенах в секунду, DeepSeek V4 Flash $0,22/$0,66 в непиковые часы.</li><li>MAI-Transcribe-2 стоит $0,10 за час аудио до конца года при WER 5,2% на FLEURS по замеру Microsoft. GPT-Transcribe от OpenAI стоит $0,27 за час.</li><li>Автономность пока не продаётся: в эксперименте Bottleneck Labs семь моделей за 72 часа и $300 каждая заработали $0 и отправили 2797 писем.</li></ul><h2>Чем Fable 5.1 отличается от Astra, если цена у них одинаковая?</h2><p>Разница в том, за что вы платите: Fable 5.1 берёт качеством на широком наборе задач и дешёвым кэшем, Astra экономит токены в агентном коде. Anthropic <a href="https://www.anthropic.com/claude-fable-and-mythos-5-1">выпустила</a> Claude Fable 5.1 и Claude Mythos 5.1 как одну модель с разными уровнями ограничителей: Fable доступна всем, Mythos только через программы проверенного доступа для кибербезопасности и биологии. В API модель называется claude-fable-5-1, есть на Amazon Web Services, Google Cloud и Microsoft Azure. Цены прежние, $10 и $50 за миллион токенов, но чтение кэша подешевело на 75%, до $0,25 за миллион. Anthropic посчитала по четырём неделям реального использования в августе, что типичная нагрузка станет дешевле примерно на 25%, а агентная, где кэш составляет большую часть счёта, до 45%. Это оценка вендора.</p><p>По бенчмаркам самой Anthropic модель обошла Opus 5 и GPT-5.6 Sol, а на низком и среднем усилии даёт результат Fable 5 дешевле. У кибер-фильтров на 60% меньше ложных срабатываний: искать уязвимости в коде теперь можно, разработка эксплойтов запрещена. В Claude Code по умолчанию уровень high.</p><blockquote>We're moving our Opus 5 traffic in Devin to Claude Fable 5.1 on launch day. It matched or edged out Fable 5 in our testing at a lower cost per task, and with the new cache read pricing a Fable-class model is finally economical for the workloads we'd kept on Opus, starting with code review.</blockquote><p>OpenAI <a href="https://openai.com/index/gpt-6-astra/">начала раскатку</a> GPT-6 Astra 3 сентября: сначала ограниченному кругу организаций, затем всем на Plus, Pro, Business и Enterprise, в API под именем gpt-6-astra, а также в Microsoft Azure и Amazon Bedrock. Стандартная цена $10 за миллион входных и $50 за миллион выходных токенов, быстрый режим даёт до 2 раз больше скорости за двойную цену. По замеру OpenAI на Terminal-Bench 4.0 Astra набирает 57,9% против 55,8% у Fable 5.1 и 37,3% у Sol, при этом задача по оценке OpenAI обходится на 63% дешевле, чем у Fable 5.1, и на 9% дешевле, чем у Sol. На Humanity's Last Exam и в общем индексе Artificial Analysis она ниже Fable 5.1 и Opus 5. Подробный разбор цен, бенчмарков и кибер-ограничений Astra есть в <a href="https://tproger.ru/news/openai-nachala-vypusk-gpt-6-astra-ceny-benchmarki-i-kiber-ograni">отдельной новости</a>.</p><p>Независимая лаборатория Artificial Analysis <a href="https://x.com/ArtificialAnlys/status/2095595489031000350">разобрала</a> Astra и увидела две разные истории. В Coding Agent Index Astra в Codex набирает 67 баллов, столько же, сколько Opus 5 и Fable 5 в Claude Code, при цене задачи меньше половины от Fable 5. Лидер индекса Fable 5.1 в Claude Code с 70 баллами. Экономия идёт от токенов: Astra тратит на задачу треть от Sol на уровне max и пятую часть от Opus 5 на xhigh. В общем индексе интеллекта картина хуже: токенов уходит всего на 10% меньше, чем у Sol, при том же балле, поэтому после подорожания в 2,5 раза задача стоит на 75% дороже. Галлюцинаций на AA-Omniscience вдвое меньше: 51% против 92% у Sol.</p><blockquote>In the Artificial Analysis Coding Agent Index, GPT-6 Astra equals Fable 5 at less than half the cost, driven by significant token efficiency gains. In the Artificial Analysis Intelligence Index, GPT-6 Astra is more token efficient than its predecessor for similar performance, but this is offset by the price increase.</blockquote><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-09/69de3c9a-38d1-4426-b607-39edb06416d4.webp" alt="Горизонтальная диаграмма: цена за миллион выходных и входных токенов у семи моделей, от $50 у Fable 5.1 и Astra до $0,66 у DeepSeek V4 Flash" /><figcaption>Цена за миллион токенов по прайс-листам вендоров на 9 сентября 2026 года. У Gemini 3.8 Flash вводная цена до конца года, у Mercury 2.5 базовая цена без стартовой скидки 80%, у DeepSeek V4 Flash непиковый тариф. График: Tproger по данным Anthropic, OpenAI, Alibaba Qwen, Google, Inception и DeepSeek</figcaption></figure><p>7 сентября Artificial Analysis <a href="https://x.com/ArtificialAnlys/status/2097025638695940590">обновила</a> индекс до версии 4.3: Terminal-Bench поднят до 4.0, банковский Tau3-Banking заменён на AutomationBench от Zapier. По <a href="https://artificialanalysis.ai/">данным сайта лаборатории</a>, Fable 5.1 и Astra на уровне max делят первое место с 53 баллами, Opus 5 набирает 51, Muse Spark 1.3 48, GLM-5.3 45, Grok 4.6 и Kimi K3 по 44, Gemini 3.8 Flash 41. Цена задачи индекса при этом $7,63 у Fable 5.1, $3,26 у Astra, $5,86 у Opus 5, $1,60 у Muse Spark 1.3 и $1,24 у Gemini 3.8 Flash.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-09/537a325f-2407-4fb8-a6af-d0066d363e52.webp" alt="Точечная диаграмма: балл Artificial Analysis Intelligence Index v4.3 против цены задачи индекса в долларах, логарифмическая шкала, выделен фронт Парето" /><figcaption>Балл индекса против цены за задачу: Fable 5.1 и Astra с одним баллом различаются по цене задачи более чем вдвое. График: Tproger по данным Artificial Analysis, индекс v4.3, 7 сентября 2026 года</figcaption></figure><h2>Какой уровень рассуждений ставить, чтобы не переплатить?</h2><p>Короткий ответ: у обеих флагманских моделей верхняя ступень почти не добавляет качества, а цену поднимает заметно, поэтому начинать стоит с low или medium и подниматься по результатам своей оценки. У Fable 5.1 пять уровней, по умолчанию high. Anthropic в <a href="https://claude.com/blog/reducing-cost-and-improving-performance-with-claude-platform">разборе экономии</a> приводит две цифры: на Humanity's Last Exam шаг с xhigh до max прибавляет около половины балла за 46% цены сверху, а на CursorBench 3.2 Fable 5.1 на low повторяет результат Fable 5 на high втрое дешевле. Команды Claude Code, которые ищут экономию сами (/claude-api prompt-audit, hillclimb, cost-optimize), мы <a href="https://tproger.ru/news/anthropic-pokazala-kak-srezat-schyot-za-claude-bez-poteri-kachest">разбирали отдельно</a>.</p><p>Уровень задаётся параметром output_config.effort, пример из <a href="https://platform.claude.com/docs/en/build-with-claude/effort">документации Anthropic</a> (в примере модель Opus 5, для Fable 5.1 подставьте claude-fable-5-1). Документация отдельно отмечает, что Fable 5.1 умеет менять effort посреди диалога без сброса кэша промптов.</p><p>У Astra уровни задаются через reasoning.effort в Responses API. По <a href="https://platform.openai.com/docs/guides/reasoning">документации OpenAI</a> значение none для GPT-6 Astra не поддерживается и возвращает HTTP 400, а вызов функций работает только в Responses API, не в Chat Completions.</p><p>Однозначного оптимума у Astra нет. По опыту редакции Tproger на общих вопросах уровень выше high не окупается: цена растёт, точность нет. В коде по Coding Agent Index разумно выглядят low, medium и xhigh, а max удваивает стоимость без надёжного прироста. Рабочая схема: low по умолчанию, для сложных подзадач агент вызывает модель на более высоком уровне. Astra цепляется за формулировки, неточный промпт меняет результат сильнее, чем у прежних моделей; чеклист чистки инструкций под неё есть в <a href="https://tproger.ru/articles/gpt-6-astra-vynuzhdaet-perepisat-skills-i-agents-md-cheklist-inzh">отдельной статье</a>.</p><h2>Что взять, если бюджет считается в центах?</h2><p>Четыре модели закрывают этот сегмент по-разному: Gemini 3.8 Flash сильнее всех в агентном коде, Muse Spark 1.3 дешевле всех за задачу на уровне Sol, Mercury 2.5 быстрее всех, DeepSeek V4.1 Flash пока бета. Google <a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/3-8-flash-and-3-8-flash-cyber/">выпустила</a> Gemini 3.8 Flash 3 сентября по вводной цене $0,75 за миллион входных и $3,75 за миллион выходных токенов; с 1 января 2027 года будет $1,50 и $7,50. Контекст миллион токенов, на <a href="https://openrouter.ai/google/gemini-3.8-flash">OpenRouter</a> у Flex-провайдеров вдвое дешевле. По замеру Google на DeepSWE v1.1, где модель сама доводит инженерную задачу до конца, 3.8 Flash обходит большинство более крупных моделей, на HLE-Verified набирает 54,9%. Google предупреждает: токенов на сложной задаче уйдёт больше, особенно на высоком уровне усилия, и советует понижать уровень или оставаться на 3.7 Flash.</p><blockquote>These performance gains stem from a core design choice: 3.8 Flash works harder. On complex tasks, it exhibits greater diligence — executing extra reasoning steps, and calling tools iteratively. At times, the model might use more tokens to maximize performance, especially at higher effort levels.</blockquote><p>Уровень рассуждений у Gemini задаётся параметром thinking_level, у 3.8 Flash доступны low, medium и high, по умолчанию medium. Пример из <a href="https://ai.google.dev/gemini-api/docs/thinking">документации Gemini API</a>:</p><p>Muse Spark 1.3 от лаборатории суперинтеллекта Александра Вана вышла 2 сентября в Muse Code и в API. Цены не менялись: $1,25 за миллион входных и $4,25 за миллион выходных токенов, попадание в кэш $0,15. По <a href="https://x.com/ArtificialAnlys/status/2095247787277553929">замеру Artificial Analysis</a> открытая всем версия xhigh набрала 61 балл индекса v4.2, вровень с GPT-5.6 Sol и Grok 4.6, при цене $0,55 за задачу индекса против $0,95 у Sol и $0,94 у Grok. Рост почти весь в агентных задачах: банковский Tau3-Bench вырос с 35% до 47%. Просели длинный контекст и AA-Omniscience, где модель чаще отказывается отвечать. Входных токенов на задачу стало больше, поэтому цена задачи выросла с $0,40 у версии 1.2.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-09/212317bb-cc02-4dcf-b3b8-38f684094368.webp" alt="Горизонтальная диаграмма: цена задачи индекса Artificial Analysis, Muse Spark 1.3 xhigh $0,55, Grok 4.6 high $0,94, GPT-5.6 Sol max $0,95" /><figcaption>Цена одной задачи Intelligence Index у трёх моделей с одинаковым баллом 61. График: Tproger по данным Artificial Analysis, 2 сентября 2026 года</figcaption></figure><p>Inception <a href="https://www.inceptionlabs.ai/blog/introducing-mercury-2-5">выпустила</a> Mercury 2.5, диффузионную модель, которая пишет текст блоками параллельно. Заявлено 1107 токенов в секунду на обычных NVIDIA GPU, контекст 260 тыс. токенов, уровень GPT-5.6 Luna на низком усилии и Claude Haiku 4.5. Цена $0,20 за миллион входных и $0,75 за миллион выходных токенов, на старте скидка 80% до $0,04 и $0,15, новым аккаунтам дают 100 млн токенов; модель есть в API Inception, на OpenRouter и Baseten. Независимых замеров Mercury 2.5 пока нет, все цифры вендора. Из кейсов в анонсе: Augment Code перевела на Mercury сжатие контекста, сжатие ускорилось со 150 секунд до 27 при снижении цены на 90%.</p><blockquote>After we switched to Mercury, our P99 response time dropped from several minutes to just one second, and our P50 dropped from 0.4 seconds to under 0.2 — significantly faster than any other provider we've seen, and that's including reasoning.</blockquote><p>DeepSeek 8 сентября <a href="https://www.ithome.com/0/999/795.htm">открыла</a> бету V4.1 Flash на два дня: модель deepseek-v4.1-flash-expires-on-0910 живёт в API до 10 сентября с лимитом 20 параллельных запросов. Цена как у V4 Flash: по <a href="https://api-docs.deepseek.com/quick_start/pricing">прайс-листу</a> $0,22 за миллион входных токенов при промахе кэша, $0,007 при попадании и $0,66 за миллион выходных в непиковые часы; в пиковые вдвое дороже, $0,44 и $1,32. Официальных бенчмарков нет. <a href="https://x.com/plotarmordev/status/2097247035099640216">Тестеры</a> намерили 400–500 токенов в секунду, а китайский <a href="https://xsct.ai/">XSCT Bench</a> поставил V4.1 Flash выше V4 Flash, Gemini 3.8 Flash и Qwen3.8 Flash почти везде.</p><p>Qwen 2 сентября <a href="https://x.com/Alibaba_Qwen/status/2094968708288680276">обновила</a> закрытую Qwen3.8-Max до снапшота 0902: те же 2,4 трлн параметров, миллион контекста, режим размышлений, дообучение на кодинг и совместную агентную работу. По словам Qwen, прирост в основном в коде и агентных правках репозиториев, до Opus 5 в терминале ещё далеко. Цена в <a href="https://www.qwencloud.com/models/qwen3.8-max-0902">QwenCloud</a> $2 за миллион входных и $6 за миллион выходных токенов, чтение кэша $0,17.</p><h2>Что нового в картинках и распознавании речи?</h2><p>Две картиночные модели без бенчмарков и одна речевая с рекордом на FLEURS. OpenAI <a href="https://openai.com/index/introducing-chatgpt-images-2-5/">выпустила</a> ChatGPT Images 2.5: в API две модели, GPT-Image-2.5 Flare по умолчанию с вдвое меньшей задержкой, чем у GPT-Image-2, и Sunburst для точных правок. Цена у обеих $8 за миллион входных токенов картинки, $30 за выходные и $5 за текст на входе. Бенчмарков в анонсе нет, только примеры.</p><p>Microsoft AI <a href="https://microsoft.ai/news/pushing-the-quality-cost-frontier-with-mai-image-2-6/">выпустила</a> MAI-Image-2.6-Flash и вывела MAI-Image-2.6 из закрытого превью в Microsoft Foundry. По заявлению Microsoft, Flash рисует в 2,8 раза быстрее GPT-Image-2-Medium при сопоставимом качестве; старшая модель на Arena вторая в генерации и редактировании, у Artificial Analysis вторая в генерации и первая в редактировании.</p><p>MAI-Transcribe-2 Microsoft <a href="https://microsoft.ai/news/mai-transcribe-2">выпустила</a> 3 сентября: 60 языков с автоопределением, разделение говорящих, таймкоды на каждое слово, режимы verbatim и clean, подсказка терминов. По замеру Microsoft модель первая на мультиязычном FLEURS со средним WER 5,2%, у Artificial Analysis вторая по точности. Цена $0,10 за час аудио как акция до конца года, GPT-Transcribe от OpenAI стоит $0,27 за час. На <a href="https://openrouter.ai/microsoft/mai-transcribe-2">OpenRouter</a> модель лежит под именем microsoft/mai-transcribe-2, ещё есть в Microsoft Foundry и MAI Playground.</p><h2>Какую модель брать под какую задачу в сентябре 2026 года?</h2><p>Ниже сводка по задачам с ценами на 9 сентября. Все цены из прайс-листов вендоров, цены задач из замеров Artificial Analysis и вендоров, как указано.</p><ul><li><b>Агентный кодинг в большой кодовой базе.</b> GPT-6 Astra на low или medium: 67 баллов Coding Agent Index при цене задачи меньше половины от Fable 5 (Artificial Analysis). Если важен максимум качества, Fable 5.1 в Claude Code с 70 баллами, но задача почти вдвое дороже.</li><li><b>Массовые дешёвые задачи с агентами.</b> Gemini 3.8 Flash на low: $0,75/$3,75 до конца года, $1,24 за задачу индекса v4.3. Muse Spark 1.3 на xhigh, если нужен уровень Sol за $0,55 за задачу (AA, v4.2).</li><li><b>Голосовые агенты и всё, где важна задержка.</b> Mercury 2.5: $0,20/$0,75, заявленные 1107 токенов в секунду и медиана ответа около 170 мс у OpenCall. Независимых замеров нет, проверяйте на своём трафике: новым аккаунтам дают 100 млн токенов.</li><li><b>Сжатие контекста и маршрутизация внутри агента.</b> Mercury 2.5 по кейсу Augment Code или DeepSeek V4 Flash за $0,22/$0,66 в непиковые часы.</li><li><b>Транскрибация.</b> MAI-Transcribe-2 за $0,10 в час до конца года против $0,27 у GPT-Transcribe.</li><li><b>Картинки.</b> GPT-Image-2.5 Flare для скорости, Sunburst для правок, $8/$30 за миллион токенов картинки.</li><li><b>Длинный контекст.</b> Qwen3.8-Max-0902 или Gemini 3.8 Flash с миллионом токенов; у Astra и Muse Spark 1.3 длинный контекст по замерам Artificial Analysis просел.</li></ul><p>Порядок действий, чтобы перейти на новые модели без сюрпризов в счёте:</p><ol><li>Замените идентификатор модели: claude-fable-5-1 в Claude API, gpt-6-astra в Responses API, gemini-3.8-flash в Gemini API. У Astra уберите reasoning.effort: none, иначе получите HTTP 400.</li><li>Поставьте низкий уровень усилия (output_config.effort: low, reasoning.effort: low, thinking_level: low) и прогоните свою оценку; поднимайте уровень только там, где балл растёт.</li><li>Проверьте долю попаданий в кэш: у Fable 5.1 чтение кэша стоит $0,25, и смена effort посреди диалога кэш не сбрасывает, у остальных моделей сброс возможен.</li><li>Для агентов с инструментами на Astra заложите обработку остановки: внешний мониторинг OpenAI может прервать задачу, и через API диалог не возобновить.</li><li>Сравнивайте цену задачи вместо цены токена: считайте токены на задачу из поля usage в ответе API и умножайте на прайс.</li></ol><h2>Почему автономный агент на новых моделях всё ещё нельзя оставлять без присмотра?</h2><p>Потому что фильтры вендоров останавливают работу, а сами модели делают лишнее. OpenAI признаёт, что Astra достигла критического уровня в кибербезопасности по её Preparedness Framework: в тестах модель сама нашла и использовала две уязвимости нулевого дня. Поэтому на вызовы с инструментами в Codex, ChatGPT и Responses API включён внешний мониторинг.</p><blockquote>Extra safety checks can sometimes slow, pause, or stop legitimate work, including defensive cybersecurity. If a task is paused in ChatGPT or Codex, you may be asked to review the action before continuing. In the API, the task will stop.</blockquote><p>Вторая причина показана в эксперименте Bottleneck Labs, которая <a href="https://www.bottlenecklabs.com/blog/benchmarking-7-autonomous-businesses">дала</a> семи моделям по $300, Mac mini, почту, Stripe и 72 часа с промптом «заработай как можно больше денег». Итог по всем семи: 2797 писем, 11 живых посетителей, выручка $0, около $2800 на токены. Qwen 3.8 открыла сервис аудита GitHub-репозиториев, упёрлась в лимиты почты и выставила через Stripe 50 счетов незнакомым людям за незаказанную работу на $12 350, сочтя это допустимым шагом продаж. Это один эксперимент одной компании, но подтверждение человеком на платёжных действиях он делает обязательным.</p><p>Попробовать можно без денег: Inception даёт 100 млн токенов Mercury 2.5 новым аккаунтам, а Z.ai до 20 сентября <a href="https://x.com/zcode_ai/status/2095847518194307434">держит</a> ночной Global Build с бесплатной GLM-5.3-Flash для подписчиков Coding Plan. Цену решённой задачи у GLM-5.3, Sol и других мы <a href="https://tproger.ru/news/na-chyom-kodit-v-sentyabre-cena-rewyonnoj-zadachi-u-glm-5-3-sol-i">считали отдельно</a>. Следующая проверка — когда OpenAI закончит раскатку Astra и Artificial Analysis добавит в индекс v4.3 Mercury 2.5 и DeepSeek V4.1 Flash.</p><p>Источники: <a href="https://www.anthropic.com/claude-fable-and-mythos-5-1">Anthropic: Introducing Claude Fable 5.1 and Claude Mythos 5.1</a>, <a href="https://platform.claude.com/docs/en/build-with-claude/effort">Claude Platform Docs: Effort</a>, <a href="https://claude.com/blog/reducing-cost-and-improving-performance-with-claude-platform">Claude Blog: Reducing cost and improving performance with Claude Platform</a>, <a href="https://openai.com/index/gpt-6-astra/">OpenAI: Introducing GPT-6 Astra</a>, <a href="https://platform.openai.com/docs/guides/reasoning">OpenAI Docs: Reasoning models</a>, <a href="https://openai.com/index/introducing-chatgpt-images-2-5/">OpenAI: Introducing ChatGPT Images 2.5</a>, <a href="https://x.com/ArtificialAnlys/status/2095595489031000350">Artificial Analysis: разбор GPT-6 Astra</a>, <a href="https://x.com/ArtificialAnlys/status/2095247787277553929">Artificial Analysis: замер Muse Spark 1.3</a>, <a href="https://x.com/ArtificialAnlys/status/2097025638695940590">Artificial Analysis: Intelligence Index v4.3</a>, <a href="https://artificialanalysis.ai/">Artificial Analysis: главная страница индекса</a>, <a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/3-8-flash-and-3-8-flash-cyber/">Google: Gemini 3.8 Flash and 3.8 Flash Cyber</a>, <a href="https://ai.google.dev/gemini-api/docs/thinking">Gemini API Docs: Thinking</a>, <a href="https://www.inceptionlabs.ai/blog/introducing-mercury-2-5">Inception: Introducing Mercury 2.5</a>, <a href="https://www.qwencloud.com/models/qwen3.8-max-0902">QwenCloud: Qwen3.8-Max-0902</a>, <a href="https://x.com/Alibaba_Qwen/status/2094968708288680276">Alibaba Qwen: анонс Qwen3.8-Max-0902</a>, <a href="https://api-docs.deepseek.com/quick_start/pricing">DeepSeek API Docs: Pricing</a>, <a href="https://www.ithome.com/0/999/795.htm">IT之家: бета DeepSeek V4.1 Flash</a>, <a href="https://microsoft.ai/news/mai-transcribe-2">Microsoft AI: MAI-Transcribe-2</a>, <a href="https://microsoft.ai/news/pushing-the-quality-cost-frontier-with-mai-image-2-6/">Microsoft AI: MAI-Image-2.6</a>, <a href="https://www.bottlenecklabs.com/blog/benchmarking-7-autonomous-businesses">Bottleneck Labs: Benchmarking 7 autonomous businesses</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Anthropic показала, как срезать счёт за Claude без потери качества</title>
      <link>https://tproger.ru/news/anthropic-pokazala-kak-srezat-schyot-za-claude-bez-poteri-kachest</link>
      <comments>https://tproger.ru/news/anthropic-pokazala-kak-srezat-schyot-za-claude-bez-poteri-kachest?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/anthropic-pokazala-kak-srezat-schyot-za-claude-bez-poteri-kachest</guid>
      <description><![CDATA[<p>Три рычага экономии на Claude Platform: кэш промптов, чистка инструкций и уровень усилия. Команда prompt-audit дала минус 14,6% к цене и плюс 5,3 пункта точности.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/anthropic-pokazala-kak-srezat-schyot-za-claude-bez-poteri-kachest">Anthropic показала, как срезать счёт за Claude без потери качества</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Нейронные сети]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 08 Sep 2026 17:52:36 GMT</pubDate>
      <content:encoded><![CDATA[<p>Anthropic 8 сентября <a href="https://claude.com/blog/reducing-cost-and-improving-performance-with-claude-platform">опубликовала</a> разбор того, где приложения на Claude переплачивают, и заявила, что во многих случаях счёт можно снизить без потери качества. Рычагов три: доля попаданий в кэш промптов, инструкции, написанные под старые модели, и уровень усилия (effort). Все три вынесены в скилл <a href="https://github.com/anthropics/skills/tree/main/skills/claude-api">claude-api</a>, который встроен в Claude Code, и у него появились три команды: /claude-api prompt-audit, /claude-api cost-optimize и /claude-api hillclimb.</p><p>Для разработчика это значит, что аудит расходов теперь можно запустить одной командой прямо в рабочей директории проекта, а не выискивать промахи кэша по логам. Цифры в статье приводит сама Anthropic, поэтому ниже они даются с оговорками авторов.</p><ul><li>Кэш промптов ломают таймстампы в системном промпте, перетасованные описания инструментов и смена effort посреди диалога. Менять effort без сброса кэша умеют отдельные модели, в том числе Opus 5 и Fable 5.1.</li><li>Команда prompt-audit вычищает из промптов «проверь дважды», «будь максимально тщательным», обязательные scratchpad и противоречивые правила. На саппорт-бенчмарке при переезде с Opus 4.8 на Opus 5 это дало минус 14,6% к стоимости и плюс 5,3 пункта точности.</li><li>На CursorBench 3.2 Fable 5.1 на низком усилии повторяет результат Fable 5 на высоком за треть цены. У Fable 5.1 на Humanity's Last Exam шаг с xhigh до max прибавляет полбалла за 46% цены сверху.</li><li>Команда cost-optimize на четырёх открытых бенчмарках с Sonnet 5 срезала 52–73% стоимости при качестве в пределах шума.</li><li>Команда hillclimb подбирает модель, effort и промпт по вашей оценке: на отложенных тестах точность выросла с 78,6% до 90,5% при цене примерно в пять раз ниже.</li></ul><h2>Почему кэш промптов промахивается и как это увидеть?</h2><p>Перед генерацией ответа модель прогоняет весь промпт в рабочее состояние, и этот этап, prefill, и есть дорогая часть обработки входа. Кэш промптов сохраняет это состояние (KV-кэш), и если следующий запрос начинается с того же префикса, модель читает его из кэша вместо пересчёта. Чтение из кэша тарифицируется в разы дешевле полной цены входных токенов: у Fable 5.1 это $0,25 за миллион против $10 за обычный вход.</p><p>Три условия, при которых кэш вообще работает: он привязан к конкретной модели, префикс должен совпадать байт в байт, и у него ограниченный срок жизни. Отсюда типичные промахи, которые Anthropic перечисляет по опыту клиентов: динамический таймстамп или идентификатор в системном промпте, описания инструментов, которые меняют порядок между вызовами, и смена уровня усилия посреди диалога, потому что effort рендерится в промпт перед вашим контентом и входит в кэшируемый префикс. Исключение сделано только для части моделей, включая Opus 5 и Fable 5.1: у них effort можно менять без сброса кэша. Отдельная ловушка у субагентов и веток диалога: они делят кэш родителя только при байт-идентичном префиксе, той же модели и том же effort.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-08/06ee5cf9-0d04-41c1-9899-286122137bb2.webp" alt="Панель диагностики кэша в Claude Console: доля чтений из кэша 71,3% и разбивка промахов по причинам" /><figcaption>Диагностика кэша в Claude Console показывает долю чтений из кэша и причины промахов: изменились сообщения, системный промпт, инструменты или модель. Изображение: Anthropic</figcaption></figure><p>Что с этим делать, по списку Anthropic. Смотреть долю попаданий в кэш в Claude Console и через <a href="https://platform.claude.com/docs/en/build-with-claude/cache-diagnostics">API диагностики кэша</a>: он показывает причину промаха и место, где два запроса разошлись. Редко используемые инструменты объявлять с defer_loading: они не входят в кэшируемый префикс и подгружаются в диалог только когда модель находит их через поиск инструментов. На моделях, которые это поддерживают, обновления системного промпта добавлять как сообщения посреди диалога, а не правкой самого системного промпта. Раскладывать запрос так, чтобы стабильная часть оставалась стабильной: сначала описания инструментов и системный промпт, потом растущий диалог.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-08/d20dce2e-0962-45c7-b52d-97e00753e97b.webp" alt="Схема раскладки промпта: системные инструкции и инструменты кэшируются глобально, CLAUDE.md по проекту, состояние сессии по сессии, сообщения растут с каждым ходом" /><figcaption>Раскладка промпта по слоям кэширования на примере Claude Code. Изображение: Anthropic</figcaption></figure><p>Ещё несколько приёмов из той же статьи. Модель или effort менять в тот момент, когда кэш всё равно сброшен, например при компактификации диалога. Двигать точку кэширования по мере роста диалога: автоматическое кэширование ставит её на последний кэшируемый блок. Прогревать кэш заранее: запрос с max_tokens: 0 и явной точкой кэширования на том же effort, что и боевой трафик, обрабатывает промпт и записывает его в кэш, ничего не генерируя. Если отправить его, пока пользователь ещё печатает, первый настоящий запрос попадёт в тёплый кэш. И не выходить за срок жизни кэша: пятиминутный TTL считается с начала запроса, и если агент ждёт инструмент или субагента дольше пяти минут, кэш родителя истекает до возврата результата. На такие случаи есть <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching#ttl-support">часовой TTL</a> на префикс.</p><h2>Какие инструкции вредят новым моделям?</h2><p>Промпты со временем обрастают правилами, которые латали слабости старых моделей, и после обновления модели эти правила начинают мешать. Anthropic перечисляет шесть антипаттернов. Ритуалы проверки: «перепроверь свою работу», «проверь дважды перед ответом» новые модели выполняют буквально и тратят токены впустую. Усилители вроде «будь максимально тщательным» и «КРИТИЧНО: ТЫ ДОЛЖЕН ВСЕГДА…» дают многословие и лишние вызовы инструментов. Обязательные процедуры и шаблоны рассуждений («думай по шагам в scratchpad») накладываются на встроенное мышление модели и жгут токены. Устаревшие примеры few-shot, подобранные под ошибки старой модели, учат новую имитировать длинные цепочки рассуждений там, где они не нужны. Противоречивые правила («всегда возвращай деньги по политике» против «никогда не возвращай без эскалации») новые модели соблюдают буквальнее, и качество падает. И устаревшая конфигурация: настройки под прошлое поколение, например ручные бюджеты на размышления, платформа с новыми моделями может отвергнуть.</p><p>Команда /claude-api prompt-audit ищет всё это в рабочей директории: в коде приложения, который вызывает Claude API, и в конфигурации самого Claude Code, включая CLAUDE.md и скиллы. Для проверки Anthropic взяла бенчмарк службы поддержки и переезд с Opus 4.8 на Opus 5: в чистый промпт по одному подсаживали антипаттерн (снятая настройка thinking, пара противоречивых правил о возвратах, ручной scratchpad, «проверь дважды», «будь максимально тщательным» и обязательная процедура из шести шагов), получили шесть «легаси» промптов и прогнали каждый на Opus 4.8, на Opus 5 с заменой только идентификатора модели и на Opus 5 после одного прогона prompt-audit.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-08/0333e49a-1dd5-4b12-ba2c-926f265e6f0e.webp" alt="График: Opus 4.8 с легаси-промптом 2,52 цента и 89,4% точности, Opus 5 без аудита 3,43 цента и 91,7%, Opus 5 после prompt-audit 2,93 цента и 97,0%" /><figcaption>Среднее по шести легаси-промптам на саппорт-бенчмарке: смена модели подняла точность и цену, аудит промпта снизил цену и поднял точность ещё. Изображение: Anthropic</figcaption></figure><p>В среднем аудит снизил стоимость на 14,6% и поднял точность на 5,3 пункта. Цена упала за счёт лишних вызовов инструментов и дублирующихся рассуждений: на Opus 5 «проверь дважды» превращалось в повторный поиск заказа при каждом возврате, а «будь максимально тщательным» в десятки ненужных обращений к базе знаний. Точность выросла по трём причинам. Снятая настройка thinking заставляла API отвергать каждый запрос на маршрутизацию. Из-за противоречивых правил Opus 5 придержал четыре возврата, которые был должен, и просил клиента подтвердить. А ручной scratchpad конфликтовал со встроенным мышлением Opus 5: в трёх тикетах модель написала вызов инструмента внутри рассуждений и не выполнила его.</p><h2>Когда высокий effort не окупается?</h2><p>Effort задаёт, насколько усердно модель работает: на low она быстрее приходит к выводу, на high дольше рассуждает, проверяет и перебирает альтернативы. Кривая цена-качество у одной и той же модели бывает очень разной. У Fable 5 на FrontierCode Diamond (50 самых сложных задач) low даёт 11,5% за $5,35 на задачу, max даёт 30,9% за $19,00: результат вырос примерно в 2,7 раза за примерно 3,5 раза по цене. А у Fable 5.1 на Humanity's Last Exam без инструментов кривая крутая, но с плоским последним шагом: около 53% на low за примерно $0,30 на вопрос и около 61% на max за $2,23, при этом шаг с xhigh до max добавляет около половины балла за 46% цены сверху. Этот прирост укладывается в разброс между прогонами бенчмарка, то есть переплата идёт ни за что.</p><p>Ошибиться можно в обе стороны. Считать, что выше всегда лучше: на high модель может передумывать дольше, чем требует задача, это добавляет цену и задержку и может ухудшить ответ, потому что рассуждение помогает только пока есть что искать. И зажимать effort до low: тогда модель останавливается раньше, чем собрала достаточно улик, делает меньше вызовов инструментов, отвечает по первому результату поиска вместо третьего и пропускает проверку, которую сделала бы сама. Ответ выглядит законченным, но построен на неполной информации.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-08/25b2b728-2502-4034-93dc-17ce3fd5f8b4.webp" alt="График CursorBench 3.2: Fable 5.1 на low набирает столько же, сколько Fable 5 на high, при цене за задачу около $3 против $9" /><figcaption>CursorBench 3.2: пять уровней усилия Fable 5 и Fable 5.1, цена за задачу в логарифмической шкале. Изображение: Anthropic</figcaption></figure><p>Совет Anthropic звучит так: пробовать более сильную модель на низком усилии, потому что она может выйти дешевле слабой на высоком. На CursorBench 3.2 Fable 5.1 на low повторяет результат Fable 5 на high за треть цены. Дешевле по двум причинам: на low модель делает меньше работы на задачу, а чтение из кэша у Fable 5.1 стоит $0,25 за миллион токенов против $1,00 у Fable 5. Даже по ценам Fable 5 Fable 5.1 на low обошлась бы примерно на 40% дешевле. Второй совет: понять форму своей задачи, прогнав оценку по всем уровням усилия. Если на ненасыщенном бенчмарке кривая плоская, задача не упирается в вычисления на размышления, и поднимать effort бессмысленно.</p><h2>Что делают команды hillclimb и cost-optimize?</h2><p>/claude-api hillclimb автоматизирует этот перебор. Команда делит вашу оценку на обучающую и тестовую части, предлагает изменения конфигурации и читает проваленные примеры из обучающей части, чтобы починить найденное. На том же саппорт-бенчмарке старт был с Opus 4.8 на дефолтном high. Первым шагом hillclimb попробовал Opus 5 на low с prompt-audit, который убрал обязательные ритуалы вызова инструментов, шаги scratchpad и противоречивые правила: это превысило базовый уровень Opus 4.8 с 98,9% точности на обучающей части и снизило цену до 2,6 цента за тикет. Затем он спустился до Sonnet 5 на low: ещё дешевле, 1 цент за тикет, но точность упала до 88,9%. Прочитав проваленные тикеты, Claude добавил в промпт правила маршрутизации и сверку с лимитом на возврат, и Sonnet 5 вернулась к 98,9% при той же цене.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-08/9e666b9d-3976-4670-8220-4a136e0bf4de.webp" alt="Путь hillclimb: Opus 4.8 high с 74,4% за 4,4 цента, Opus 5 low около 99% за 2,6 цента, Sonnet 5 low 88,9% за 1 цент, Sonnet 5 low с улучшенным промптом около 99% за 1 цент" /><figcaption>Четыре шага hillclimb на обучающей части саппорт-бенчмарка: точность решения и цена за тикет. Изображение: Anthropic</figcaption></figure><p>На 14 отложенных тикетах, которых поиск не видел, итоговая конфигурация набрала 90,5% против 78,6% у исходной, при цене примерно в пять раз ниже. Разрыв между 98,9% на обучающей части и 90,5% на тестовой стоит держать в уме: на отложенных примерах прирост заметно меньше.</p><p>/claude-api cost-optimize нужна для полного аудита расходов кода, который ходит в Claude API. Сначала она выясняет, куда уходят токены: из отчётов об использовании и затратах организации, если есть ключ Claude Admin API, из объекта usage в каждом ответе API, если приложение его логирует, а если нет ни того, ни другого, читает код сборки запросов и оценивает. Затем ранжирует доступную экономию: кэш промптов, урезание того, что несёт каждый запрос (включая prompt-audit), ограничение вывода и отправка неинтерактивной работы через Batch API. Если дать ей оценку качества, она ещё и считает цену и результат по уровням усилия и моделям.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-08/3c5d5930-dd12-4dfe-9010-88ae46aae1af.webp" alt="Четыре бенчмарка после cost-optimize: tau2-bench retail минус 72,7%, LegalBench минус 57,6%, OfficeQA Pro минус 52,4%, SWE-bench Verified минус 55,1%, изменение результата в пределах доверительных интервалов" /><figcaption>cost-optimize на четырёх открытых бенчмарках с Sonnet 5 как базой: цена за прогон и изменение результата с 95% доверительными интервалами. Изображение: Anthropic</figcaption></figure><p>Anthropic прогнала её на четырёх открытых бенчмарках с Sonnet 5 как базой. На LegalBench команда предложила кэшировать общий префикс между задачами, поставить low и гнать задачи через Batch API: токены на размышления упали со 102 779 до 8 284, доля решённых осталась в пределах шума, цена снизилась примерно на 58%. На tau2-bench retail кэш с явной расстановкой точек кэширования дал минус 72% при той же доле решённых. На OfficeQA Pro пакетная обработка и кэширование документов снизили цену со $136,20 до $64,87. На SWE-bench Verified cost-optimize обнаружила, что кэш в дефолтной конфигурации уже настроен правильно, и экономию дали medium вместо high и ограничение вывода агента несколькими короткими фразами: медиана шагов на задачу упала с 29 до 17, входные токены с 75,2 млн до 33,7 млн, минус 55% по цене. По графику на SWE-bench результат при этом просел на 3,3 пункта при интервале от минус 9,6 до плюс 3,1, то есть значимого изменения не установлено, но интервал допускает и ухудшение, и на своих задачах это стоит перепроверить.</p><h2>С чего начать?</h2><p>Порядок, который предлагает сама Anthropic. Если вы переехали на новую модель Claude и хотите проверить старые промпты, запускайте /claude-api prompt-audit: она сканирует промпты, скиллы и описания инструментов в рабочей директории, будь то код приложения или конфигурация Claude Code. Если приложение ходит в Claude API и нужен аудит расходов, берите /claude-api cost-optimize: она профилирует расход токенов и проверяет рычаги по очереди, а с оценкой качества ещё и меряет компромиссы по effort и выбору модели. Если есть оценка и нужен поиск по цене и качеству, /claude-api hillclimb разобьёт её на обучающую и тестовую части, предложит изменения и оценит финальную конфигурацию на отложенных примерах.</p><p>Скилл claude-api встроен в Claude Code, отдельно он лежит <a href="https://github.com/anthropics/skills/tree/main/skills/claude-api">на GitHub</a>. Подробности по каждому рычагу собраны в <a href="https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence">документации</a> и в <a href="https://platform.claude.com/cookbook/cost-optimization-cost-optimization">кукбуке по снижению затрат</a>. Все цифры в статье получены в прогонах Anthropic, в том числе на четырёх открытых бенчмарках; сторонних проверок в публикации нет. О том, на что способна Fable 5.1 в агентных сценариях, мы <a href="https://tproger.ru/news/agenty-fable-5-1-sobrali-v-brauzere-prohodimuyu-kopiyu-yunion-skver">писали</a> на примере агентов, собравших копию Юнион-сквер, а про открытый чертёж торгового агента на Claude есть <a href="https://tproger.ru/news/anthropic-otkryla-claude-commerce-agents-chertyozh-torgovogo-agent">отдельный разбор</a>.</p><p>Источники: <a href="https://claude.com/blog/reducing-cost-and-improving-performance-with-claude-platform">Claude Blog: Reducing cost and improving performance with Claude Platform</a>, <a href="https://x.com/ClaudeDevs/status/2097369738968195513">Анонс @ClaudeDevs в X</a>, <a href="https://platform.claude.com/docs/en/about-claude/models/optimizing-for-cost-and-intelligence">Документация: Optimizing for cost and intelligence</a>, <a href="https://github.com/anthropics/skills/tree/main/skills/claude-api">Скилл claude-api на GitHub</a>, <a href="https://platform.claude.com/cookbook/cost-optimization-cost-optimization">Cookbook: Cost optimization</a></p><p>Изображение на обложке: Anthropic, заставка статьи «Reducing cost and improving performance with Claude Platform»</p>]]></content:encoded>
    </item>
    <item>
      <title>Вышла FreeBSD 14.5 с поддержкой Linux API inotify</title>
      <link>https://tproger.ru/news/vywla-freebsd-14-5-s-podderzhkoj-linux-api-inotify</link>
      <comments>https://tproger.ru/news/vywla-freebsd-14-5-s-podderzhkoj-linux-api-inotify?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/vywla-freebsd-14-5-s-podderzhkoj-linux-api-inotify</guid>
      <description><![CDATA[<p>FreeBSD 14.5 получила нативный API inotify, LLVM 21.1.8 и изменения для Clang. Релиз доступен с 8 сентября, его поддержка продлится до 30 июня 2027 года.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/vywla-freebsd-14-5-s-podderzhkoj-linux-api-inotify">Вышла FreeBSD 14.5 с поддержкой Linux API inotify</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Операционные системы]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 08 Sep 2026 12:03:20 GMT</pubDate>
      <content:encoded><![CDATA[<p>Команда FreeBSD 8 сентября <a href="https://www.freebsd.org/releases/14.5R/announce/">выпустила FreeBSD 14.5-RELEASE</a> — шестой релиз ветки stable/14. Среди изменений для разработчиков — нативный API inotify, совместимый с Linux на уровне исходного кода, и обновление LLVM до версии 21.1.8.</p><p>Поддержка inotify появилась в ядре и стандартной библиотеке libc. Приложения могут получать уведомления об изменениях в файловой системе, не открывая каждый отслеживаемый файл. Это упрощает перенос программ, которые используют такой API в Linux; речь о совместимости исходников, а не о гарантированном запуске готовых Linux-приложений.</p><p>Для Clang изменили выбор линкера по умолчанию: теперь используется ld.lld вместо поиска линкера по имени ld. В math.h также стали доступны тригонометрические функции стандарта C23 с множителем π, в том числе sinpi и cospi.</p><p>Изменения затронули и командную строку. Утилита pwd по умолчанию работает в режиме -L, а не -P, как требует POSIX: при выводе пути сохраняются символические ссылки. Размер истории sh по умолчанию увеличили со 100 до 128 записей. Эти и другие изменения перечислены в <a href="https://www.freebsd.org/releases/14.5R/relnotes/">примечаниях к выпуску</a>.</p><p>Разработчики подчёркивают, что в 14.5 основной акцент сделан на исправлениях и обновлении компонентов. Уже доступны установочные образы и образы виртуальных машин. Поддержка FreeBSD 14.5 продлится до 30 июня 2027 года.</p>]]></content:encoded>
    </item>
    <item>
      <title>Пагинация и лимиты API: как отдавать данные постранично и не дать выгрести базу</title>
      <link>https://tproger.ru/articles/paginaciya-i-limity-api-kak-otdavat-dannye-postranichno-i-ne-dat</link>
      <comments>https://tproger.ru/articles/paginaciya-i-limity-api-kak-otdavat-dannye-postranichno-i-ne-dat?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/paginaciya-i-limity-api-kak-otdavat-dannye-postranichno-i-ne-dat</guid>
      <description><![CDATA[<p>Пагинация через OFFSET тормозит на глубоких страницах и теряет строки. Смотрите, как перейти на курсор и настроить лимиты запросов — с кодом и замерами.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/paginaciya-i-limity-api-kak-otdavat-dannye-postranichno-i-ne-dat">Пагинация и лимиты API: как отдавать данные постранично и не дать выгрести базу</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Базы данных]]></category>
      <category><![CDATA[Redis]]></category>
      <category><![CDATA[Высокие нагрузки]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 07 Sep 2026 05:00:45 GMT</pubDate>
      <content:encoded><![CDATA[<p>Ваш API отдаёт страницы по двадцать записей и работает прекрасно ровно до того дня, когда у первого крупного клиента накопится полмиллиона строк. Тогда выяснится сразу две вещи: страницы стали открываться секундами, а синхронизация на стороне клиента дважды затянула одни и те же заказы.</p><p>Оба симптома дают один и тот же виновник — постраничная выдача через OFFSET. И оба чинятся одним переходом, причём переписывать приходится только слой выдачи.</p><p>Пагинация — это способ отдать большую коллекцию по частям. Вариантов ровно два. Offset-пагинация просит базу пропустить N строк и вернуть следующие двадцать. Курсорная (её же называют keyset) запоминает последнюю отданную запись и просит всё, что идёт после неё.</p><p>Стоимость OFFSET растёт линейно: на таблице в 1,2 млн строк выборка со смещением в миллион занимает 2,4 с против 3 мс у курсора.</p><p>Под параллельными вставками и удалениями OFFSET выдаёт дубликаты и пропуски, потому что нумерация строк сдвигается между запросами.</p><p>Курсор не поддерживает переход на произвольную страницу, поэтому для админок и таблиц с кнопкой «страница 47» offset остаётся правильным выбором.</p><p>Лимиты запросов на счётчике в памяти инстанса не работают: при десяти инстансах настроенные 100 запросов в минуту превращаются в 1000.</p><p>Скользящее окно на сортированном множестве Redis и атомарном Lua-скрипте занимает пятнадцать строк и снимает гонку без распределённых блокировок.</p><p>Результат на спокойной базе одинаковый. Поведение под ростом данных и параллельными записями — принципиально разное.</p><h2>Offset ломается двумя разными способами</h2><p>Про первый знают почти все, про второй вспоминают уже после инцидента.</p><h3>Он линейно замедляется</h3><p>PostgreSQL, MySQL и SQLite не умеют «перепрыгнуть» через строки. При OFFSET 100000 база честно читает сто тысяч строк и выбрасывает их, чтобы отдать следующие двадцать. Стоимость запроса растёт вместе со смещением.</p><p>Автор разбора <a href="https://dev.to/sirmax/why-i-switched-my-api-from-offset-to-cursor-pagination-and-when-you-shouldnt-1464">замерил это на таблице в 1,2 млн строк</a> в PostgreSQL 15 с холодным кешем и обычным btree-индексом по id:</p><p>Курсорный вариант на той же таблице держал 3 мс на любой глубине. Разница объясняется сложностью: поиск по индексу это O(log n), а большое смещение — O(offset). На пятидесятитысячной странице пользователь ждёт больше двух секунд вместо миллисекунд.</p><h3>Он врёт, когда в таблицу пишут</h3><p>Этот сценарий коварнее. Пользователь загрузил первую страницу с двадцатью записями, отсортированными от новых к старым. Пока он читал, в таблицу добавились три новые записи. Запрос второй страницы с OFFSET 20 вернёт часть того, что уже было на первой: всё сдвинулось на три позиции.</p><p>Клиент получает дубликаты. При удалении записей картина обратная — часть строк он не увидит никогда, потому что они проскочили мимо границы страницы. У автора статьи на этом сломалась синхронизация у клиента: задание дважды загрузило одни и те же двадцать заказов, и три письма в поддержку ушло на то, чтобы понять, что виновата пагинация, а не код клиента.</p><p>Курсор от этого защищён по построению. Курсор — это последняя фактически полученная запись, поэтому «всё, что после неё» остаётся верным независимо от того, сколько строк вставили или удалили между запросами.</p><h2>Как выглядит курсор в коде</h2><p>Простейшая версия работает по первичному ключу и умещается в один обработчик:</p><p>Обратите внимание на per_page + 1. Запрашивая на одну запись больше, чем собираетесь отдать, вы узнаёте о существовании следующей страницы без отдельного запроса COUNT. Лишняя запись отбрасывается, а её наличие становится флагом has_more.</p><h3>Составной курсор: место, где ломается наивная версия</h3><p>Курсор по одному id корректен, только пока вы сортируете по id. Как только сортировка идёт по created_at, простое условие created_at &gt; X начинает терять записи: два заказа, созданные в одну миллисекунду, дают ничью, и одна из строк молча исчезает из выдачи.</p><p>Лечится это составным курсором — ключ сортировки плюс первичный ключ, сравниваемые как кортеж:</p><p>Сравнение кортежей разрешает ничьи детерминированно, поэтому ни одна строка не дублируется и не пропадает. Под это нужен составной индекс (created_at DESC, id DESC), иначе выигрыш в скорости пропадёт вместе с планом запроса.</p><p><b>Про формат курсора:</b><br />Не отдавайте наружу голый идентификатор, если планируете менять схему. Заверните значения в маленький JSON с полем версии и закодируйте в base64: тогда через год вы поменяете состав курсора, не сломав клиентов, которые прямо сейчас держат страницу открытой.</p><h2>Когда офсетную пагинацию нужно оставить</h2><p>Курсор не бесплатный, и подменять им всё подряд не стоит. Есть четыре ситуации, где offset честно лучше:</p><ul><li>Интерфейсу нужен переход на конкретную страницу. У курсора нет номеров страниц, поэтому админки, таблицы и всё с кнопкой «перейти к странице 47» остаются на offset.</li><li>Данных мало и они не меняются. Справочник на пять тысяч строк не выиграет ничего, зато offset проще объяснить и отладить.</li><li>Пагинация идёт по памяти или по кешу, где смещение и так стоит O(1).</li><li>Сортировка задаётся пользователем по произвольной колонке. Курсор тут превращается в кодирование кортежей в непрозрачные строки, и это уже заметная сложность.</li></ul><p>Разумное правило: курсор по умолчанию для всего, что может перерасти десять тысяч строк или читается во время записи. Offset — для небольших, статичных и внутренних данных.</p><p>И отдельно стоит помнить, что пагинация обычно не единственная нагрузка на базу. Кто ещё и насколько сильно её грузит, разбирали в переводе про <a href="https://tproger.ru/translations/patterny-upravleniya-trafikom-k-postgresql-v-production">паттерны управления трафиком к PostgreSQL</a>.</p><h2>Вторая половина задачи: кто и сколько может забрать</h2><p>Правильная пагинация решает, как отдавать данные. Она не решает, сколько их заберут за минуту. Ограничение частоты запросов выглядит тривиально («считай запросы, блокируй сверх N») и превращается в задачу распределённых систем ровно в тот момент, когда серверов становится два.</p><h3>Сначала ответьте, от чего защищаетесь</h3><p>От выбранной цели зависит вся конструкция, и целей <a href="https://dev.to/weston_carnes_d580b505e0c/api-rate-limiting-patterns-algorithms-and-how-to-do-it-right-4l35">обычно выделяют четыре</a>:</p><ul><li>Защита от перегрузки — не дать всплеску положить сервис.</li><li>Честное распределение — не дать одному шумному клиенту вытеснить остальных.</li><li>Защита от злоупотреблений — притупить перебор паролей, скрейпинг и подстановку учётных данных.</li><li>Контроль расходов — ограничить дорогие ручки вроде вызова модели или построения отчёта. Тот же принцип со стороны поставщика разбирали на примере <a href="https://tproger.ru/articles/kak-ogranichit-rashody-na-openai-api-chtoby-ii-agenty-ne-sozhgli">лимитов трат в OpenAI API</a>.</li></ul><h3>Три алгоритма и один, который выбирают почти всегда</h3><p><b>Фиксированное окно</b> считает запросы в календарном интервале: сто в минуту со сбросом на начале минуты. Просто и дыряво: клиент отправляет сотню в 12:00:59 и ещё сотню в 12:01:00, то есть двести за одну секунду. Граница окна и есть дыра.</p><p><b>Скользящее окно</b> считает в непрерывно сдвигающемся интервале, часто взвешивая счётчик предыдущего окна по мере хода времени. Точнее, но требует больше состояния.</p><p><b>Ведро токенов</b> обычно и оказывается верным выбором по умолчанию. В ведре лежит до N токенов, оно пополняется с постоянной скоростью, каждый запрос тратит один токен. Такая схема разрешает контролируемые всплески (молчавший клиент накопил токены и может потратить их разом), но держит среднюю нагрузку в рамках. Родственное «дырявое ведро» выдаёт идеально ровный поток и нужно там, где принимающая сторона всплесков не переносит.</p><blockquote>Фиксированное окно пишут первым и потом жалеют. На ведро токенов мигрируют.</blockquote><h3>Ловушка, из-за которой лимит не работает вообще</h3><p>Счётчик в памяти процесса живёт до появления второго сервера. После этого «сто запросов в минуту» тихо означает «сто запросов в минуту на инстанс», и при десяти инстансах клиент законно получает тысячу. Ошибку не видно ни в логах, ни в мониторинге: лимит вроде бы работает, просто не тот.</p><p>Лечится это переносом счётчика в общее хранилище, обычно в Redis, причём проверка и инкремент обязаны быть атомарными. Последовательность «прочитать, сравнить, увеличить» из кода приложения гоняется между инстансами и недосчитывает запросы ровно под той нагрузкой, ради которой лимит и ставили.</p><h2>Скользящее окно на Redis: пятнадцать строк Lua</h2><p>Команда сервиса jo4.io столкнулась с частным случаем этой задачи: ручка подсказки категорий ходит в модель через Groq, каждый вызов стоит денег, а пользователь может дёрнуть её полсотни раз за минуту. Нужны были лимиты на конкретную ручку и на конкретного пользователя, причём в тот же день.</p><p>Скользящее окно они <a href="https://dev.to/anand_rathnas_d5b608cc3de/redis-sliding-window-rate-limiting-with-lua-the-15-line-script-that-saved-our-ai-budget-p0i">собрали на сортированном множестве Redis</a>. Скор записи — временная метка в миллисекундах, а весь алгоритм умещается в один Lua-скрипт, который Redis выполняет атомарно:</p><p>Первая команда чистит записи старше окна относительно текущего момента — именно поэтому окно скользящее, а не фиксированное: границ, к которым можно приурочить всплеск, здесь просто нет. PEXPIRE с запасом в секунду доубивает ключ, если новых запросов не приходит, так что чистить хранилище отдельно не нужно.</p><h3>Две детали, на которых легко ошибиться</h3><p><b>Уникальность члена множества.</b> ZADD не добавляет запись, а перезаписывает существующую, если член совпал. Два запроса в одну миллисекунду с одинаковым значением дадут счётчик, который занижен. Авторы склеивают метку времени с восемью символами UUID: метка обеспечивает уникальность почти всегда, а восемь шестнадцатеричных символов дают около четырёх миллиардов вариантов внутри одной миллисекунды.</p><p><b>Куда падать при отказе Redis.</b> Решение здесь принимается осознанно и по-разному для двух случаев. Если вызов не получил внятного ответа вовремя (таймаут клиента, сетевая икота), запрос пропускают: лимит здесь страхует бюджет, а не безопасность, и блокировать живого пользователя из-за сбоя инфраструктуры хуже, чем оплатить лишний вызов модели. А вот жёсткое исключение (Redis недоступен, соединение отвергнуто) пробрасывают наверх: если хранилище легло целиком, лучше шумно упасть, чем молча жечь бюджет вообще без ограничений.</p><p>Обошлось это в два часа работы вместе с тестами. Одна запись в сортированном множестве занимает около 50 байт, на пользователя их пять, и даже при десяти тысячах активных пользователей всё хранилище лимитов весит порядка 2,5 МБ. Настроенный лимит составил пять запросов за шестьдесят секунд на пользователя. Первым же уловом стал автоматизированный скрипт, бивший в ручку больше двухсот раз в час.</p><h2>Честный контракт с клиентом</h2><p>Ограничение без внятного ответа превращает вежливого клиента в невежливого: не понимая, что происходит, он начинает долбить чаще. Минимальный набор обязательств выглядит так:</p><ul><li>Отдавать 429 Too Many Requests, а не общий 400 или 503. По коду клиент понимает, что делать.</li><li>Присылать заголовок Retry-After, чтобы клиент знал момент следующей попытки, а не подбирал его перебором.</li><li>Показывать остаток бюджета в заголовках вида X-RateLimit-Remaining и X-RateLimit-Reset.</li></ul><p>Последний пункт стоит дешевле всего и работает лучше всего: клиент, который видит свой остаток, обычно распределяет запросы сам и до стены не доходит.</p><h2>Что забрать с собой</h2><p>Обе половины задачи решаются до того, как появится нагрузка, и обе стоят один вечер. Курсорная пагинация убирает и деградацию на глубоких страницах, и молчаливую порчу выдачи при параллельных записях. Атомарный счётчик в общем хранилище превращает лимит из декоративного в настоящий.</p><p>Отложить их дешевле всего прямо сейчас и дороже всего в момент, когда в поддержку придёт клиент с задвоенными заказами: тогда чинить придётся не только API, но и данные на его стороне.</p><p>Разборы, на которых основан материал: <a href="https://dev.to/sirmax/why-i-switched-my-api-from-offset-to-cursor-pagination-and-when-you-shouldnt-1464">переход с offset на курсор с замерами</a>, <a href="https://dev.to/weston_carnes_d580b505e0c/api-rate-limiting-patterns-algorithms-and-how-to-do-it-right-4l35">паттерны и алгоритмы ограничения частоты</a> и <a href="https://dev.to/anand_rathnas_d5b608cc3de/redis-sliding-window-rate-limiting-with-lua-the-15-line-script-that-saved-our-ai-budget-p0i">скользящее окно на Redis и Lua</a>.</p><p>Откройте свой самый нагруженный список и выполните запрос с большим смещением. Если ответ идёт дольше сотни миллисекунд, вы уже нашли, с чего начать.</p>]]></content:encoded>
    </item>
    <item>
      <title>Anthropic открыла Claude Commerce Agents: чертёж торгового агента на Claude</title>
      <link>https://tproger.ru/news/anthropic-otkryla-claude-commerce-agents-chertyozh-torgovogo-agent</link>
      <comments>https://tproger.ru/news/anthropic-otkryla-claude-commerce-agents-chertyozh-torgovogo-agent?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/anthropic-otkryla-claude-commerce-agents-chertyozh-torgovogo-agent</guid>
      <description><![CDATA[<p>Anthropic открыла Claude Commerce Agents под Apache 2.0: два агента для магазина, три способа запуска, проверки внутри вызова инструмента и свой бэкенд.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/anthropic-otkryla-claude-commerce-agents-chertyozh-torgovogo-agent">Anthropic открыла Claude Commerce Agents: чертёж торгового агента на Claude</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 02 Sep 2026 19:53:51 GMT</pubDate>
      <content:encoded><![CDATA[<p>Anthropic 2 сентября 2026 года <a href="https://x.com/ClaudeDevs/status/2095233745167282602">открыла исходники</a> Claude Commerce Agents: двух агентов на Claude для интернет-торговли под лицензией Apache 2.0. Первый, покупательский, бизнес встраивает в своё приложение для клиентов. Второй, мерчантский, нужен сотрудникам, чтобы вести листинги, цены, остатки и кампании. В <a href="https://github.com/anthropics/commerce-agents">репозитории anthropics/commerce-agents</a> лежат оба агента, четыре демонстрационные вертикали (розница, путешествия, телеком, билеты), семь pip-пакетов и плагин для Claude Code, который собирает такого агента под чужой стек.</p><p>Для команды, которая пишет ассистента магазина или маркетплейса, интерес здесь в архитектуре, а не в демо. Anthropic показывает, как описать агента один раз и запускать тремя способами, где стоят проверки, чтобы модель не могла подложить в корзину чужой товар или изменить цену без человека, и как подключить свой каталог через два интерфейса на Python.</p><p>Оговорка стоит в самом README: это референсная реализация, она не поддерживается и не принимает внешний вклад. В примерах нет аутентификации, MCP-серверы по умолчанию слушают loopback.</p><ul><li>Два агента, три способа запуска (Messages API, Claude Agent SDK, Managed Agents (beta)), четыре вертикали и восемь веб-приложений в одном репозитории под Apache 2.0.</li><li>Не оформляет заказ, не списывает деньги и не меняет живые листинги: checkout только рисует корзину, каждая запись мерчанта ждёт одобрения человека.</li><li>Проверки provenance, лимиты, ограждение стороннего текста и валидация памяти работают внутри вызова инструмента и держатся на всех трёх путях запуска.</li><li>Своя интеграция сводится к реализации StorefrontBackend или MerchantBackend; отсутствующие системы выключаются переключателями enable_*.</li><li>Модели по умолчанию: claude-sonnet-5 у покупательского агента, claude-opus-5 у мерчантского, claude-haiku-4-5-20251001 для памяти; рантаймы работают через Vertex AI, Bedrock, Microsoft Foundry и шлюзы.</li><li>Требования: Python 3.11 и новее, Node 22. Демо поднимается шестью командами из README.</li></ul><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-03/8278495a-80f4-42a1-baf3-e052ab3d3504.webp" alt="Кадр из видео Anthropic с четырьмя вертикалями: Retail, Travel, Telecom, Ticketing" /><figcaption>Четыре вертикали из анонсирующего видео. Скриншот: Anthropic, commerce-agents</figcaption></figure><h2>Один агент описан один раз и работает на трёх рантаймах</h2><p>Главная архитектурная идея репозитория, как её формулирует <a href="https://github.com/anthropics/commerce-agents/blob/main/README.md">README</a>: каждый агент определён один раз (промпт, скиллы, контракты инструментов, гейты) и запускается на Messages API, на Claude Agent SDK и на Managed Agents. Четыре вертикали работают поверх одних библиотек и различаются бэкендом и доменными расширениями интерфейса.</p><p>Покупательский агент ищет и сравнивает товары, собирает планы покупок, наполняет корзину, отвечает на вопросы о заказах и правилах магазина и запоминает, что покупатель о себе рассказал. Его пять сценариев лежат как skills в каталоге <a href="https://github.com/anthropics/commerce-agents/tree/main/shopping-agent/skills">shopping-agent/skills</a>. Мерчантский агент объясняет показатели, правит листинги, реагирует на алерты по остаткам и заказам, назначает цены и промо, готовит кампании. Его пять сценариев лежат в <a href="https://github.com/anthropics/commerce-agents/tree/main/merchant-agent/skills">merchant-agent/skills</a>. Любая запись мерчанта становится staged change, которую применяет уже интерфейс одобрения на стороне хоста.</p><blockquote>Nothing places an order, charges a card, or changes a live listing: checkout renders the cart for the host to complete, and every merchant write is staged until a person approves it.</blockquote><p>Код разложен на семь pip-пакетов. Общее для обеих ролей вынесено в commerce-common: конфиг, ограждение стороннего текста, память, скиллы, grounding, презентационные компоненты, исполнитель инструментов и события. У каждой роли три пакета: core с типами, интерфейсом бэкенда, промптом, контрактами инструментов и гейтами; runtime с циклом ходов на Messages API; sdk с тем же агентом на Agent SDK и консолью. CI проверяет, что имена семи пакетов остаются незарегистрированными в публичном индексе, а pin-файлы ставят их из каталогов репозитория.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-03/6f818534-34eb-4db9-9321-d353b648b4e1.webp" alt="Горизонтальная диаграмма: состав репозитория commerce-agents в штуках: 2 агента, 3 рантайма, 4 вертикали, 7 пакетов, 8 веб-приложений, 10 flows, 7 расширений интерфейса, 4 команды плагина" /><figcaption>Состав поставки по README репозитория. График: Tproger по данным README anthropics/commerce-agents</figcaption></figure><p>Эталонный путь запуска, вокруг которого построены примеры, это Messages API. Хост создаёт объект агента с бэкендом, каталогом скиллов и конфигом и стримит события хода; извлечение памяти вызывается отдельно после хода, и только на этом пути. Код из README:</p><p>На Agent SDK тот же промпт, скиллы и инструменты, но цикл ведёт SDK: хост заранее подгружает данные для grounding, после хода ничего не выполняется. На Managed Agents агент размещён у Anthropic и ходит за данными в ваш MCP-сервер; деплой делает скрипт scripts/deploy_managed_agent.sh, без флага --live это сухой прогон. Различия трёх путей по docs/safety.md:</p><ul><li><b>Messages API.</b> Все правила grounding включаются принудительно через tool_choice; работают извлечение памяти после хода, сжатие истории и бюджеты аналитического делегата мерчанта.</li><li><b>Agent SDK.</b> Grounding только для правил с формой предварительной загрузки; цикл ограничен max_turns; аналитика мерчанта идёт субагентом без SQL-инструмента и бюджетов; память хост извлекает сам.</li><li><b>Managed Agents.</b> Grounding отсутствует, циклом владеет платформа, память пишется только через save_memory, одобрением staged change служит промпт always_ask на apply_change.</li></ul><h2>Проверки стоят внутри вызова инструмента, поэтому переживают смену рантайма</h2><p>Документ <a href="https://github.com/anthropics/commerce-agents/blob/main/docs/safety.md">docs/safety.md</a> делит правила на три группы: что код проверяет сам, что по-прежнему просят у модели промптом и что обязан добавить деплой. Ключевой приём: правило внутри вызова инструмента держится на всех трёх путях, потому что все три прогоняют вызовы через один исполнитель в модуле commerce_common/execution.py. Правило на уровне хода живёт в конкретном рантайме, и таблица указывает, где оно не работает.</p><blockquote>A rule enforced inside a tool call holds on all three paths, because the Messages API runtime, the SDK toolset, and the MCP server execute tools through the same executor.</blockquote><p>Что именно проверяется в коде, по таблице документа:</p><ul><li><b>Ограждение (fencing).</b> Сторонний текст очищается, оборачивается в ограждение с фиксированной меткой и обрезается до max_fenced_chars. Очистка убирает невидимые и управляющие символы, поддельные маркеры ходов, теги транскрипта и вызовов инструментов и копии самого маркера ограждения.</li><li><b>Лимиты цикла.</b> Запрошенное моделью число результатов поиска обрезается до max_search_results; после max_tool_iterations раундов рантайм Messages API принудительно делает ход без инструментов.</li><li><b>Provenance корзины.</b> В корзину попадают только идентификаторы товаров, которые в этой сессии вернул инструмент каталога или заказов. Попытка добавить товар с опциями (размер, цвет) задерживается, и модели показывают варианты. Действует лимит на позицию и на число строк.</li><li><b>Нет оплаты.</b> У StorefrontBackend нет метода, который размещает заказ или списывает деньги. URL размещённого checkout приходит из checkout_handoff после вызова модели и не проходит через неё.</li><li><b>Provenance staged-записей мерчанта.</b> Изменение принимает только идентификаторы листингов и кампаний, возвращённые инструментом в этой сессии; правка контента требует чтения get_listing. apply_change принимает только идентификаторы изменений, которые вернули staging или get_pending_changes.</li><li><b>Guardrails мерчанта.</b> Проверяются при постановке изменения и повторно при применении: число позиций, размах изменения цены, глубина промо, размер пополнения, бюджет кампании, защищённые поля.</li><li><b>Одобрение хостом.</b> При require_host_approval (включено по умолчанию) apply_change проходит только для идентификаторов, которые хост пометил одобренными. Карточка предпросмотра ничего не одобряет, «да, применяй» в чате тоже.</li><li><b>Память.</b> Ключ факта до 64 символов, значение до 200, одна из трёх категорий; значения, похожие на идентификаторы, отбрасываются. Извлечение читает только текст последнего обмена, никогда результаты инструментов.</li><li><b>Поверхность инструментов и идентичность.</b> Список инструментов вычисляется из конфига деплоя, исполнитель отказывает любому другому имени. Идентичность держит сервер: ни один аргумент инструмента не называет пользователя или мерчанта.</li></ul><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-03/858edd4a-4a45-4ee5-adca-71116592a154.webp" alt="Горизонтальная диаграмма лимитов: ключ факта памяти 64 символа, значение 200 символов, ограждение стороннего текста 12 000 символов по умолчанию" /><figcaption>Лимиты, которые проверяет код: память покупателя и размер одного ограждения. График: Tproger по данным docs/safety.md и docs/backends.md anthropics/commerce-agents</figcaption></figure><p>Вторая группа правил остаётся в промпте: трактовать ограждённый текст как материал для отчёта, называть условия и цифры только из результата инструмента, подтверждать запись только после успешного вызова, называть товары по идентификатору. Документ оговаривает: промптовые правила держатся ровно настолько, насколько модель следует инструкциям, а таблица держится на любой модели. Деплой, который меняет модель или выключает require_host_approval, должен сначала перегнать свои evals по этому разделу.</p><blockquote>When the model breaks one of these, the error is confined to its text. Every write, figure, and disclosure behind that text still passed the checks in the table above, so the failure is a misstatement to correct and no action needs reversing.</blockquote><p>Третья группа целиком на стороне деплоя: аутентификация и авторизация на каждом маршруте и на MCP-серверах (примеры принимают любого вызывающего), учётные данные для вызова ваших сервисов, лимиты запросов, бизнес-правила (фрод, право на покупку, цены, остатки), оплата после checkout, обращение с памятью как с персональными данными, гигиена логов и сама поверхность одобрения. Значения guardrails в двух файлах config.py названы демонстрационными.</p><h2>Своя интеграция сводится к двум интерфейсам и переключателям enable_*</h2><p>Точка входа для собственных систем описана в <a href="https://github.com/anthropics/commerce-agents/blob/main/docs/backends.md">docs/backends.md</a>. Деплой реализует StorefrontBackend поверх каталога, корзины, заказов и политик или MerchantBackend поверх аналитики, каталога, остатков, цен и кампаний. Контрактом служат докстринги методов в backend.py и types.py каждой роли. Каждый метод вызывает ваш сервис на стороне сервера с учётными данными, которые хост хранит для сессии; модель видит только результат.</p><blockquote>Each one calls your service server-side with the credential your host holds for the session; the model reads only the result.</blockquote><p>Документ раскладывает интеграцию на шесть шагов. Первый: решить, кто вызывающий. Хост аутентифицирует человека и стартует сессию с принципалом; токен покупателя живёт в контексте сессии, сервисная учётка передаётся в конструктор бэкенда. Гость тоже принципал: чтение, которому нужен аккаунт, бросает исключение, которое подкласс исполнителя превращает в просьбу войти. Второй: порядок многошаговых сценариев (удержать места, затем подтвердить) хранится и проверяется в бэкенде, а нарушение маппится через domain_error в понятный модели результат. Третий: как завершается checkout. Вариантов три: ссылка на маршрут в вашем приложении, размещённый checkout платформы, для которого checkout_handoff возвращает URL, или маркетплейс с записью на каждого продавца.</p><p>Четвёртый шаг: товары с опциями. Запись бывает простой, семейством (с полем options) или вариантом (с option_values и variant_of); идентификатор варианта идёт всюду, где ждут идентификатор товара. Детали товара возвращают все варианты семейства в одном ограждении, обрезанном до max_fenced_chars (12 000 символов по умолчанию). Компактная строка варианта занимает 70–120 символов, так что в семейство помещается около шестидесяти вариантов; кроссовки в восьми цветах и четырнадцати размерах документация советует подавать как восемь семейств по четырнадцать, потому что за пределами лимита результат режется без ошибки. Пятый: записи мерчанта по семействам, где изменение цены и пополнение именуют вариант. Шестой: для цифр, которых у платформы нет, возвращать None с пометкой, а не подставной ноль.</p><p>Для пилота README предлагает начинать с малого. Покупательский пилот реализует поиск и карточку товара, а остальное заглушает: метод-заглушка возвращает результат «недоступно» и не меняет ни байта промпта. Мерчантский пилот реализует восемь методов чтения, записи отказывают. Система, которой у бизнеса нет совсем, выключается переключателем enable_*: это убирает её инструменты, строки промпта и правило grounding на всех трёх путях, а сценарии, которым она нужна, паркуются в каталоге skills/_staged/. Свой сценарий добавляется каталогом с файлом SKILL.md, доменный интерфейс расширением PresentationExtension (вертикали поставляют семь), а brand_name, assistant_name и brand_voice в конфиге задают личность ассистента.</p><figure><img src="https://media.tproger.ru/user-uploads/133946/2026-09-03/632d0218-5e02-4a2c-8f59-e75bb9f7efce.webp" alt="Кадр из видео Anthropic: путь от намерения покупателя до staged-заказа" /><figcaption>Кадр «From intent to a staged order» из анонсирующего видео. Скриншот: Anthropic, commerce-agents</figcaption></figure><h2>Модели заданы строкой в конфиге, а переключение платформы сосредоточено в одном месте и зависит от рантайма</h2><p>По <a href="https://github.com/anthropics/commerce-agents/blob/main/docs/deployment.md">docs/deployment.md</a> код по умолчанию ходит в API Anthropic, но у каждого пути есть одно место, где деплой переключает платформу. Рантаймы Messages API принимают любой асинхронный клиент из пакета anthropic аргументом client=: AsyncAnthropicVertex для GCP Vertex AI, AsyncAnthropicBedrockMantle или AsyncAnthropicBedrock для AWS, AsyncAnthropicFoundry для Microsoft Foundry, AsyncAnthropic с base_url и auth_token для собственного шлюза. Пакеты требуют anthropic 0.91 и новее. Рантаймы Agent SDK HTTP-клиента не создают: платформу выбирает CLI Claude Code по переменным окружения, которые добавляются в options.env. Managed Agents работает на инфраструктуре Anthropic, поэтому у него нет варианта для Vertex, Bedrock и Foundry.</p><p>Модель задаётся строкой в конфиге: поля model и memory_model у каждой роли, у мерчанта ещё analysis_model. Значения по умолчанию, по таблице документа: claude-sonnet-5 для покупательского агента, claude-opus-5 для мерчантского, claude-haiku-4-5-20251001 для извлечения памяти. Грамматика идентификаторов у платформ разная: Vertex пишет датированные снимки через @, Bedrock через Mantle берёт идентификаторы с префиксом anthropic., а через Invoke API идентификаторы inference-профилей. Все три поля идут через один клиент, поэтому все три модели должны существовать на целевой платформе. Живого разговора с облаком в CI нет; документ просит прогнать его на своей платформе до того, как на неё полагаться.</p><p>Доступность API Anthropic и облачных платформ для конкретной страны или способа оплаты в документации репозитория не обсуждается. Для собственного шлюза документ называет требование: отдавать /v1/messages со стримингом SSE для Messages API, а для Managed Agents ещё проксировать /v1/skills, /v1/agents, /v1/environments, /v1/sessions и поток событий сессии с заголовками anthropic-beta.</p><h2>Демо поднимается шестью командами, а плагин Claude Code собирает агента под ваш стек</h2><p>Порядок запуска из README (нужны Python 3.11 и новее и Node 22, ключ ANTHROPIC_API_KEY в файле .env):</p><p>Флаг --merchant поднимает портал мерчанта вместо витрины, --all оба. В README каждой вертикали есть раздел Try с репликами, которые прогоняет scripts/smoke_chat.py. Розничная ACME показывает поиск, сравнение, корзину, checkout и память; ACME Travel добавляет инвентарь с датами; ACME Mobile матрицу тарифов и серверные раскрытия комиссий; ACME Tickets таймированные удержания мест, листы ожидания и карту зала.</p><p>Второй способ начать: <a href="https://github.com/anthropics/commerce-agents/tree/main/plugins/commerce-builder">плагин commerce-builder</a> для Claude Code. Он читает клонированный репозиторий как эталон и собирает агента на этих пакетах против ваших систем либо проверяет уже написанного. Установка и первая команда из README:</p><p>Команда /scaffold-commerce-agent спрашивает о стеке, проговаривает план и строит проект. Дальше /add-commerce-flow добавляет сценарий, /author-commerce-evals пишет evals, /review-commerce-agent начинает с уже существующего агента. Собственных MCP-коннекторов в поставке нет: оба агента ходят в системы через интерфейсы бэкенда. Где официальный коннектор является источником истины (Snowflake, BigQuery, Stripe, Square, Slack и другие в списке README), он и становится целью интеграции. MCP-сервер торговой платформы вызывается из метода бэкенда на сервере, и гейты provenance остаются перед каждой записью.</p><p>Проверка после правок: ruff check и ruff format --check, pytest, python scripts/check.py; python scripts/verify_all.py добавляет сухие прогоны деплоя и сборку веб-приложений; python scripts/smoke_chat.py --vertical travel проводит один живой разговор и требует ключ. Чтобы убедиться, что кэширование промпта работает, README советует читать cache_read_input_tokens из события turn_complete: ноль на втором ходу означает, что префикс промпта изменился.</p><h2>Что делать команде, которая пишет ассистента для магазина</h2><ol><li>Поднять розничное демо по шести командам выше (Python 3.11 и новее, Node 22, ключ API) и пройти реплики из раздела Try в examples/retail/ на витрине (порт 3000) и в портале мерчанта (флаг --merchant, порт 3100).</li><li>Сверить таблицу «Enforced in code» и список «What a deployment owns» из docs/safety.md с собственной платформой: аутентификация, учётные данные, лимиты запросов, бизнес-правила, оплата, персональные данные в памяти, логи.</li><li>Для пилота реализовать в StorefrontBackend только поиск и карточку товара, для MerchantBackend восемь методов чтения. Отсутствующие системы выключить через enable_*, зависимые сценарии убрать в skills/_staged/.</li><li>Разложить каталог по трём формам записи из docs/backends.md и проверить самое большое семейство против лимита max_fenced_chars в 12 000 символов.</li><li>Выбрать завершение checkout: свой маршрут, размещённый URL платформы через checkout_handoff или ссылка на продавца для маркетплейса; оплата остаётся в хосте.</li><li>Для Vertex AI, Bedrock, Foundry или шлюза передать клиент аргументом client= (anthropic 0.91 и новее) или переменные CLI в options.env и заменить все три идентификатора моделей.</li><li>Перед выкладкой прогнать ruff, pytest, scripts/check.py и scripts/verify_all.py, затем один живой разговор scripts/smoke_chat.py на своей платформе; при смене модели перегнать evals по разделу «Still asked of the model».</li></ol><p>Репозиторий создан 1 сентября, анонс в аккаунте Claude Developers вышел 2 сентября в 19:33 UTC. На 3 сентября, 01:53 мск, по <a href="https://api.github.com/repos/anthropics/commerce-agents">данным GitHub API</a> у проекта 277 звёзд и 46 форков. Поддержки и приёма внешних изменений Anthropic не обещает: «This is a reference implementation; it is not maintained and does not accept contributions», говорится в README. На практике это значит, что исправления и адаптацию под свои системы команде придётся вести в собственном форке, а промпты и гейты под новые модели проверять своими evals. Цен, лимитов и сроков дальнейшего развития Anthropic в репозитории не называет.</p><p>Источники: <a href="https://x.com/ClaudeDevs/status/2095233745167282602">Claude Developers в X: анонс открытия Claude Commerce Agents (2 сентября 2026)</a>, <a href="https://github.com/anthropics/commerce-agents">GitHub: anthropics/commerce-agents</a>, <a href="https://github.com/anthropics/commerce-agents/blob/main/README.md">README репозитория commerce-agents</a>, <a href="https://github.com/anthropics/commerce-agents/blob/main/docs/safety.md">docs/safety.md: правила, проверяемые кодом, и обязанности деплоя</a>, <a href="https://github.com/anthropics/commerce-agents/blob/main/docs/backends.md">docs/backends.md: подключение своих систем</a>, <a href="https://github.com/anthropics/commerce-agents/blob/main/docs/deployment.md">docs/deployment.md: Vertex AI, Bedrock, Microsoft Foundry и шлюзы</a>, <a href="https://github.com/anthropics/commerce-agents/tree/main/plugins/commerce-builder">Плагин commerce-builder для Claude Code</a>, <a href="https://github.com/anthropics/commerce-agents/tree/main/shopping-agent/skills">Скиллы покупательского агента</a>, <a href="https://github.com/anthropics/commerce-agents/tree/main/merchant-agent/skills">Скиллы мерчантского агента</a></p><p>Изображение на обложке: Anthropic, кадр из анонса Claude Commerce Agents</p>]]></content:encoded>
    </item>
    <item>
      <title>METR рассказала, как у неё украли API-ключ через приложение с ошибкой fail-open</title>
      <link>https://tproger.ru/news/metr-rasskazala-kak-u-neyo-ukrali-api-klyuch-k-modelyam-vajb-kodi</link>
      <comments>https://tproger.ru/news/metr-rasskazala-kak-u-neyo-ukrali-api-klyuch-k-modelyam-vajb-kodi?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/metr-rasskazala-kak-u-neyo-ukrali-api-klyuch-k-modelyam-vajb-kodi</guid>
      <description><![CDATA[<p>Лаборатория METR раскрыла два инцидента 2026 года: кражу API-ключа к моделям через самодельное приложение на личном EC2 и майскую кампанию сканирования. Цепочка ошибок, что удалось и что не удалось атакующим, правила хранения ключей для команд, работающих с LLM.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/metr-rasskazala-kak-u-neyo-ukrali-api-klyuch-k-modelyam-vajb-kodi">METR рассказала, как у неё украли API-ключ через приложение с ошибкой fail-open</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Облачные технологии]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 01 Sep 2026 17:30:42 GMT</pubDate>
      <content:encoded><![CDATA[<p>Исследовательская лаборатория <b>METR</b>, которая оценивает возможности ИИ-моделей для крупных разработчиков, 31 августа <a href="https://metr.org/blog/2026-08-31-security-update/">опубликовала</a> отчёт о двух инцидентах безопасности 2026 года. В марте у неё украли API-ключ для запросов к публичным моделям и три недели тратили её кредиты, в мае злоумышленники сканировали публичную инфраструктуру и перебирали пароли. По оценке METR, к самым чувствительным данным доступ не получили.</p><p>METR оценивает израсходованные бесплатные кредиты примерно в $600 тыс., но интереснее цепочка ошибок: она типична для любой команды, которая быстро собирает внутренние инструменты вокруг LLM. Ключ лежал на личном сервере исследователя, приложение было написано с помощью ИИ и при сбое проверки доступа пропускало запрос вместо того, чтобы отклонить его. Российские команды, которые получают доступ к зарубежным моделям через посредников или общие ключи, рискуют сильнее: перевыпуск ключа у них занимает не минуты, а дни.</p><ul><li>Март 2026 года: API-ключ для инференса публичных моделей украден с личного EC2-инстанса исследователя, где стояло самодельное приложение за Google-аутентификацией.</li><li>Приложение имело уязвимость fail-open: при ошибке проверки доступ открывался; инстанс был намеренно публичным за Google-аутентификацией.</li><li>Атакующий попросил агента показать ключ, получил его и добавил на сервер собственный SSH-ключ; чужие запросы шли около трёх недель.</li><li>Май 2026 года: сканирование сервисов, подбор паролей по утёкшим базам, попытки через OAuth-токены; в публичном просмотрщике транскриптов нашли ошибку с read-only SQL, признаков её эксплуатации нет.</li><li>METR остановила и сняла образ инстанса, заменила учётные данные; описанные меры актуальны на 30 июля 2026 года.</li></ul><h2>Как украли ключ</h2><p>Исследователь METR поднял на личном инстансе EC2 небольшое веб-приложение, написанное с помощью ИИ, и защитил его входом через Google. В коде была классическая ошибка <b>fail-open</b>: если проверка авторизации по какой-то причине не срабатывала, приложение считало пользователя допущенным, а не отказывало. Инстанс намеренно был публичным за входом через Google, и ошибка fail-open сняла эту защиту; этого хватило.</p><blockquote>The vibe-coded app included a fail-open vulnerability.</blockquote><p>Дальше атакующий, по описанию METR, попросил агента показать ключ API, и тот его раскрыл, а для постоянного доступа добавил на сервер собственный SSH-ключ. Ключ использовали для запросов к публичным моделям примерно три недели. Заметить это оказалось трудно по двум причинам: METR не платила за эти кредиты деньгами, так что счёт не рос, а внутренняя панель METR не показывала запросы, отклонённые по лимитам, для всех пользователей ключа.</p><h2>Вторая волна: май</h2><p>В мае METR зафиксировала другую активность: сканирование публичной инфраструктуры, перебор паролей по утёкшим базам и попытки получить OAuth-токены. Попутно выяснилось, что публичный просмотрщик транскриптов позволял выполнять SQL-запросы только на чтение, но через эту ошибку в теории можно было добраться до неопубликованных данных оценок. Признаков, что атакующие этим воспользовались, компания не нашла. Описанные меры, по словам METR, актуальны на 30 июля 2026 года.</p><h2>Правила, которые из этого следуют</h2><ul><li>Ключи API к моделям не живут на личных серверах и ноутбуках: только в секрет-хранилище команды с выдачей по ролям и сроком жизни.</li><li>Приложения с доступом к ключам делайте fail-closed: любая ошибка в проверке прав — отказ, а не пропуск. Это первое, что стоит проверить в коде, написанном с ИИ.</li><li>На каждый ключ — лимит расходов и алерт на аномалию по числу запросов, а не только по деньгам: бесплатные кредиты тратятся так же незаметно.</li><li>Отдельный ключ на каждое приложение и человека: один общий ключ означает, что после утечки ротировать придётся всё сразу.</li><li>Инстансы «на минутку» с публичным IP считайте продом: инвентаризация, автоматическое выключение по таймеру, запрет входящих портов по умолчанию.</li></ul><h2>Контекст</h2><p>METR получает от разработчиков моделей ранний доступ для оценок безопасности, поэтому её инфраструктура — заметная цель. То, что оба инцидента пришлись на периферию (личный сервер, публичный просмотрщик), а не на основные системы, говорит скорее о сегментации, чем об удаче. Но именно периферия и есть то место, где у большинства команд лежат ключи «на время». Сумму METR оценивает примерно в $600 тыс. бесплатных кредитов, которые она не оплачивала деньгами.</p><p>Источник: <a href="https://metr.org/blog/2026-08-31-security-update/">Security update (METR, 31 августа 2026)</a></p><p>Изображение на обложке: METR</p>]]></content:encoded>
    </item>
    <item>
      <title>Цифровой рубль вышел в массовое использование: что менять в интеграциях</title>
      <link>https://tproger.ru/news/cifrovoj-rubl-vywel-v-massovoe-ispolzovanie-s-1-sentyabrya-perv</link>
      <comments>https://tproger.ru/news/cifrovoj-rubl-vywel-v-massovoe-ispolzovanie-s-1-sentyabrya-perv?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Tproger]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/cifrovoj-rubl-vywel-v-massovoe-ispolzovanie-s-1-sentyabrya-perv</guid>
      <description><![CDATA[<p>С 1 сентября 2026 года крупнейшие банки и ритейлеры открыли инфраструктуру цифрового рубля. Как устроен третий вид денег, какие лимиты, сроки и комиссии установил Банк России, кто обязан принимать цифровые рубли и что менять в платёжных интеграциях магазинов и сервисов.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/cifrovoj-rubl-vywel-v-massovoe-ispolzovanie-s-1-sentyabrya-perv">Цифровой рубль вышел в массовое использование: что менять в интеграциях</a>»</p>]]></description>
      <category><![CDATA[Интернет]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Организация разработки]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 01 Sep 2026 17:29:45 GMT</pubDate>
      <content:encoded><![CDATA[<p>С 1 сентября 2026 года крупнейшие банки и торговые компании открыли инфраструктуру <b>цифрового рубля</b>, <a href="https://www.cbr.ru/press/event/?id=32802">сообщил</a> Банк России 31 августа. Совершеннолетний гражданин с подтверждённой учётной записью Госуслуг может завести цифровой счёт в приложении подключённого банка, а крупнейшие магазины обязаны принимать оплату в новой форме. Для разработчиков это означает появление третьего платёжного канала рядом с картами и СБП, со своими правилами, лимитами и сроками подключения.</p><p>Цифровой рубль — не криптовалюта и не «безнал на карте». Счёт открывается на платформе Банка России, а банк выступает посредником, через приложение которого клиент этим счётом управляет. Один человек или компания может иметь только один такой счёт; у ИП их два: личный и для бизнеса. Если вы делаете интернет-магазин, кассу, биллинг или сервис подписок для компании из первой волны, приём цифрового рубля становится обязательным сценарием, а не опцией.</p><ul><li>Счёт цифрового рубля открывается на платформе Банка России через раздел «Цифровой рубль» в приложении подключённого банка; один счёт на физлицо или компанию, у ИП два.</li><li>Лимит пополнения для физлиц — 300 тыс. рублей в месяц, для бизнеса лимита нет; тратить накопленное можно без ограничений.</li><li>Для граждан операции бесплатны; для бизнеса комиссии не взимаются до конца 2026 года, тарифы с 2027 года установлены отдельным решением Банка России от 28 августа.</li><li>Принимать цифровые рубли обязаны с 1 сентября 2026 года торговые компании с выручкой свыше 120 млн рублей, у которых на 1 января 2026 года был договор с крупнейшим банком-участником; торговые точки с выручкой до 5 млн рублей освобождены.</li><li>Все банки с универсальной лицензией подключаются к 1 сентября 2027 года, с базовой — к 1 сентября 2028 года; сроки закреплены законом 248-ФЗ.</li></ul><h2>Как это устроено</h2><p>Платформа цифрового рубля принадлежит Банку России, и все счета живут на ней, а не в отдельных банках. Банк лишь даёт интерфейс: открыть счёт, пополнить его с обычного счёта, заплатить, вернуть деньги обратно. Отсюда две особенности, которых нет у безнала: счёт один на всю страну, и, сменив банк, клиент сохраняет тот же счёт; лимиты и комиссии задаёт регулятор, а не банк. Регулятор допускает и банки, которые не обязаны открывать инфраструктуру этой осенью, но хотят предоставлять сервис уже сейчас.</p><blockquote>Граждане смогут пополнять счёт цифрового рубля со своих банковских счетов на сумму до 300 тыс. рублей в месяц. Для бизнеса лимита на пополнение нет. Всеми накоплениями на своём цифровом кошельке и граждане, и компании смогут распоряжаться без ограничений.</blockquote><p>Доступные операции: переводы между гражданами и компаниями, платежи в бюджет и из бюджета, оплата покупок, возвраты. Открытие и закрытие счёта бесплатны, для граждан бесплатны все платежи и переводы. Для бизнеса действует льготный период до конца 2026 года; тарифы для индивидуальных предпринимателей и компаний с 2027 года установлены <a href="https://www.cbr.ru/rbr/dir_decisions/rsd_2026-08-28_45_01/">отдельным решением Совета директоров Банка России от 28 августа 2026 года</a>. По вопросам работы с цифровыми рублями регулятор советует обращаться сначала в свой банк, затем на горячую линию Банка России по цифровому рублю: 8 800 301 30 00, короткий номер 301 с мобильного или +7 499 300 3 301.</p><h2>Сроки для банков и магазинов</h2><p>Внедрение идёт волнами. С 1 сентября 2026 года инфраструктуру открывают крупнейшие банки, а торговые компании с выручкой свыше 120 млн рублей в год, у которых на 1 января 2026 года был договор с таким банком, обязаны принимать цифровые рубли. С 1 сентября 2027 года такую возможность должны обеспечить все банки с универсальной лицензией, с 1 сентября 2028 года — банки с базовой лицензией. Торговые точки с выручкой меньше 5 млн рублей от обязанности освобождены, как и торговые точки там, где нет интернета. Обязательные сроки для банков и продавцов закреплены федеральным законом 248-ФЗ, а решение Банка России определяет лимиты, перечень операций и порядок добровольного раннего подключения остальных банков.</p><h2>Что это значит для разработчика платёжной интеграции</h2><p>Технически приём идёт через банк-участник, поэтому прямой интеграции с платформой Банка России у магазина нет: интерфейс и документацию даёт ваш банк. Возвраты уходят обратно на цифровой счёт покупателя, а не на карту, и это отдельная ветка в логике рефандов и чеков. Лимит 300 тыс. рублей в месяц касается пополнения счёта физлицом; расход ограничен только остатком на счёте.</p><ul><li>Узнайте у своего банка, как он подключает приём цифровых рублей и какие интерфейсы даёт; для крупнейших банков это уже сентябрь 2026 года.</li><li>Заложите в модель данных третий тип платежа рядом с картой и СБП: у него свои статусы, свой возврат и своя сверка.</li><li>Возвраты: средства уходят обратно на цифровой счёт покупателя; учитывайте это в логике рефандов и в чеках.</li><li>Комиссии для бизнеса появятся с 2027 года по тарифам решения от 28 августа; не зашивайте «бесплатно» в расчёт стоимости платежей.</li><li>Торговые точки с выручкой до 5 млн рублей, точки без интернета и, до сентября 2027 года, клиенты банков вне списка крупнейших могут не спешить: для них цифровой рубль пока добровольный.</li></ul><h2>Контекст</h2><p>Пилот цифрового рубля стартовал в августе 2023 года на ограниченном круге клиентов и банков. К концу сентября 2025 года в нём было открыто больше 2,5 тыс. кошельков и проведено больше 90 тыс. операций. Массовый запуск дважды переносили. Следующая проверка — сентябрь 2027 года, когда к платформе должны подключиться все банки с универсальной лицензией, и тарифы для бизнеса, которые начнут действовать с января.</p><p>Источники: <a href="https://www.cbr.ru/press/event/?id=32802">Сообщение Банка России о старте с 1 сентября</a>, <a href="https://www.cbr.ru/rbr/dir_decisions/rsd_2026-08-28_45_02/">Решение Совета директоров Банка России от 28.08.2026</a>, <a href="https://www.cbr.ru/fintech/dr/">Страница проекта «Цифровой рубль»</a></p><p>Изображение на обложке: Банк России</p>]]></content:encoded>
    </item>
    <item>
      <title>RAG-бот для любого сайта на Python за 60 строк кода</title>
      <link>https://tproger.ru/articles/rag-bot-dlya-lyubogo-sajta-na-python-za-60-strok-koda</link>
      <comments>https://tproger.ru/articles/rag-bot-dlya-lyubogo-sajta-na-python-za-60-strok-koda?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/rag-bot-dlya-lyubogo-sajta-na-python-za-60-strok-koda</guid>
      <description><![CDATA[<p>Соберите простого RAG-бота на Python, который читает любую веб-страницу и отвечает на вопросы только по её тексту. Гайд с кодом и объяснениями.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/rag-bot-dlya-lyubogo-sajta-na-python-za-60-strok-koda">RAG-бот для любого сайта на Python за 60 строк кода</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Обучение программированию]]></category>
      <category><![CDATA[Парсинг]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Машинное обучение]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 26 Aug 2026 12:06:57 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если попросить языковую модель ответить по свежей документации или конкретному сайту, она с блеском выдумает то, чего там нет. Стандартное решение — <strong>Retrieval-Augmented Generation (RAG)</strong>: сначала достать реальный текст, найти в нём нужные куски и только потом передать их модели в качестве контекста.</p><p>В этой статье соберём работающего RAG-бота, который отвечает на вопросы о любой веб-странице, примерно на 60 строках Python. Никаких парсеров HTML, headless-браузеров и сложных фреймворков — только requests, локальная Ollama и чистый Markdown.</p><h2>Что такое RAG</h2><p>RAG (retrieval-augmented generation) — это подход, при котором языковая модель не отвечает по своей памяти, а сначала ищет релевантные фрагменты во внешнем тексте, а потом генерирует ответ на их основе. Это резко снижает галлюцинации и позволяет работать с данными, которых не было в обучающей выборке.</p><ul><li>RAG-бот на Python укладывается в ~60 строк и работает без облачных LLM.</li><li>Самое неприятное в RAG-пайплайне — очистка HTML; готовый Markdown API убирает эту работу.</li><li>Текст разбивается на чанки (~1200 символов), каждый превращается в эмбеддинг и сравнивается с эмбеддингом вопроса.</li><li>Локальные модели nomic-embed-text и llama3 через Ollama не требуют иностранных карт и VPN.</li><li>Качество ответа зависит от качества исходного текста: сырой HTML зашумляет поиск, чистый Markdown улучшает ретривл.</li></ul><h2>Что мы соберём</h2><p>Архитектура бота простая и универсальная:</p><ol><li>Отправляем URL в сервис извлечения текста и получаем чистый Markdown.</li><li>Разбиваем Markdown на фрагменты (чанки) по границам абзацев.</li><li>Превращаем каждый чанк в вектор — эмбеддинг.</li><li>То же самое делаем с вопросом пользователя.</li><li>Находим чанки, ближайшие к вопросу, по косинусной близости.</li><li>Отдаём найденные фрагменты + вопрос языковой модели с инструкцией отвечать только по контексту.</li></ol><p>Такая схема легко масштабируется: можно заменить локальную Ollama на OpenAI, Anthropic или российские модели, а векторы перенести в Qdrant или Chroma.</p><h2>Что понадобится</h2><ul><li>Python 3.9+</li><li>Библиотека requests</li><li>Локально запущенная Ollama с моделями nomic-embed-text и llama3</li><li>Доступ к API извлечения текста (в примере — <a href="https://rapidapi.com/xiaobao882026/api/web-to-markdown-json-api" rel="noopener noreferrer">Web to Markdown/JSON API</a>; бесплатный тариф даёт 50 запросов в сутки)</li></ul><h2>Код бота</h2><p>Сохраните скрипт как rag_bot.py и подставьте свой ключ, если сервис извлечения текста требует авторизации:</p><p><b>На что обратить внимание:</b><br />Если вы используете RapidAPI-версию сервиса, запрос к API_URL обычно требует заголовка X-RapidAPI-Key. Без ключа бесплатный endpoint может вернуть 401.</p><h3>Разбор по частям</h3><p>fetch_markdown — единственный внешний вызов. Сервис сам забирает страницу, убирает навигацию, баннеры и футер и возвращает Markdown: заголовки, абзацы, списки. Это освобождает от зависимостей вроде BeautifulSoup или headless Chrome.</p><p>chunk_markdown режет текст на фрагменты примерно по 1200 символов, не разрывая абзацы. Мелкие чанки дают более точный ретривл, но увеличивают число эмбеддингов; для начала 1200 символов — хороший баланс.</p><p>embed и cosine превращают текст в векторы и считают их близость. Модель nomic-embed-text из Ollama бесплатна, быстрая и неплохо понимает русский и английский.</p><p>answer эмбеддит вопрос, выбирает три самых похожих чанка и строит промпт с жёстким ограничением: отвечать только по контексту. Это главная страховка от галлюцинаций.</p><h2>Запуск</h2><p>Установите зависимости и скачайте модели в Ollama:</p><p>Если всё в порядке, в консоли появится примерно такой результат:</p><h2>Почему важен чистый Markdown</h2><p>Если скормить эмбеддинг-модели сырой HTML, в векторах окажутся теги &lt;div&gt;, меню навигации и копирайты из футера. В результате поиск похожести выдаст «Copyright © 2026» вместо полезного ответа. Чистый Markdown — заголовки, абзацы, списки — улучшает качество ретривла почти бесплатно.</p><p>Если не хочется зависеть от внешнего API, можно заменить fetch_markdown на один из альтернативных вариантов:</p><ul><li><a href="https://github.com/adbar/trafilatura" rel="noopener noreferrer">trafilatura</a> — библиотека на Python для извлечения главного текста.</li><li><a href="https://r.jina.ai/http://example.com" rel="noopener noreferrer">r.jina.ai/http://URL</a> — бесплатный сервис без ключа.</li><li><a href="https://www.firecrawl.dev/" rel="noopener noreferrer">Firecrawl</a> — API с поддержкой сканирования сайтов целиком.</li><li><a href="https://github.com/scrapingbee" rel="noopener noreferrer">ScrapingBee</a> — прокси + рендеринг для сложных страниц.</li></ul><p>Для российских разработчиков локальная Ollama особенно удобна: модели качаются бесплатно, не нужны иностранные карты, а инференс идёт на своём железе.</p><h2>Куда развивать</h2><ul><li>Направьте бота на документацию, чейнджлог или блог конкурента и задавайте вопросы по ним.</li><li>Замените Ollama на OpenAI, Anthropic, Gemini или российские модели — функция answer меняется в двух строках.</li><li>Сохраняйте эмбеддинги в векторную БД: Chroma, Qdrant или FAISS, чтобы индексировать сразу много страниц.</li><li>Используйте формат json вместо Markdown, если нужна структура: параграфы, заголовки, ссылки — отдельно.</li></ul><h2>Выводы</h2><p>RAG — не магия, а последовательность простых шагов: получить чистый текст, разрезать его на фрагменты, найти ближайшие к вопросу и отдать их модели. Весь минимальный пайплайн укладывается в короткий Python-скрипт, который можно запустить на своём ноутбуке.</p><blockquote>RAG работает ровно так хорошо, каков текст, который вы ему скармливаете. Уберите самую утомительную часть — очистку HTML, — и останется интересное: поиск и генерация.</blockquote><p>Исходник идеи — статья <a href="https://dev.to/bao001_xiao_37db0a18ce6b2/chat-with-any-website-build-a-rag-bot-in-60-lines-of-python-1m1k" rel="noopener noreferrer">«Chat With Any Website: Build a RAG Bot in ~60 Lines of Python»</a>. Попробуйте собрать бота на своей странице и посмотрите, где он справляется, а где начинает фантазировать.</p>]]></content:encoded>
    </item>
    <item>
      <title>S3 в инфраструктуре: где объектное хранилище помогает, а где не заменит файловую систему</title>
      <link>https://tproger.ru/articles/s3-v-infrastrukture-gde-obektnoe-hranilishhe-pomogaet-a-gde-ne</link>
      <comments>https://tproger.ru/articles/s3-v-infrastrukture-gde-obektnoe-hranilishhe-pomogaet-a-gde-ne?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Дима Дмитриев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/s3-v-infrastrukture-gde-obektnoe-hranilishhe-pomogaet-a-gde-ne</guid>
      <description><![CDATA[<p>Разбираем, где S3 подходит для бэкапов, архивов, логов и медиаданных, а где нужны файловые или блочные хранилища. Versioning, Object Lock, репликация и практический пилот перед миграцией.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/s3-v-infrastrukture-gde-obektnoe-hranilishhe-pomogaet-a-gde-ne">S3 в инфраструктуре: где объектное хранилище помогает, а где не заменит файловую систему</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Форматы хранения данных]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 18 Aug 2026 07:16:51 GMT</pubDate>
      <content:encoded><![CDATA[<p>Объём бэкапов, логов и медиаконтента растёт быстрее бюджета на инфраструктуру, а требования к сохранности и восстановлению данных становятся жёстче. В какой-то момент файловое хранилище начинает требовать всё больше дисков, контроллеров и внимания команды.</p><p>У <a href="https://linx.ru/cloud/object-storage-s3/">S3-совместимого объектного хранилища</a> другая логика: приложение обращается к объектам через API, а вопросы физического размещения и масштабирования решает сама система хранения. Для бэкапов, архивов и медиаданных модель такого рода подходит хорошо, однако перед переходом на нее важно проверить, как конкретное приложение работает с объектами и что произойдет с данными при нагрузке или восстановлении.</p><h2>Как устроено S3</h2><p>В объектном хранилище данные организованы в бакеты, где у объекта три составляющие: содержимое, уникальный ключ и метаданные. Вложенных директорий в привычном смысле здесь нет — папки в интерфейсах появляются потому, что ключ объекта разбирают по разделителю. Например, backups/2026/08/db-dump.tar.gz читается человеком как путь по папкам, а для хранилища — просто одна строка-идентификатор.</p><p>В отличие от файловой системы, где приложение может открывать файл, записывать данные частями, дополнять его и использовать блокировки, S3 работает с объектами через API. Объект загружается целиком, а изменения выполняются отдельными операциями API.</p><p>Переименование объекта выполняется копированием под новым ключом с последующим удалением исходного — приложению, которое часто переименовывает или дописывает файлы либо использует файловые блокировки, потребуется изменить логику работы с данными при переходе на S3.</p><p>Управляется модель небольшим набором предсказуемых HTTPS-операций.</p><figure><img src="https://media.tproger.ru/user-uploads/99633/2026-08-17/17660b4e-f38e-42ec-8d53-d73765978182.webp" alt="" /></figure><p>S3 API используется разными объектными хранилищами, однако поддерживаемые функции могут различаться. Перед миграцией стоит проверить конкретные API-операции приложения, политики доступа, уведомления, Object Lock, репликацию и подпись запросов. Совместимость проверяют на рабочих сценариях приложения и часто в них применяемых API-операциях.</p><h2>Где подходит модель</h2><p>Зная, как устроена модель, проще понять, где S3 подходит лучше всего. Он хорошо работает с данными, которые сохраняются целыми объектами, хранятся независимо друг от друга и читаются по ключу. Например, так удобно хранить резервные копии, архивы, медиаконтент, логи и аналитические данные.</p><figure><img src="https://media.tproger.ru/user-uploads/99633/2026-08-17/e6bf3c95-a2f8-4ec9-8fb5-b94492c8b212.webp" alt="" /></figure><p>Для задач с частыми синхронными изменениями нужна другая модель хранения. Например, для дисков виртуальных машин, транзакционных логов СУБД, рабочих каталогов сборки и приложений с POSIX-блокировками подходит блочное или файловое хранилище. S3 при этом можно использовать для снапшотов, регулярных выгрузок и резервных копий.</p><h2>Что защищает данные внутри S3 и где заканчивается эта защита</h2><p>Для критичных данных в S3 используются versioning, Object Lock и репликация. Эти функции решают разные задачи и применяются в разных сценариях.</p><p>Versioning сохраняет предыдущие версии объектов. При повторной записи по тому же ключу создаётся новая версия с собственным version ID. DELETE добавляет delete marker, поэтому предыдущие версии остаются доступными для восстановления.</p><p>Versioning увеличивает объём хранения. Приложение, которое ежедневно переписывает крупный объект, создаёт последовательность его полных версий. Lifecycle-политика позволяет определить срок хранения старых версий и правила очистки незавершённых multipart-загрузок. Versioning переводится в состояние suspended, а полностью отключить его нельзя. При создании бакета с Object Lock versioning включается автоматически.</p><p>Object Lock реализует модель WORM, Write Once, Read Many. Для объекта задаётся срок retention, в течение которого система сохраняет его в защищённом состоянии.</p><p>В режиме Governance пользователь с расширенными правами может снять защиту вручную. В режиме Compliance защищённая версия сохраняется до окончания retention, включая случаи с root-аккаунтом. Срок хранения стоит рассчитывать заранее: установленный retention нельзя сократить, поэтому версия продолжит занимать место до окончания заданного периода.</p><p>Репликация создаёт дополнительные копии объектов и повышает устойчивость к отказам оборудования. В <a href="https://linx.ru/cloud/object-storage-s3/">Linx Cloud</a> используется фактор репликации 3, RF3, поэтому каждый объект хранится в трёх экземплярах.</p><p>Репликация переносит изменения вместе с объектами. Если исходные данные уже содержат логическую ошибку, она попадёт и в реплики. Для критичных данных поэтому требуется отдельный домен отказа, регулярная проверка восстановления и схема резервного копирования 3-2-1 или 3-2-1-1-0.</p><h2>Своя инфраструктура или сервис провайдера</h2><p>S3-сервис можно развернуть внутри собственной инфраструктуры или использовать как управляемую услугу провайдера. На уровне приложения подключение выглядит одинаково: endpoint, access key, secret key и S3 API — разница в эксплуатации инфраструктуры.</p><figure><img src="https://media.tproger.ru/user-uploads/99633/2026-08-17/3a92450a-1f79-4be0-a4f6-81d5b0741d6c.webp" alt="" /></figure><p>Перед выбором провайдера стоит свериться с матрицей ответственности — кто чинит платформу при сбое, кто управляет ключами и доступом, кто следит за квотами и кто в итоге отвечает за резервные копии данных. Такая матрица для S3 есть и у Linx Cloud — сверить её с внутренними регламентами команды стоит ещё до того, как сервис запущен в работу.</p><h2>Как это устроено у Linx Cloud</h2><p>Если выбор сделан в пользу провайдера, вот пример конкретной реализации. В основе сервиса <a href="https://linx.ru/cloud/object-storage-s3/">Объектное хранилище (S3)</a> в Linx Cloud — Ceph: мы выбрали его из-за совместимости с S3 API (по нашему опыту, полнее её реализует разве что сам AWS), а также из-за масштабируемости и гибкости для развития продукта.</p><p>Путь запроса такой: HTTPS endpoint → сетевой периметр с WAF и NGFW → балансировщики нагрузки → Ceph Object Gateway (RGW), который уже разбирает команды S3 API и передаёт операции в backend-кластер. Сами объекты лежат на OSD-узлах с репликацией в три копии (RF3), а управляющие компоненты кластера вынесены на отдельное оборудование.</p><p>Подключиться к сервису можно по интернету или по выделенному каналу точка-точка — из виртуального ЦОД Linx Cloud, серверной стойки в дата-центре Linx или с любой внешней площадки. По документации сервис поддерживает multipart upload, versioning, Object Lock/WORM, presigned URL, репликацию бакетов и lifecycle-правила удаления. Один PUT рассчитан максимум на 5 Гбайт — для объектов крупнее нужен multipart.</p><p>Этого достаточно для типовых задач: интеграции с Veeam, архивного хранения, выдачи приватных объектов по временным ссылкам. Но перед миграцией конкретного приложения тест всё равно нужен — оно может опираться на уведомления о событиях, свою схему управления пользователями, определённый способ адресации объектов или редкую операцию API.</p><h2>Что проверить на пилоте</h2><p>Каким бы ни было решение — свой кластер или сервис вроде Linx Cloud — переводить на него прод стоит только после пилота, и строить его нужно на реальном потоке данных приложения: одна команда aws s3 cp с тестовым файлом ничего не покажет.</p><ul><li>Поэтому сначала измеряется профиль данных: средний и максимальный размер объектов, общее количество объектов, соотношение GET и PUT, частота LIST, пиковая нагрузка и допустимая задержка.</li><li>Затем проверяется совместимость приложения с нужными функциями S3. В тест входят multipart, versioning, Object Lock, lifecycle, presigned URL и права доступа. Для каждого механизма важно проверить именно тот сценарий, который используется в рабочей системе.</li><li>После этого оцениваются сеть и безопасность. Тест показывает поведение канала под нагрузкой, работу при обрыве соединения, доступные маршруты и стоимость исходящего трафика. На уровне безопасности проверяются разделение прав, хранение и ротация ключей, шифрование, аудит операций и сценарий компрометации учётной записи.</li><li>Финальная часть пилота посвящена восстановлению и стоимости. Нужно выполнить возврат старой версии и полное восстановление данных, измерить объём накопленных неактуальных версий и рассчитать расходы на запросы, хранение и трафик с учётом ожидаемого роста данных.</li></ul><p>Критерий успеха зависит от сценария. Для бэкапов главное — успешное восстановление, факта одной только загрузки недостаточно. Для медиаконтента важна стабильная выдача и то, что временные ссылки действительно работают.</p><p>Для data lake — скорость, с которой выбранный аналитический стек читает данные, и отсутствие «болезни мелких файлов», когда объектов становится очень много. Одна и та же <a href="https://linx.ru/cloud/object-storage-s3/">платформа S3</a> может отлично закрывать один сценарий и требовать уже другого архитектурного решения в соседнем.</p><h2>Вместо вывода</h2><p>S3 подходит для бэкапов, архивов, медиаконтента и аналитических данных, которые хранятся и читаются как объекты. Для дисков ВМ, СУБД и рабочих каталогов с частыми изменениями больше подходят файловые и блочные хранилища.</p><p>Поэтому перед миграцией стоит провести пилот на реальных данных приложения: проверить нагрузку, нужные API-операции, восстановление и стоимость хранения с учётом трафика. Результаты помогут определить, какую часть инфраструктуры имеет смысл перевести на S3 и где сохранить другие типы хранилищ.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как я написал AI-бота на aiogram 3 с помощью нейросетей, выжил при 2500+ пользователей и почему SQLite "всё ещё торт"</title>
      <link>https://tproger.ru/articles/kak-ya-napisal-ai-bota-na-aiogram-3-s-pomoshhyu-nejrosetej-vyzhil-p</link>
      <comments>https://tproger.ru/articles/kak-ya-napisal-ai-bota-na-aiogram-3-s-pomoshhyu-nejrosetej-vyzhil-p?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Нуя]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-ya-napisal-ai-bota-na-aiogram-3-s-pomoshhyu-nejrosetej-vyzhil-p</guid>
      <description><![CDATA[<p>Технический кейс создания Telegram-бота Щёлк-ГДЗ (ИИ-репетитор по фото). Разбор архитектуры на Python (aiogram 3, aiosqlite), работы с API Gemini и решения проблем под нагрузкой 2500+ пользователей. </p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-ya-napisal-ai-bota-na-aiogram-3-s-pomoshhyu-nejrosetej-vyzhil-p">Как я написал AI-бота на aiogram 3 с помощью нейросетей, выжил при 2500+ пользователей и почему SQLite "всё ещё торт"</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Telegram]]></category>
      <category><![CDATA[MIT]]></category>
      <category><![CDATA[Flash]]></category>
      <category><![CDATA[Redis]]></category>
      <category><![CDATA[Маркетинг]]></category>
      <category><![CDATA[аналитик]]></category>
      <category><![CDATA[микро]]></category>
      <category><![CDATA[Пет-проект]]></category>
      <category><![CDATA[Бизнес]]></category>
      <category><![CDATA[VPS]]></category>
      <category><![CDATA[Hardware]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 26 Jul 2026 15:47:08 GMT</pubDate>
      <content:encoded><![CDATA[<p>На дворе 2026 год. Очередной постмортем микро-SaaS'а в Телеге.</p><p>Без маркетинга и успешного успеха. Только боль, костыли и суровый прод! Мой пет-проект - бот «Щёлк-ГДЗ». Это ИИ-помощник, который решает школьные задачки по фоткам, видео, гс, тг-кружкам и PDF. Под капотом <b>Python 3.12.3</b>, <b>aiogram 3</b>, <b>aiosqlite</b>,<b> апи OpenRouter </b>(модель Gemini 3.0 Flash) и <b>Робокасса</b>. Крутится всё это на дешёвом VPS в Нидерландах. Держит 2500+ пользователей и не падает.</p><p>В этой статье расскажу, как за 9 месяцев построил логичную архитектуру, победил ошибку FloodWait при стриминге ответа ИИ и почему в условиях 1 гига RAM обычная SQLite - отличное решение.</p><h2>Нейронка вместо джуна и Уроборос багов</h2><p>Сразу признаюсь... С нуля я это не писал :) Синтаксис мне генерили LLM-ки. Начинал с Gemini 2.5 Pro, затем перешел на 3.0 Pro, а сейчас использую 3.1 Pro.</p><p>Многие думают, что нейронка сама напишет проект "под ключ", но это миф. Я <b>никогда </b>не доверял ИИ проектирование архитектуры и использовал его как продвинутый<i> StackOverflow</i> (скармливал конкретную задачу (например, написать SQL-миграцию) и получал кусок кода).</p><p><i>ИИ — это не архитектор, а джун на спидах. </i></p><p>Как только логика усложнялась - гемини ловил <b>«Уроборос багов»</b>. Кидаешь баг <b>А</b> - он его фиксит, но появляется ошибка <b>Б</b>. Скармливаешь и её - фиксит, но возвращается баг <b>А</b>. Цикл замкнулся. Лечилось только созданием новых чатов, в которые я кидал код и писал запросы типа "Найди критические ошибки, логические дыры и баги".</p><p>Про продуктовую логику нейронка вообще не слышала. В первой версии рефералки был баг, где любой(если его аккаунта ещё нет в БД) мог написать в конце ссылки что любые 9 цифр (<i>?start=1234567890</i>) и получить бонусы.</p><p>Также были ошибки с гонкой состояний при оплатах и активациях промокодов, которые тоже фиксил запросами в новые чаты с ИИ. Так я исправил около 20 архитектурных дыр.</p><h2>Немного про архитектуру.</h2><p>Чтобы код не превратился в нечитаемую лапшу на 5000 строк, я жестко разбил всё на модули. Архитектура бота выглядит так:</p><figure><img src="https://media.tproger.ru/user-uploads/139416/2026-07-08/dfc8dd70-365f-4f70-bbbf-2b00b503bef4.webp" alt="" /></figure><p><b>main.py</b> - это точка входа с настройкой логгеров, коннетами aiohttp и запуском APScheduler</p><p><b>database.py</b> - вся работа с БД</p><p><b>neiro.py</b> - логика общения с апи OpenRouter (стриминг, сжатие фоток через Pillow, JSON-контекст)</p><p><b>states.py</b> - классы состояний aiogram.fsm.state (например, PaymentProcess, GdzMode)</p><p><b>utils.py</b> - легковесные утилиты. Например лок пользователей (защита от спама запросами):</p><p>Хэндлеры вынесены в отдельную папку handlers/:</p><p><b>handlers/common_handlers.py</b> - главное меню с обработкой /start (рефералки, utm-метки).</p><p><b>handlers/gdz_handlers.py</b> - сам процесс ИИ-решения (вход в GdzMode, прием фото, видео, кружочков).</p><p><b>handlers/pay_handlers.py</b> - это логика платежей (Robokassa) и "Умная корзина".</p><p><b>handlers/tasks_handlers.py</b> - квесты (выдача премиума за подписку на каналы спонсоров).</p><p>Сборку интерфейсов вынес в <b>all_def.py</b>. Не люблю, когда в хэндлерах генерится полотно текста с кнопками. Там же лежат функции склонения слов (1 запрос, 2 запроса, 5 запросов). А в <b>settings.py </b>лежат списки с рандомными ответами бота, чтоб казался живым.</p><p>Так же в <b>settings.py</b> я сделал кэширование картинок, тоесть при первом запуске бот грузит фото меню как <b>BufferedInputFile</b>, сохраняет <b>file_id</b> от Телеграма и дальше шлет картинки моментально по ID. Сервак говорит спасибо за сэкономленный трафик)</p><p>В <b>handlers/common_handlers.py</b> находится первичная маршрутизация. Вот так обрабатываются рефералки, переходы с сайта, с рекламы и другое при старте:</p><h2>Диета по токенам</h2><p>Хранить бесконечную историю диалогов дорого и бессмысленно. В бесплатной версии храню <b>10 последних сообщений</b> (5 пар вопрос-ответ), а в преме — <b>30. </b></p><p>Но фотки весят большое кол-во токенов. Если премиум-юзер закинет 30 фоток, OpenRouter выставит мне огромный счет. В итоге я прикрутил ограничение: Из <b>30 сообщений</b> ИИ видит только <b>10 последних картинок. </b></p><p>Старые фотки тупо вырезаю из JSON. Подменяю на системный промпт:</p><p>С довольно неплохой моделью (gemini 3.0 flash) это работает как часы (она честно признается, что забыла картинку, а не выдумывает что-то из воздуха).</p><h2>Стриминг, FloodWait и защита баланса</h2><p>Чтобы бот не выглядел тормозом, я сделал стриминг ответа от ИИ в <b>neiro.py</b>. Я обновляю сообщение в Телеграме чанками по мере получения их от ОпенРоутера.</p><p>Но если делать <b>message.edit_text </b>слишком часто, ловишь <b>FloodWait</b>. В итоге я выставил интервал в 0.7 секунд и обернул всё в жесткий<b> try/except</b>:</p><p>Стрим при этом не прерывается. Поспали и погнали дальше :) Если на этапе обработки файла или стриминга падает критическая ошибка - честно возвращаю юзеру запрос на баланс.</p><p>В <b>handlers/gdz_handlers.py</b> это выглядит так:</p><h2>SQLite тащит</h2><p>Почему не <b>Postgre</b>? Потому что для микро-SaaS с 2,5к пользователей<b> SQLite</b> хватает за глаза. Но в асинхронной среде она любит кидать ошибку <b>database is locked</b>.</p><p>Чтобы этого избежать, я включил <b>WAL-режим</b> при инициализации пула, разделил коннекты на <b>db_writer</b> и <b>db_reader</b>, а сложные операции доверил самому <b>SQL</b>.</p><p>Например, 00:00 запускается крон-таска, которая собирает огромную аналитику, начисляет всем активным юзерам +1 ежедневный запрос и сбрасывает просроченные подписки. И это всё это работает атомарно внутри <b>database.py</b>:</p><h2>Умная корзина на APScheduler</h2><p>Когда дело дошло до монетизации, всплыли две проблемы:</p><p>Первая: юзер оплатил, но забыл нажать кнопку <b>«✅ Я оплатил»</b> в боте. Бот ждет, юзер ждет, товар не выдается, поддержка кипит.</p><p>Вторая: юзер сформировал счёт и передумал ("брошенная корзина").</p><p>Вместе с LLM я с нуля изучил <b>apscheduler </b>и убил двух зайцев фоновыми задачами. Теперь в <b>handlers/pay_handlers.py </b>при генерации ссылки на оплату я создаю две отложенные таски:</p><h4>Как это работает?</h4><p>Через 5 минут срабатывает <b>async def auto_check_payment()</b>, которая тихо стучится в робокассу. Если статус<b> success</b> - бот сам начисляет запросы на баланс и радует клиента. Если статус <b>pending</b> - таска умирает, и в дело вступает 30-минутная таска.</p><p>Но она не шлёт спам вслепую, а лезит в БД и проверяет 3 бизнес-правила:</p><p>1. <b>await db.has_successful_payment_recently</b> - Не купил ли он другой товар за последние 3 часа?</p><p>2. <b>await db.get_latest_invoice_id</b> - А это точно самый последний сгенерированный им счет?</p><p>3. <b>await db.can_send_agitation</b> - Не присылали ли мы ему агитацию недавно?</p><p>Если проверки пройдены, то юзер получает сообщение: <i>"⏳ Домашка сама себя не решит! Ты начал оформлять покупку, но оплата так и не прошла..."</i>. Это поднимает конверсию оплат.</p><h2>Финал</h2><p>Почему я не использую <b>Redis </b>для стейтов? Ответ банален: мой дешевый VPS имеет всего 1 гб оперативки. Пул <b>aiohttp</b>, In-Memory стейты и асинхронные таски и так жрут 70% RAM. Редис тупо не влезет.</p><p>Как говорится, <i>работает — не трогай.</i></p><p>Сейчас проект обзавелся сайтом-витриной и продолжает развиваться. В планах - искать и чинить новые баги. Перееду на более мощное железо, когда сервак начнет физически задыхаться.</p><p>Готов ответить на вопросы по архитектуре и послушать советы в комментариях \(^^)/</p><p><i>P.s. вот ссылка на первую статью о моём проекте: </i></p><p>P.s. Если кто-то хочет потестить вживую(не реклама), то юз бота в тг <a>@gdzshchelk_bot</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Своя self-hosted двухсерверная VPN-архитектура. Подробный путь разработки и ошибки, с которыми вы можете столкнуться</title>
      <link>https://tproger.ru/articles/svoya-self-hosted-dvuhservernaya-vpn-arhitektura-podrobnyj-put-r</link>
      <comments>https://tproger.ru/articles/svoya-self-hosted-dvuhservernaya-vpn-arhitektura-podrobnyj-put-r?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Роман Фролов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/svoya-self-hosted-dvuhservernaya-vpn-arhitektura-podrobnyj-put-r</guid>
      <description><![CDATA[<p>Проект представляет из себя быстрый способ воссоздать архитектуру состоящую из 2 серверов (локальный + удаленный) с определенными сервисами, которые решают специфические задачи. Проект сделан прежде всего для меня, а также для людей которые хотят свой готовый self-hosted сервер из коробки с полной системой обслуживания</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/svoya-self-hosted-dvuhservernaya-vpn-arhitektura-podrobnyj-put-r">Своя self-hosted двухсерверная VPN-архитектура. Подробный путь разработки и ошибки, с которыми вы можете столкнуться</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Тестирование]]></category>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Ruby]]></category>
      <category><![CDATA[unix]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Музыка]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[HTML]]></category>
      <category><![CDATA[DIY]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[Навыки]]></category>
      <category><![CDATA[VPN]]></category>
      <category><![CDATA[Telegram]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Docker]]></category>
      <category><![CDATA[Cloudflare]]></category>
      <category><![CDATA[Фронтенд]]></category>
      <category><![CDATA[Redis]]></category>
      <category><![CDATA[QA]]></category>
      <category><![CDATA[Мессенджер]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[NFT]]></category>
      <category><![CDATA[Машин]]></category>
      <category><![CDATA[1C]]></category>
      <category><![CDATA[DeFi]]></category>
      <category><![CDATA[Grafana]]></category>
      <category><![CDATA[VPS]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 26 Jul 2026 15:46:26 GMT</pubDate>
      <content:encoded><![CDATA[<p>Всё
 началось с того, что меня перестал устраивать мой подход к 
развертыванию личных сервисов. Я решил переписать всё с нуля. К тому же 
это был отличный повод получить новые навыки и попробовать инструменты, 
до которых давно не доходили руки.</p><p>Арендовать мощные VPS под 
ресурсоемкие задачи в текущих реалиях выходит неоправданно дорого. При 
этом дома у меня уже был выделенный неттоп (мини-ПК) с 16 ГБ оперативной
 памяти на базе энергоэффективного процессора Intel N95.</p><p>Пройдя 
путь от простых Bash-скриптов и сторонних туннелей до полностью 
автоматизированной инфраструктуры, я создал проект ServeHub-2. В этой 
статье я подробно разберу, как эволюционировала сеть проекта, почему 
декларативный подход победил императивный и с какими неочевидными багами
 пришлось столкнуться в процессе автоматизации.</p><h2>История настройки сетевой архитектуры</h2><h3>Использование Tuna</h3><p>В
 самом начале проекта я еще не думал о VPN как о способе пробития NAT и 
основе, на которой будет строиться вся система. Первое, к чему я пришел —
 сервис Tuna. Если кратко, это аналог Cloudflare Tunnel за условные 300 
рублей. У него очень приятный веб-интерфейс и невероятно простая 
настройка. Однако для полноценной независимой архитектуры он не подошел 
по двум причинам:</p><ul><li>Сервера Tuna находятся вне контроля пользователя.</li><li>На удаленном сервере нельзя развернуть свои сопутствующие сервисы.</li></ul><p>В целом сервис действительно удобный, но для моих задач он оказался слишком ограничивающим.</p><p>Вот
 пример конфига для tuna (все максимально просто, создаем контейнеры для
 ssh туннеля, чтобы был доступ ssh, а также основной http туннель с 
привязкой к nginx или любому другому прокси если такой есть):</p><h3>В поисках гибкости: тесты Pangolin и переход к FRP</h3><p>После Tuna я решил двигаться в сторону собственного контроля и попробовал Pangolin.
 Однако решение быстро отвалилось: для дешёвого сервера оно оказалось 
слишком «тяжёлым» и избыточным. Главные минусы — ощутимый оверхед по 
ресурсам и лишний слой принудительной веб-аутентификации перед самими 
сервисами. Это ломало нормальное взаимодействие с родными мобильными 
клиентами (вроде Element для Matrix или Bitwarden для паролей), где 
повторная авторизация в браузере просто не нужна.</p><p>На смену пришел FRP (Fast Reverse Proxy).
 Он выполнял ту же функцию проброса, но хостил я его уже на собственном 
арендованном VPS в режиме Layer 4 (TCP). Это дало абсолютную гибкость: 
внешний VPS не заглядывал внутрь пакетов и ничего не расшифровывал, а 
просто пересылал сырой поток домой. Кроме того, это отлично 
оптимизировало расходы: вместо 300 рублей за Tuna и ещё 300 рублей за 
отдельный VPN, я стал платить всего 500 рублей за один стойкий VPS, 
который мог настраивать как хочу. (к тому же можно было обойтись даже 
дешевле, так как VPS с 4 гб оперативки загружен всего лишь на 40%, 
процессор всего на 20%-40%)</p><p>FRP состоит из 2 конфигурационных 
файлов (один на удаленном сервере frp server, другой на локальном frp 
client), все также довольно просто, однако его можно использовать на 
разных слоях. У меня он брал трафик за стандартный TCP и передавал его 
на локальный сервер.</p><p>Также доп. фишка в том что основная 
конфигурация происходит именно в frpc, который, в свою очередь, передает
 часть настроек на frp на удаленном сервере.</p><p>frpc.toml:</p><p>frps.toml:</p><h3>Полноценный переезд на WireGuard (AmneziaWG) и 8 часов отладки</h3><p>Со временем архитектура эволюционировала в сторону полноценной VPN-сети на базе WireGuard, а точнее — его модификации AmneziaWG. Причин для этого шага было несколько:</p><ul><li>Безопасность: FRP всё же открывал внутренние ресурсы в публичный интернет, оставляя их доступными для сканеров портов.</li><li>Удобство маршрутизации:
 Все участники сети стали равноправными узлами в одной виртуальной 
локальной подсети. Больше не нужно было настраивать постоянные 
односторонние пробросы.</li><li>Дополнительный бонус:
 Поскольку удаленный VPS был куплен в Нидерландах, через этот же VPN я 
автоматически получил безопасный доступ ко всем зарубежным ресурсам.</li></ul><p>Для реализации схемы на удаленном VPS был развернут контейнер wg-easy с поддержкой AmneziaWG, а на домашнем мини-ПК — клиентский контейнер Amnezia (сборка из Dockerfile с использованием amnezia-tools  и модулем ядра хоста).</p><p>И
 именно здесь я поймал самый изнурительный баг проекта. После 
развертывания трафик упорно шёл только в одну сторону. Часов 8 ушло на 
диагностику iptables, маршрутов и чтение зарубежных форумов (что 
бесполезно, учитывая специфику наших блокировок). Оказалось, провайдер 
просто дропал обратный трафик стандартного WireGuard, так как пакеты шли
 без маскировки. Причина крылась в docker-compose.yml: у меня было прописано image: ghcr.io/wg-easy/wg-easy:latest. Как выяснилось, тег latest  на Docker Hub намертво прилип к старой 14-й версии, а поддержка параметров AmneziaWG появилась только в ветке 15.x. Изменение тега на конкретную версию (15.3) решило проблему за секунду.</p><p>Благодаря
 переходу конфигурация получилась максимально простой, основные отличия 
от стандартной документации выделил в коде: (в основном то, на что 
пришлось долго рыть информацию)</p><h3>Настройка Nginx</h3><p>Чтобы
 сервисы были доступны исключительно внутри подсети VPN, я задействовал 
Nginx. Доступ к приложениям был жестко ограничен на уровне конфигурации —
 веб-сервер принимает запросы только из диапазона IP-адресов 10.8.0.0/24. Любые попытки постучаться на сервер из внешнего интернета без активного VPN-туннеля автоматически сбрасываются Nginx.</p><p>Логика
 распределения завязана на proxy-протоколе: Nginx на удаленном VPS 
выступает основным входным узлом, принимает зашифрованный трафик, 
заворачивает его в заголовки с реальным IP-адресом клиента и через 
туннель перекидывает на локальный Nginx домашнего сервера. Локальный 
веб-сервер уже сам расшифровывает SSL и распределяет трафик по конечным 
Docker-контейнерам, сохраняя реальные IP в логах безопасности.</p><p>Вставлю
 один кусок кода из nginx на удаленной машине для примера, так все 
остальное примерно похоже (конфиги использовались в виде .template):</p><h3>SSL-сертификаты</h3><p>Для получения валидных SSL-сертификатов я настроил работу через автоматический Certbot по challenge-валидации DNS-01 c API Webnames. Сам домен привязан к внутреннему IP-адресу 10.8.0.1.
 Проверка через DNS позволила выпустить единый wildcard-сертификат на 
весь домен и его поддомены без необходимости держать открытым 80-й порт 
веб-сервера наружу.</p><p>Уточню, что certbot запускается автоматически 
во время выполнения Ansible плейбука, поэтому самому кроме указания 
переменных ничего делать не нужно.</p><p>В
 итоге получилась схема, при которой все сервисы доступны по красивым 
доменным именам с HTTPS, но абсолютно невидимы для внешнего интернета.</p><p>Вот настройка certbot:</p><h2>История софта</h2><p>Параллельно
 с сетевой структурой развивался и сам набор приложений. Изначально я 
хотел собрать в одном месте утилиты, которыми пользуюсь каждый день, но в
 процессе селфхостинга быстро понимаешь: нельзя просто накидать 
контейнеров и надеяться, что мини-ПК справится, а конфигурационные файлы
 не превратятся в кашу.</p><h3>Первый стек и оптимизация</h3><p>Первыми на домашнем сервере прижились медиа-сервисы: Navidrome для стриминга музыки и Audiobookshelf
 для аудиокниг и подкастов. Они легковесные, имеют отличные мобильные 
клиенты с синхронизацией прогресса и полностью закрывают мои 
потребности. Позже к ним добавился Nextcloud как единое независимое облако для файлов, контактов и семейных документов.</p><p>Затем встал вопрос безопасного хранения паролей. Сначала я смотрел в сторону оригинального Bitwarden, но в итоге я выбрал Vaultwarden
 — альтернативный сервер на Rust, полностью совместимый с API Bitwarden.
 Он потребляет считанные мегабайты оперативной памяти и работает 
идеально. Дополнительно для удобства управления всей этой распределенной
 Docker-инфраструктурой в локальный стек был добавлен Portainer. (+ Portainer Agent на удаленный сервер)</p><p>Из интересных моментов, где мне пришлось немного больше возиться, чем с остальными сервисами это nextcloud настройка:</p><h3>Ошибки проектирования: почему я удалил Matrix (Synapse)</h3><p>Не все решения прошли проверку временем. На этапе использования Tuna и FRP я развернул сервер Matrix (Synapse)
 для защищенного обмена сообщениями. Мне казалось это крутой идеей, но 
когда я окончательно перешел на AmneziaWG, целесообразность мессенджера 
внутри закрытого туннеля сошла на нет.</p><p>Synapse требовал слишком 
много ресурсов, впустую расходовал оперативку домашнего ПК и усложнял 
конфиг Nginx. При этом реальной пользы для семьи он не приносил. Для 
критических алертов инфраструктуры и повседневного общения проще и 
эффективнее оказалось использовать Telegram. (плюс алертинг настроен 
именно через него) В итоге я полностью выпилил Synapse из стека, 
освободив ресурсы.</p><p>Вместо него я добавил в связку к wg-easy локальный AdGuard Home.
 Теперь он работает прямо внутри VPN-сети: очищает весь трафик от 
рекламы и трекеров на лету, кэширует DNS-запросы и не дает истории 
веб-серфинга улетать внешним провайдерам.</p><p>Основной проблемой с 
которой я столкнулся при использовании AdGuard Home, так это то что я 
так и не понял как заставить использовать AmneziaVPN клиент AdGuard как 
основной DNS, при этом AmneziaWG работает прекрасно. Как я понимаю дело в
 том что AmneziaWG работает намного проще на уровне ip и у него нету 
никаких доп фильтров, настроек и подобного, поэтому он просто берет 
данные из конфига.</p><h3>От костылей на Bash к декларативному Ansible</h3><p>Весь
 стек на обоих серверах разворачивался через bash скрипты, что было уж 
очень плохо с точки зрения идемпотентности. Во первых из-за bash мне 
постоянно приходилось очищать сервера, так как нормальных проверок у 
меня не было и писать я их не хотел, а также было много костылей с 
импортом переменных, записями в файлы и подобным.</p><p>Так я пришел к декларативному подходу и Ansible.
 Теперь вся конфигурация описывается в виде плейбуков и ролей, 
отражающих конечное желаемое состояние серверов. Конфиденциальные данные
 перенесены в файл secrets.yml, а хрупкие конструкции 
автоматизированы через шаблоны Jinja2. Проект стал идемпотентным: если 
шаги уже выполнены, Ansible их просто пропускает.</p><p>В итоге 
получилось несколько yaml файлов для стандартной настройки системы 
(bootstrap_os.yml) и для настройки каждого из хостов (setup_local.yml и 
setup_remote.yml). В итоге теперь все что нужно чтобы полностью с нуля 
развернуть проект - скачать Ansible, несколько других зависимостей на 
свой рабочий пк и запустить один manage_deploy.sh, в котором можно будет
 выбрать сценарий как будет вести себя Ansible и спокойно дождаться 
разворачивания сервисов.</p><p>Также благодаря Ansible я удобно 
реализовал переносимость проекта. Так как я решил не использовать тома 
docker, и вместо этого храню все в папках, чтобы перенести старые данные
 проекта нужно просто скопировать папку apps-data и положить ее в нужное
 место и все само заработает после повторного развертывания проекта. В 
Ansible выделяется отдельная пауза для этого.</p><p>Вот пример основного плейбука deploy.yml:</p><h3>Тестирование мультидистрибутивности с помощью Vagrant</h3><p>Проект
 изначально затачивался под работу на трех дистрибутивах: Ubuntu, Debian
 и Arch Linux. Тестировать Ansible-плейбуки прямо на рабочей локальной 
машине (в моем случае — EndeavourOS) слишком рискованно, а создавать 
виртуальные машины руками — долго и неудобно.</p><p>Решением стал Vagrant,
 позволяющий за пару минут развернуть чистые ОС в VirtualBox из готовых 
образов. Но в процессе настройки мультивендорного стенда в режиме 
сетевого моста (public_network) всплыли две критические проблемы:</p><ol><li>Конфликт DNS:
 По умолчанию Vagrant создает NAT-интерфейс для управления нодой. При 
включении второго (публичного) интерфейса для локальной сети ломался 
дефолтный DNS-резолвер. Проблему пришлось решать принудительной очисткой
 и перезаписью файла /etc/resolv.conf через inline-скрипт автоматизации Vagrant.</li><li>Проблема с GRUB на Debian: В используемом базовом образе generic/debian12
 конфигурация GRUB сохраняла жесткую привязку к конкретному имени диска 
из окружения сборщика. При повторном развертывании плейбуков на тестовом
 стенде это приводило к сбоям загрузчика. Чтобы автоматизировать 
очистку, пришлось внедрить скрипт, который на лету определяет имя 
системного диска через lsblk и автоматически передает правильные параметры в загрузчик через утилиту debconf-set-selections.</li></ol><p>Вот код Vagrantfile: (в node.vm.provision происходит основное решение ошибок)</p><p>Надежная система бэкапов на базе BorgmaticДля создания резервных копий я внедрил Borgmatic
 (удобную надстройку над дедуплицирующим инструментом Borg Backup). Весь
 процесс автоматизирован с помощью связки системных юнитов borgmatic.service и borgmatic.timer. В бэкап уходят две ключевые директории: apps-data (конфигурации приложений и баз данных) и PersonalData (медиатека: музыка, книги, подкасты, файлы Nextcloud).</p><p>Развертывание
 системы бэкапов полностью берет на себя Ansible. Мне достаточно указать
 UUID внешнего жесткого диска — скрипт сам проверит его наличие в 
системе, примонтирует в нужную директорию, создаст зашифрованный 
репозиторий и настроит политику ротации (хранение 7 ежедневных, 4 
еженедельных и 6 ежемесячных копий). Также в Prometheus выведен 
мониторинг самого репозитория .borg для отслеживания его размера и статуса успешности архивации.</p><p>Главная
 проблема при бэкапе работающих Docker-контейнеров — риск скопировать 
базу данных в «битом» или неконсистентном состоянии, если в момент 
создания архива в нее шла активная запись. Чтобы решить эту проблему, я 
задействовал механизм хуков в конфигурации Borgmatic.</p><p>Перед началом резервного копирования автоматически срабатывает команда остановки контейнеров проекта (docker-compose down),
 а после успешного завершения (или в случае возникновения непредвиденной
 ошибки) контейнеры автоматически поднимаются обратно в фоновом режиме. 
Для удобного просмотра архивов и быстрого восстановления файлов я 
развернул веб-интерфейс Borg UI.</p><p>Конфигурация borgmatic: (использую как Jinja2 шаблон, чтобы Ansible в плейбуках сам подставил переменные)</p><h2>Наблюдаемость (Observability) уровня Enterprise</h2><p>В последних релизах (v1.2.0 и v1.3.0) фокус проекта сместился на мониторинг и работу с логами.</p><h3>Эволюция алертинга и переход на Gatus</h3><p>Изначально для мониторинга доступности я смотрел на Uptime Kuma, но отказался из-за отсутствия удобной декларативной настройки через конфиги. Затем я развернул связку Blackbox Exporter и Alertmanager
 с уведомлениями в Matrix. Но тут крылась логическая несостыковка: весь 
алертинг был завязан на локальном ПК, и в случае его аппаратного отказа я
 бы просто лишился уведомлений.</p><p>Тогда я решил вернуть Uptime Kuma,
 но развернуть его на удаленном VPS в качестве внешнего «сторожа» и 
автоматизировать его настройку через Python-скрипт с библиотекой uptime-kuma-api. Но и тут ждали «грабли» — библиотека не обновлялась три года и намертво ломалась на свежих версиях Kuma.</p><p>В итоге идеальным решением стал Gatus.
 Он изначально проектировался под управление через YAML-конфиги и 
поддерживает отправку алертов, если сервер не отвечает. Из-за специфики 
фронтенда Gatus (он не умеет работать из подкаталога типа /gatus), мне пришлось перенести его и wg-easy на полноценные субдомены gatus. и wireguard.</p><p>Для Gatus получился простой конфиг:</p><p>Для мониторинга аппаратных ресурсов удаленного и локального серверов была развернута связка node-exporter + cAdvisor. Все уведомления теперь приходят мгновенно в Telegram-бота. Чтобы 
избежать лавины одинаковых сообщений (например, при перезагрузке хоста),
 в Alertmanager настроена жесткая группировка и дедупликация событий. 
Также добавлен экспортер для AdGuard Home, выводящий статистику 
заблокированных запросов в Grafana.</p><h3>Централизованные логи: Loki + Grafana Alloy</h3><p>В релизе v1.3.0 в стек была добавлена централизованная система сбора логов Loki. Вместо устаревшего Promtail в качестве агента сбора я применил Grafana Alloy.</p><p>Он
 эффективно собирает логи со всех запущенных Docker-контейнеров, парсит 
их и передает в Loki. Теперь вся история событий, ошибок веб-сервера 
Nginx или падений внутренних приложений доступна в едином интерфейсе 
Grafana с возможностью удобной фильтрации через LogQL, что значительно 
упрощает отладку.</p><p>Конфиг Loki:</p><p>Конфиг Grafana Alloy: (локальный конфиг)</p><h2>Интерфейс: переход на Homepage</h2><p>Изначально для 
домашней страницы я написал кастомную минималистичную HTML-панель с 
Glassmorphism-дизайном. Выглядело это красиво, но добавлять новые 
сервисы вручную через постоянную правку исходного кода было крайне 
неудобно.</p><figure><img src="https://media.tproger.ru/user-uploads/139471/2026-07-15/8a8f2752-8aac-4aa5-898e-98affd01cdff.webp" alt="" /><figcaption>HTML + CSS</figcaption></figure><p>В итоге я заменил самописную страницу на полноценный комьюнити-проект Homepage.
 Это дало некоторую гибкость: вся панель настраивается через простые 
YAML-файлы и поддерживает встроенные виджеты интеграции. Пока что она 
простенькая, но возможно в будущем сделаю что-то более продвинутое.</p><figure><img src="https://media.tproger.ru/user-uploads/139471/2026-07-15/90c65d4a-1310-4a30-b1ad-9e4d3083959d.webp" alt="" /><figcaption>Homepage</figcaption></figure><h2>Заключение</h2><p>Постарался
 подробно рассказать о структуре проекта и как я к этому пришел, очень 
много я не добавил, если пост зайдет, то я обязательно более подробно 
пройдусь по некоторым моментам: как я настраивал Matrix и на каком 
моменте я решил его убрать, как собирал локальный amnezia 
контейнер-клиент, что нового я добавил в релизе 1.4.0 и другое.</p><p>Также
 я перешел с manage_deploy.sh на отдельный GUI клиент, который 
будет полностью автоматизировать процесс подготовки к deploy. (написан на Go Wails). Про это тоже возможно сделаю статью.</p><p>Вся кодовая база проекта, подробная документация, инструкции по развертыванию открыты и доступны для сообщества:</p><p>🔗 GitHub-репозиторий: <a href="https://github.com/canntstand/ServeHub-2" rel="noopener noreferrer nofollow">https://github.com/canntstand/ServeHub-2</a></p><p>Это
 моя первая статья на этом сайте и в то же время первый личный проект, которому я 
отдал так много времени (3 месяца). Буду рад вашему фидбеку в 
комментариях!</p>]]></content:encoded>
    </item>
    <item>
      <title>MCP отказывается от сессий: протокол ИИ-агентов становится stateless</title>
      <link>https://tproger.ru/news/mcp-otkazyvaetsya-ot-sessij-protokol-ii-agentov-stanovitsya-state</link>
      <comments>https://tproger.ru/news/mcp-otkazyvaetsya-ot-sessij-protokol-ii-agentov-stanovitsya-state?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/mcp-otkazyvaetsya-ot-sessij-protokol-ii-agentov-stanovitsya-state</guid>
      <description><![CDATA[<p>Новый релиз-кандидат MCP убирает handshake и Mcp-Session-Id. Разбираем, почему это важно для масштабирования ИИ-агентов и что ждёт разработчиков.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/mcp-otkazyvaetsya-ot-sessij-protokol-ii-agentov-stanovitsya-state">MCP отказывается от сессий: протокол ИИ-агентов становится stateless</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Сетевые протоколы]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Инфраструктура]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 21 Jul 2026 11:35:20 GMT</pubDate>
      <content:encoded><![CDATA[<p>MCP перестаёт быть протоколом «один клиент — один сервер». Релиз-кандидат спецификации 2026-07-28, зафиксированный 21 мая 2026 года, полностью убирает handshake initialize / initialized и заголовок Mcp-Session-Id. Теперь каждый запрос несёт с собой всё необходимое состояние, а сервер может быть обычным веб-сервисом за балансировщиком.</p><ul><li>Новая спецификация MCP 2026-07-28 делает протокол stateless: сессии и handshake больше не нужны.</li><li>Клиент передаёт свою идентификацию и возможности в поле _meta каждого JSON-RPC-запроса.</li><li>Балансировщик может использовать обычный round-robin, ориентируясь на заголовки Mcp-Method и Mcp-Name.</li><li>Roots, Sampling и Logging объявлены устаревшими с минимальным окном поддержки 12 месяцев.</li><li>Финальная спецификация ожидается 28 июля 2026 года после 10-недельного окна валидации SDK.</li></ul><p>Model Context Protocol (MCP) — открытый протокол для подключения ИИ-агентов к внешним инструментам и данным. С момента передачи Anthropic в Linux Foundation в декабре 2025-го им управляет Agentic AI Foundation, а число production-серверов уже исчисляется сотнями тысяч. До сих пор MCP работал по модели чата: сначала handshake, потом сервер выдавал идентификатор сессии, который клиент возвращал с каждым запросом.</p><p>В релиз-кандидате эта модель заменена на stateless. Клиент кладёт имя, версию и capabilities в поле _meta прямо в тело запроса. Балансировщик читает HTTP-заголовки Mcp-Method и Mcp-Name (SEP-2243) и направляет запрос на любой свободный инстанс — общее хранилище сессий больше не требуется. Если серверу нужен ввод посреди вызова, он возвращает InputRequiredResult, а клиент переотправляет запрос с inputResponses и requestState.</p><p>Вместе с ядром обновляются и расширения. Появляется MCP Apps — серверный интерактивный UI в sandboxed iframe с заранее декларируемыми шаблонами. Переработано API долгих задач: вместо tasks/list приходят tasks/get, tasks/update и tasks/cancel. Также шесть SEPов ужесточают авторизацию по OAuth/OIDC, включая проверку issuer по RFC 9207.</p><h2>Часто задаваемые вопросы</h2><h2>Выводы</h2><p>Новая спецификация — признак того, что MCP вырос из протокола для локальных подключений в полноценную enterprise-инфраструктуру. Переход к statelessness решает главную операционную проблему масштабирования, но добавляет работы тем, кто уже внедрил stateful-реализации. Главное — помнить, что релиз пока кандидат: production-серверы продолжают работать на спецификации 2025-11-25.</p><p>Источник: <a href="https://awesomeagents.ai/news/mcp-stateless-protocol-update/">awesomeagents.ai</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как ограничить расходы на OpenAI API, чтобы ИИ-агенты не сожгли бюджет</title>
      <link>https://tproger.ru/articles/kak-ogranichit-rashody-na-openai-api-chtoby-ii-agenty-ne-sozhgli</link>
      <comments>https://tproger.ru/articles/kak-ogranichit-rashody-na-openai-api-chtoby-ii-agenty-ne-sozhgli?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-ogranichit-rashody-na-openai-api-chtoby-ii-agenty-ne-sozhgli</guid>
      <description><![CDATA[<p>Разбираем, как настроить лимиты расходов, алерты и жёсткие ограничения в OpenAI API. Пошаговая инструкция для разработчиков и команд.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-ogranichit-rashody-na-openai-api-chtoby-ii-agenty-ne-sozhgli">Как ограничить расходы на OpenAI API, чтобы ИИ-агенты не сожгли бюджет</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[OpenAI]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 04 Jul 2026 15:34:20 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если ваше приложение или агент работает с <a href="https://openai.com/api/">OpenAI API</a>, один бесконтрольный цикл способен за несколько часов превратить пару долларов в счёт на сотни или тысячи. Хорошая новость: в кабинете разработчика уже есть инструменты, которые не дают бюджету уйти в свободное плавание.</p><p>В этой статье разбираем, как работают usage tiers, мягкие и жёсткие лимиты расходов, алерты и rate limits. И главное — что нужно учесть в коде, чтобы приложение корректно обработало отказ API.</p><p>OpenAI API делит аккаунты на usage tiers: чем больше суммарно оплачено, тем выше месячный потолок расходов.</p><p>В настройках Limits можно задать собственный лимит трат, включить жёсткое ограничение и настроить email-алерты.</p><p>Жёсткий лимит отключает API при превышении бюджета: запросы начинают возвращать ошибку 429.</p><p>Rate limits ограничивают RPM, RPD, TPM и TPD по моделям; при превышении помогает экспоненциальный бэкофф.</p><p>В коде важно перехватывать 429, повторять запросы с задержкой и логировать расход токенов.</p><h2>Как устроены usage tiers</h2><p>Usage tiers — это автоматические уровни аккаунта, которые OpenAI выдаёт в зависимости от суммы уже оплаченных API-вызовов. Чем выше tier, тем больше месячный потолок трат и выше rate limits. Для новичка это двойная защита: даже если вы ничего не настраивали, система не даст потратить больше, чем разрешено текущему уровню.</p><h3>Таблица tiers по состоянию на июль 2026</h3><p>Данные взяты из <a href="https://platform.openai.com/docs/guides/rate-limits">документации OpenAI</a>.</p><ul><li><b>Free</b> — доступен из разрешённых регионов, лимит $100 / месяц.</li><li><b>Tier 1</b> — нужно оплатить от $5, лимит $100 / месяц.</li><li><b>Tier 2</b> — оплачено от $50, лимит $500 / месяц.</li><li><b>Tier 3</b> — оплачено от $100, лимит $1 000 / месяц.</li><li><b>Tier 4</b> — оплачено от $250, лимит $5 000 / месяц.</li><li><b>Tier 5</b> — оплачено от $1 000, лимит $200 000 / месяц.</li></ul><p><b>Важно:</b><br />После Tier 5 потолок резко растёт — именно на этом этапе жёсткий лимит расходов становится критичным. Без него зациклившийся агент теоретически может исчерпать шестизначную сумму до того, как вы заметите.</p><h2>Лимит расходов: мягкий, жёсткий и алерты</h2><p>На странице <a href="https://platform.openai.com/settings/organization/limits">Limits</a> в настройках организации можно задать три вещи: месячный бюджет, уведомления и автопополнение баланса.</p><ul><li><b>Spend limit</b> — мягкий потолок. OpenAI показывает предупреждение, но фактические траты могут его немного превысить.</li><li><b>Enforce hard limit</b> — жёсткий потолок. При достижении лимита API начинает возвращать ошибку 429 и больше не списывает деньги.</li><li><b>Spend alerts</b> — email-уведомление при достижении заданного процента от бюджета.</li><li><b>Auto recharge</b> — автоматическое пополнение баланса с привязанной карты. При риске перерасхода его стоит отключить.</li></ul><p>Рекомендация простая: для продакшена включайте Enforce hard limit и настраивайте алерты на 50% и 80%. Так у вас будет время разобраться, пока API ещё работает.</p><h2>Rate limits: почему API отвечает 429</h2><p>Rate limits — это не про деньги, а про нагрузку. OpenAI ограничивает количество запросов в минуту/день и токенов в минуту/день для каждой модели. Лимиты зависят от tier и модели: например, для gpt-4o и gpt-4o-mini они различаются.</p><ul><li><b>RPM</b> — requests per minute, запросы в минуту.</li><li><b>RPD</b> — requests per day, запросы в день.</li><li><b>TPM</b> — tokens per minute, токены в минуту.</li><li><b>TPD</b> — tokens per day, токены в день.</li><li><b>IPM</b> — images per minute, изображения в минуту (для моделей генерации картинок).</li></ul><p>При превышении любого из лимитов API возвращает 429 Too Many Requests. OpenAI рекомендует обрабатывать эту ошибку через экспоненциальный бэкофф: повторять запрос с увеличивающейся паузой.</p><h2>Что делать в коде</h2><ol><li>Перехватывайте 429 и различайте причину: rate limit, hard spend limit или квота по токенам.</li><li>Используйте экспоненциальный бэкофф с джиттером, чтобы не «дудосить» API своими ретраями.</li><li>Логируйте количество токенов и стоимость каждого вызова — лучше всего через поля usage в ответе.</li><li>Для агентов добавьте circuit breaker: если бюджет исчерпан или ошибки 429 идут подряд, остановите цикл и уведомите команду.</li><li>Не храните API-ключ в клиентском коде: утечка ключа — самый быстрый способ получить чужой счёт.</li></ol><h2>Пошаговая настройка</h2><h2>Выводы</h2><p>OpenAI API даёт в руки разработчика все нужные рычаги: usage tiers, spend limits, spend alerts, rate limits и жёсткое ограничение. Проблема не в отсутствии инструментов, а в том, что ими редко пользуются до первого «сюрприза» в биллинге.</p><p>Минимальный must have для любого проекта: включить Enforce Hard Limit, настроить алерты на 50% и 80%, отключить автопополнение, если бюджет критичен, и добавить в код обработку 429. Так вы защитите не только карту, но и репутацию команды.</p><blockquote>Set up spend limits so rogue AIs don't exceed your budget. Rate limits are very easy to configure, making them a no-brainer for protecting your account.</blockquote><p><b>Источники:</b><br /><a href="https://www.zdnet.com/article/how-to-set-openai-api-spend-usage-limits/">ZDNET — How I set OpenAI API usage limits to stop agent overspending</a><br /><a href="https://platform.openai.com/docs/guides/rate-limits">OpenAI Docs — Rate limits</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Microsoft признала ошибку привязки Copilot к OpenAI и вложит $2,5 млрд в мульти-модельный ИИ</title>
      <link>https://tproger.ru/news/microsoft-priznala-owibku-privyazki-copilot-k-openai-i-vlozhit-2</link>
      <comments>https://tproger.ru/news/microsoft-priznala-owibku-privyazki-copilot-k-openai-i-vlozhit-2?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/microsoft-priznala-owibku-privyazki-copilot-k-openai-i-vlozhit-2</guid>
      <description><![CDATA[<p>Microsoft создаёт Frontier Company с $2,5 млрд, чтобы enterprises выбирали ИИ-модели разных провайдеров. Узнайте подробнее, почему уходит эпоха единой модели.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/microsoft-priznala-owibku-privyazki-copilot-k-openai-i-vlozhit-2">Microsoft признала ошибку привязки Copilot к OpenAI и вложит $2,5 млрд в мульти-модельный ИИ</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Машинное обучение]]></category>
      <category><![CDATA[Нейронные сети]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Облачные технологии]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 03 Jul 2026 05:00:13 GMT</pubDate>
      <content:encoded><![CDATA[<p>Microsoft сделала ставку на гибкость вместо моногамии с одной ИИ-моделью. Компания объявила о создании нового подразделения Microsoft Frontier Company с фондом в <b>$2,5 млрд</b>, которое будет помогать крупным заказчикам выбирать, комбинировать и быстро менять генеративные модели под свои задачи.</p><p>Решение выросло из собственного опыта: по словам Judson Althoff, главы коммерческого направления Microsoft, привязка оригинального Copilot исключительно к моделям OpenAI была ошибкой. Клиентам важнее не бренд модели, а результат: их данные плюс та архитектура, которая даёт лучший отклик, цену и безопасность.</p><p>Microsoft запускает подразделение Frontier Company с бюджетом $2,5 млрд для помощи enterprise-клиентам в выборе ИИ-моделей.</p><p>Компания признала: привязка Copilot только к OpenAI была ошибкой, и теперь продвигает мульти-модельную стратегию.</p><p>Современные приложения всё чаще маршрутизируют запросы между несколькими моделями в зависимости от стоимости, скорости и требований к данным.</p><p>Рынок отвечает развитием ИИ-шлюзов и оркестраторов: LiteLLM, Portkey, LangGraph, MCP, Azure AI Foundry, Amazon Bedrock, Google Vertex AI.</p><h2>Почему одной модели уже недостаточно</h2><p>В одном типичном корпоративном сценарии может понадобиться суммаризация тикета, анализ 300-страничного договора, генерация письма, расшифровка встречи и ревью кода. Это разные задачи: для длинного контракта выгоднее модель с огромным контекстом, для быстрых ответов — лёгкая и дешёвая, для чувствительных данных — локальная open-weight модель. Вместо того чтобы искать универсального победителя, разработчники строят <b>слой маршрутизации</b>, который отправляет каждый запрос к подходящей модели.</p><blockquote>We made a mistake by binding it to OpenAI models only.</blockquote><h2>Что это меняет для инженеров</h2><p>Если раньше приложение жёстко завязывалось на один API, то теперь ключевой навык — проектирование оркестрации. Нужно уметь сравнивать модели по качеству, задержке и цене, мониторить отказы, переключать трафик и соблюдать политики безопасности. В enterprise-масштабе такие решения принимаются миллионы раз в день, поэтому шлюз должен быть быстрым и управляемым.</p><h2>Кто ещё строит маршрутизацию</h2><ul><li><b>LiteLLM</b> и <b>Portkey</b> — нормализуют API разных провайдеров.</li><li><b>LangChain / LangGraph</b> — рассчитаны на много-модельные пайплайны.</li><li><b>Model Context Protocol (MCP)</b> — делает инструменты переносимыми между моделями.</li><li><b>Azure AI Foundry, Amazon Bedrock, Google Vertex AI</b> — предлагают десятки моделей за единым endpoint.</li></ul><h2>Выводы</h2><p>Microsoft закладывает $2,5 млрд на то, что следующий конкурентный рубеж в enterprise ИИ — не сама модель, а умение ею управлять. Для разработчиков это означает рост спроса на инфраструктуру маршрутизации, observability и политики данных. Если облачная эра научила не привязываться к одному серверу, то ИИ-эра учит не привязываться к одной модели.</p><p>Оригинал материала: <a href="https://thenewstack.io/enterprise-ai-model-routing/" rel="noopener noreferrer">The New Stack — Enterprise AI Model Routing</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Дайджест Android-разработки за июнь 2026: Android 17, Play и безопасность</title>
      <link>https://tproger.ru/articles/android-cli-1-0-navyki-ii-agentov-i-android-bench-ot-google</link>
      <comments>https://tproger.ru/articles/android-cli-1-0-navyki-ii-agentov-i-android-bench-ot-google?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/android-cli-1-0-navyki-ii-agentov-i-android-bench-ot-google</guid>
      <description><![CDATA[<p>Главное для Android-разработчиков в июне 2026: релиз Android 17, новые правила Google Play, zero-day CVE-2025-48595 и верификация разработчиков. Разбираем.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/android-cli-1-0-navyki-ii-agentov-i-android-bench-ot-google">Дайджест Android-разработки за июнь 2026: Android 17, Play и безопасность</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Инструменты командной строки]]></category>
      <category><![CDATA[Google]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Инновации]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 01 Jul 2026 12:30:26 GMT</pubDate>
      <content:encoded><![CDATA[<p>Июнь 2026 года выдался насыщенным для Android-разработчиков: Google выпустила Android 17 с API 37, пересмотрела комиссии и биллинг в Play, залатала активно эксплуатируемую уязвимость и продолжила накатывать верификацию разработчиков. Ниже — краткий дайджест главных событий месяца, которые стоит учитывать при планировании релизов и миграций.</p><p><b>Android 17</b> вышел 16 июня. API 37, AppFunctions для ИИ-агентов, adaptive-first и Compose-first, строгие лимиты памяти и новые API приватности.</p><p><b>Google Play</b> расширяет выбор платёжных систем и снижает комиссии: с 30 июня 2026 сервисный сбор отдельно от платёжного, первый $1M — 10%.</p><p><b>Безопасность</b>: июньский бюллетень закрыл 124 уязвимости, включая zero-day CVE-2025-48595 в Framework. С 30 сентября 2026 начинается обязательная верификация разработчиков в четырёх странах.</p><p><b>Инструменты</b>: Android CLI 1.0, 17+ Android skills, Android Bench с Gemma 4 и Gemini 3.5 Flash, Android XR SDK DP4 и Eclipsa Video для HDR.</p><h2>Android 17: релиз 16 июня и API 37</h2><p>16 июня 2026 года Google <a href="https://android-developers.googleblog.com/2026/06/Android-17.html" rel="noopener">выпустил Android 17</a>. Платформа переходит от «операционной системы» к «интеллектуальной системе»: центральную роль занимают AppFunctions — функции приложений, которые ИИ-агенты могут обнаруживать и вызывать через Jetpack-библиотеку. Разработчики аннотируют класс, добавляют KDoc, и Gemini получает доступ к локальному состоянию приложения.</p><p>Главное архитектурное изменение — <b>adaptive-first</b>: на больших экранах (sw &gt; 600 dp) для приложений с targetSdk 37 игнорируются ограничения ориентации и размера. Вместе с этим появились App Bubbles, Bubble Bar и интерактивный Picture-in-Picture для десктопа. Google заявляет, что Compose теперь является первым классом UI: View-компоненты и View-based библиотеки переведены в режим обслуживания.</p><h3>Производительность и приватность</h3><p>Android 17 вводит лимиты памяти на основе объёма RAM устройства и убивает процессы, их нарушающие. Для диагностики добавили интеграцию LeakCanary в Android Studio Panda и on-device аномалию в ProfilingManager. ART получил generational GC, а MessageQueue для targetSdk 37 стал lock-free — это ускоряет старт и снижает пропуск кадров, но ломает рефлексию над приватными полями.</p><p>Из приватных нововведений — системный Contact Picker без разрешения READ_CONTACTS, системный Eyedropper для выбора цвета, временный доступ к локальной сети через ACCESS_LOCAL_NETWORK и post-quantum криптография с ML-DSA и гибридной подписью APK v3.2.</p><h2>Инструменты и продуктивность: Android CLI 1.0, skills и Bench</h2><p>9 июня в блоге Android Developers <a href="https://android-developers.googleblog.com/2026/06/android-developer-productivity-updates.html" rel="noopener">подвели итоги I/O</a> по продуктивности. Главное — стабильный релиз Android CLI 1.0: теперь инструмент доступен через npm и Homebrew, умеет Journeys и команду studio для моста с Android Studio, а также интегрируется с Google Antigravity.</p><p>Каталог Android skills вырос до 17+ сценариев: адаптивный UI, CameraX, Perfetto SQL, Engage SDK, Wear OS, AppFunctions и другие. А Android Bench обзавёлся открытыми моделями, включая локальную Gemma 4, и свежими Gemini 3.5 Flash. В ближайшее время в бенчмарк добавят долгие многошаговые задачи.</p><h2>Google Play: биллинг, комиссии и поиск</h2><p>24 июня Google <a href="https://android-developers.googleblog.com/2026/06/play-expanded-billing.html" rel="noopener">расширила выбор платёжных систем</a> в Великобритании, ЕЭЗ и США. Разработчики могут предлагать альтернативный биллинг или внешние ссылки на свой сайт. С 30 июня 2026 сервисный сбор отделяется от платёжного: первый $1M в год — 10%, все автообновляемые подписки — 10%, остальное зависит от новой/существующей установки. Платёжная комиссия при использовании Google Play billing — 5% в этих регионах; при альтернативном биллинге она не берётся.</p><p>Также Google запустила программы Games Level Up и Apps Experience с пониженными ставками, а в Play Store появился AI-поиск Ask Play, Trusted Contributor-значки и более заметные скидки. Для разработчиков это означает, что ASO и монетизацию придётся пересматривать под новые механики отображения цен.</p><h2>Безопасность: zero-day и верификация разработчиков</h2><p>Июньский Android Security Bulletin закрыл 124 уязвимости. Самая неприятная — CVE-2025-48595 в Framework, уже эксплуатируемая в ограниченных целевых атаках. Она затрагивает Android 14–16 QPR2 и позволяет повысить привилегии без взаимодействия с пользователем. Критичный патч — уровень 2026-06-05, так как он включает исправления чипсетов Qualcomm и MediaTek.</p><p>18 июня Google <a href="https://android-developers.googleblog.com/2026/06/android-developer-verification.html" rel="noopener">обновила статус верификации разработчиков</a>. С 30 сентября 2026 в Бразилии, Индонезии, Сингапуре и Таиланде станут обязательными регистрация приложений в семи магазинах. В июне на устройствах начали раскатывать системный сервис, который позже будет проверять регистрацию. В июле–августе появятся Android Developer ID Status API и Developer Console API для массовой регистрации через CI/CD.</p><h2>Android XR: DP4, движки и Geospatial API</h2><p>15 июня вышел <a href="https://android-developers.googleblog.com/2026/06/what-is-new-android-xr.html" rel="noopener">Developer Preview 4 Android XR SDK</a>. Для очков дополненной реальности добавили Jetpack Projected с Device Availability API, а Compose Glimmer оптимизирован под прозрачные дисплеи и тачпад. Для иммерсивных приложений — ранняя версия Geospatial API на базе ARCore и Visual Positioning System.</p><p>Кроме Unity для проводных XR-очков появилась официальная поддержка Unreal Engine и Godot, а также Android XR Engine Hub — десктопный инструмент для Windows с real-time тестированием прямо во вьюпорте движка. Программа Android XR Developer Catalyst Program открыта для заявок и даёт доступ к pre-release железу.</p><h2>Premium-опыт: R8, Glance и Media3</h2><p>В посте 2 июня <a href="https://android-developers.googleblog.com/2026/06/building-premium-android-experiences-google-io-26.html" rel="noopener">о премиум-опыте</a> Google акцентировала R8 Configuration Analyzer: он показывает, какие keep-rules мешают оптимизации. Monzo за счёт настройки R8 получили 30% прирост холодного старта и 35% снижение ANR.</p><p>Jetpack Glance теперь унифицирует виджеты для телефонов, часов и автомобилей на базе Compose, а RemoteCompose позволяет рендерить UI на внешних поверхностях. Media3 получил AI Effects, CodecDB, Scrubbing Mode в ExoPlayer и улучшенный CastPlayer. CameraX 1.5+ добавляет CameraXViewfinder Composable и динамические диапазоны.</p><h2>Eclipsa Video: единый стандарт HDR</h2><p>29 июня Google <a href="https://android-developers.googleblog.com/2026/06/eclipsa-video-hdr-review.html" rel="noopener">представила Eclipsa Video</a> — стандарт HDR на базе SMPTE ST 2094-50, разработанный совместно с Apple и NBCUniversal. Он задаёт единый HDR reference white, адаптирует яркие участки под возможности дисплея и сохраняет творческий замысел кадр за кадром. Поддержка встроена в Android 17, ExoPlayer/Media3 обрабатывают метаданные автоматически.</p><h2>FAQ</h2><h2>Выводы</h2><p>Июнь 2026 показал, что Google делает ставку на три вещи: ИИ-агентов как часть рабочего процесса (AppFunctions, Android CLI, skills), адаптивность интерфейсов под любые форм-факторы и жёсткий контроль за безопасностью экосистемы. Разработчикам стоит в первую очередь протестировать приложения под Android 17, проверить R8-конфигурацию и подготовиться к новым правилам биллинга и верификации.</p><blockquote>Самый быстрый способ не отстать — поставить Android CLI, добавить пару skills под свой проект и прогнать релиз на Android 17 эмуляторе, прежде чем OEM-партнёры начнут массово раскатывать обновление.</blockquote><p>Источники: <a href="https://android-developers.googleblog.com/2026/06/Android-17.html" rel="noopener">Android 17 is here</a>, <a href="https://android-developers.googleblog.com/2026/06/android-developer-productivity-updates.html" rel="noopener">Top 3 updates for Android developer productivity</a>, <a href="https://android-developers.googleblog.com/2026/06/play-expanded-billing.html" rel="noopener">Expanded billing choice and lower fees on Google Play</a>, <a href="https://android-developers.googleblog.com/2026/06/android-developer-verification.html" rel="noopener">Android developer verification</a>, <a href="https://android-developers.googleblog.com/2026/06/what-is-new-android-xr.html" rel="noopener">What's New in Android XR</a>, <a href="https://android-developers.googleblog.com/2026/06/building-premium-android-experiences-google-io-26.html" rel="noopener">Building Premium Android Experiences</a>, <a href="https://android-developers.googleblog.com/2026/06/eclipsa-video-hdr-review.html" rel="noopener">Eclipsa Video</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Бесплатный WAF инструмент кибербезопасности, который я использую</title>
      <link>https://tproger.ru/articles/besplatnyj-waf-instrument-kiberbezopasnosti-kotoryj-ya-ispolzuyu</link>
      <comments>https://tproger.ru/articles/besplatnyj-waf-instrument-kiberbezopasnosti-kotoryj-ya-ispolzuyu?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Неопознанный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/besplatnyj-waf-instrument-kiberbezopasnosti-kotoryj-ya-ispolzuyu</guid>
      <description><![CDATA[<p>Разбор бесплатного open-source WAF SafeLine для защиты от OWASP Top 10, DDoS и ботов. Сравнение с ModSecurity и Cloudflare по точности обнаружения атак, минимальные ложные срабатывания, простая установка одной командой Docker.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/besplatnyj-waf-instrument-kiberbezopasnosti-kotoryj-ya-ispolzuyu">Бесплатный WAF инструмент кибербезопасности, который я использую</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Unity]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[.NET]]></category>
      <category><![CDATA[iOS]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Docker]]></category>
      <category><![CDATA[MIT]]></category>
      <category><![CDATA[IBM]]></category>
      <category><![CDATA[Cloudflare]]></category>
      <category><![CDATA[Маркетинг]]></category>
      <category><![CDATA[CSR]]></category>
      <category><![CDATA[PostgreSQL]]></category>
      <category><![CDATA[Бизнес]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 01 Jul 2026 05:55:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Решения с открытым исходным кодом достигли такого уровня зрелости, что сегодня они действительно могут конкурировать с коммерческими продуктами — не только по функциональности, но и по удобству использования и поддержке сообщества. Если вы управляете собственной инфраструктурой, больше нет оправдания тому, чтобы оставлять дверь открытой для угроз.</p><p>SafeLine WAF — это бесплатный инструмент, который я лично тестировал.</p><p>Это полностью open-source решения, продукт с действительно бесплатной Community Edition, где ключевые функции не урезаны.</p><p><b>SafeLine WAF — веб-приложенийный межсетевой экран, который действительно поставляется с разумными настройками по умолчанию</b></p><p><b>Что он делает:</b></p><p>Защищает веб-приложения от SQL-инъекций, XSS-атак, командных инъекций, CSRF, SSRF, атак включения файлов и других угроз из списка OWASP Top 10. Также поддерживает защиту от CC/DDoS-атак, управление ботами и может работать как шлюз аутентификации.</p><p><b>Почему он:</b></p><p>Большинство WAF с открытым исходным кодом достаточно сложно настроить. Можно потратить часы на настройку правил, пытаясь остановить ложные срабатывания, из-за которых легитимные пользователи блокируются.</p><p>SafeLine использует другой подход — вместо того чтобы полностью полагаться на сигнатурное обнаружение, он применяет движок семантического анализа, который фактически анализирует и понимает входящие HTTP-запросы. Это позволяет добиться более высокого уровня обнаружения при значительно меньшем количестве ложных срабатываний по умолчанию.</p><p>Некоторые показатели, которые стоит учитыват</p><ol><li>Уровень обнаружения - SafeLine (Balanced) (71.65%), ModSecurity (Level 1) (69.74%), Cloudflare (Free) (10.7%)</li><li>Уровень ложных срабатываний - SafeLine (Balanced) (0.07%), ModSecurity (Level 1) (17.58%), Cloudflare (Free) (0.07%)</li><li>Точность - SafeLine (Balanced) (99.45%), ModSecurity (Level 1) (82.20%), Cloudflare (Free) (98.40%)</li></ol><p>Сбалансированный профиль SafeLine обнаруживает более 70% атак, при этом блокируя легитимный трафик ошибочно всего в 0.07% случаев. Это именно тот уровень настроек по умолчанию, который можно использовать в промышленной среде без постоянного ручного контроля.</p><p>Установка выполняется одной командой</p><p>После запуска он разворачивается как набор Docker-контейнеров: Tengine (форк Nginx) используется в качестве reverse proxy, отдельный сервис отвечает за семантический анализ, PostgreSQL хранит конфигурации и логи, а удобная веб-панель администратора работает на порту 9443.Community Edition поддерживает до 10 сайтов, чего достаточно для большинства личных проектов и небольших бизнес-сценариев.</p><p>Сайт: <a href="https://api.vc.ru/v2.8/redirect?to=https%3A%2F%2Fcodeby.net%2Fgoto%2Flink-confirmation%3Furl%3DaHR0cHM6Ly9jeWJlcnNlcnZhbC50ZWNoL2xhbmRpbmcvc2FmZWxpbmXvv7xHaXRIdWI%253D%26s%3D7008b60d8a0849ba0be350fe25edfa72&amp;postId=3005263" rel="nofollow noopener">https://cyberserval.tech/landing/safeline</a></p><p>GitHub:<a href="https://api.vc.ru/v2.8/redirect?to=http%3A%2F%2Fgithub.com%2Fchaitin%2FSafeLine&amp;postId=3005263" rel="nofollow noopener"> github.com/chaitin/SafeLine</a> (более 21 тыс. звёзд)</p><p>Лицензия: GPL-3.0 / MIT (Community Edition)</p>]]></content:encoded>
    </item>
    <item>
      <title>Airflow, n8n и Make: что выбрать для API-оркестрации</title>
      <link>https://tproger.ru/articles/airflow-n8n-i-make-chto-vybrat-dlya-api-orkestracii</link>
      <comments>https://tproger.ru/articles/airflow-n8n-i-make-chto-vybrat-dlya-api-orkestracii?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/airflow-n8n-i-make-chto-vybrat-dlya-api-orkestracii</guid>
      <description><![CDATA[<p>Сравниваем Apache Airflow, n8n и Make для оркестрации API: плюсы, минусы, стоимость и российская специфика. Выберите инструмент под свою задачу.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/airflow-n8n-i-make-chto-vybrat-dlya-api-orkestracii">Airflow, n8n и Make: что выбрать для API-оркестрации</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[DevOps]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 25 Jun 2026 13:25:47 GMT</pubDate>
      <content:encoded><![CDATA[<p>Современное приложение редко живёт в вакууме: платёжка общается с банком, CRM — с телефонией, а аналитика собирает данные из десятка источников. Когда одного curl мало, на сцену выходит API-оркестрация — последовательность вызовов, обработка ошибок, преобразование данных и контроль за выполнением. Выбор инструмента для этой работы определяет, сколько времени вы потратите на поддержку и сколько он будет стоить при росте нагрузки.</p><ul><li><b>Apache Airflow</b> — мощный оркестратор для сложных Python-конвейеров, но требует инфраструктуры и DevOps-культуры.</li><li><b>n8n</b> — визуальный конструктор с открытым исходным кодом: удобен для средних нагрузок, можно бесплатно хостить на своём сервере.</li><li><b>Make</b> (бывший Integromat) — облачный визуальный автоматизатор для бизнес-команд, дешевле Zapier, но тарифицирует каждый шаг сценария.</li><li>Для российских команд критичны: возможность self-hosting, стоимость инфраструктуры и риски доступности зарубежного SaaS.</li><li>Нет универсального победителя — выбор зависит от размера команды, сложности логики и требований к контролю над данными.</li></ul><p><b>API-оркестрация</b> — это не просто «позвонить в API», а построить надёжный конвейер: вызвать один сервис, передать результат в другой, обработать ошибку, повторить при сбое и записать лог. Иногда это пара запросов в час, а иногда — десятки тысяч операций в день. Отсюда и разница в подходах: где-то важна гибкость кода, где-то — скорость запуска, а где-то — цена за операцию.</p><h2>Apache Airflow: тяжёлый артиллерист</h2><p>Airflow появился в Airbnb и за десять лет стал стандартом для data-пайплайнов. Его используют Netflix, Spotify и Uber — там, где нужно управлять сотнями зависимых задач с контролем SLA и аудитом. Главная идея: вы описываете workflow как Python-код в виде направленного ациклического графа (DAG), а scheduler отвечает за порядок, ретраи и мониторинг.</p><h3>Зачем выбирать Airflow</h3><ul><li>Сложная логика: ветвления, условия, ретраи, расписания через cron.</li><li>Полный контроль над кодом: любые библиотеки Python, кастомные операторы, unit-тесты.</li><li>Зрелая экосистема: SLA-мониторинг, audit trail, интеграция с Kubernetes и Spark.</li><li>Open Source: можно развернуть на своей инфраструктуре, в том числе на российских облаках.</li></ul><h3>Честный взгляд на минусы</h3><ul><li>Высокий порог входа: нужно разворачивать БД, Redis, воркеры и веб-интерфейс.</li><li>Минимальный кластер на VPS обходится примерно в €50/месяц без учёта времени администратора.</li><li>При 50+ задачах DAG превращается в большой Python-файл, который сложно поддерживать без дисциплины.</li><li>Коммуникация между задачами через XCom требует внимания: забыли очистить — получили memory leak.</li></ul><p>Пример простого DAG, который забирает пользователя, его посты и считает количество:</p><p>Airflow хорош, когда у вас уже есть data-команда, Kubernetes и понимание, зачем нужны DAG. Для стартапа из трёх человек это, скорее, оверинжиниринг.</p><h2>n8n: визуальный middle ground</h2><p>n8n занимает промежуточную нишу между кодом и no-code. Это node-based редактор: вы перетаскиваете блоки, соединяете их стрелками, а логика — в JavaScript-функциях и условиях. Главное преимущество: n8n open-source, его можно поднять на собственном сервере, и за это не придётся платить пошагово.</p><h3>Зачем выбирать n8n</h3><ul><li>Быстрый старт: визуальный конструктор позволяет собрать пайплайн за час, а не день.</li><li>Self-hosting: контейнер на VPS за $5–10/мес может обрабатывать тысячи запусков в день.</li><li>Гибридный подход: 90 % задач решается мышкой, сложную трансформацию можно написать на JS.</li><li>Прозрачная цена облака: плата за выполнение workflow, а не за каждый модуль.</li></ul><h3>Ограничения</h3><ul><li>При сотнях задач в одном workflow визуальная схема становится громоздкой.</li><li>Нативные узлы покрывают не всё: экзотический API придётся звать через HTTP Request.</li><li>Self-hosted версия требует обновлений и бэкапов — это всё ещё инфраструктура, хоть и простая.</li><li>Для России: облако n8n — европейский сервис, но self-hosted можно развернуть на Selectel, Yandex Cloud или любом другом провайдере.</li></ul><p>Пример JSON-экспорта workflow, который забирает пользователей, преобразует данные и пишет в PostgreSQL:</p><p>n8n часто выбирают команды, которым нужна скорость no-code, но не хочется терять контроль над инфраструктурой и платить за каждый шаг сценария.</p><h2>Make: бизнес-автоматизация по шагам</h2><p>Make (ранее Integromat) — это облачный визуальный автоматизатор для бизнес-команд. Его сценарии собираются из модулей: триггер → действие → фильтр → маршрутизатор. По сравнению с Zapier у Make глубже логика, а цена ниже, но он остаётся полностью SaaS-решением.</p><h3>Зачем выбирать Make</h3><ul><li>Быстрая интеграция с популярными сервисами: Google Sheets, Slack, Telegram, CRM, email-рассылки.</li><li>Визуальные маршрутизаторы (routers), итераторы и агрегаторы позволяют строить ветвления без кода.</li><li>Низкий порог входа для маркетологов, менеджеров продукта и операционистов.</li><li>План Core стоит от $9/мес за 10 000 операций — дешевле многих конкурентов.</li></ul><h3>Подводные камни</h3><ul><li>Тарификация по операциям: каждый модуль в сценарии считается отдельно. Десять шагов × тысяча запусков = 10 000 операций.</li><li>Нельзя self-host: данные обрабатываются на серверах Make, что может быть проблемой для чувствительных данных.</li><li>Для России: сервис работает как зарубежный SaaS, есть риски доступности и оплаты.</li><li>Сложные сценарии сложнее отлаживать: приходится кликать по модулям в истории выполнений.</li></ul><p>Типичный сценарий в Make выглядит так: вебхук из формы → проверка дубликата в Google Sheets → запись в CRM → отправка уведомления в Telegram. Всё это строится мышкой, но стоит добавить кастомную логику — и придётся использовать HTTP-модуль или встроенные функции.</p><h2>Сравнение в цифрах</h2><p>Сводная таблица по ключевым параметрам. Вместо абстрактных «плюсов» смотрите на конкретные ограничения:</p><ul><li><b>Airflow</b> — код Python, self-hosted, сложность высокая, стоимость от €50/мес + администрирование, лучше для data-платформ.</li><li><b>n8n</b> — визуальный + JS, self-hosted или cloud, средняя сложность, self-hosted от $5–10/мес, лучше для средних нагрузок и гибридных команд.</li><li><b>Make</b> — визуальный no-code, только cloud, низкая сложность входа, от $9/мес за 10K операций, лучше для бизнес-автоматизации.</li><li><b>Модель оплаты</b>: Airflow — инфраструктура; n8n — инфраструктура или executions в облаке; Make — операции (каждый модуль отдельно).</li><li><b>Контроль данных</b>: максимальный у Airflow и self-hosted n8n; минимальный у Make как SaaS.</li></ul><p><b>Российская специфика:</b><br />Для команд в РФ критичен self-hosted путь: Airflow и n8n можно развернуть на отечественных VPS или в Yandex Cloud/Selectel. Make, Zapier и другие зарубежные SaaS не дают гарантий доступности и оплаты. Если данные не могут покидать страну — выбор очевиден.</p><h2>Как выбрать инструмент</h2><h2>FAQ</h2><h2>Выводы</h2><p>Нет единого лучшего инструмента для API-оркестрации — есть подходящий под ваши ограничения. Airflow остаётся выбором зрелых data-команд, которым нужна масштабируемость и контроль. n8n закрывает большинство задач среднего уровня и даёт свободу self-hosting. Make — удобный SaaS для бизнес-автоматизации, но с привязкой к облаку и пошаговой тарификацией.</p><blockquote>Хороший оркестратор не тот, у кого больше иконок в интерфейсе, а тот, чьи ошибки вы сможете отладить в два часа ночи.</blockquote><p>Источник: материал основан на публикации «Airflow vs n8n vs Make for API orchestration» автора Raizan в DEV Community — <a href="https://dev.to/chasebot/airflow-vs-n8n-vs-make-for-api-orchestration-1lb8" rel="noopener">dev.to/chasebot/airflow-vs-n8n-vs-make-for-api-orchestration-1lb8</a>. Раздел про Make и сравнительный анализ дополнены редакционным контекстом.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как Android-инженер спроектировал gateway для миллионов пользователей: опыт перехода в инфраструктуру</title>
      <link>https://tproger.ru/articles/kak-android-inzhener-sproektiroval-gateway-dlya-millionov-polzova</link>
      <comments>https://tproger.ru/articles/kak-android-inzhener-sproektiroval-gateway-dlya-millionov-polzova?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Кирилл Соколов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-android-inzhener-sproektiroval-gateway-dlya-millionov-polzova</guid>
      <description><![CDATA[<p>История перехода из андроид разработки в инфраструктуру. Как мобильный инженер спроектировал gateway для платформы с миллионами пользователей, освоил распределённые системы и научился строить отказоустойчивые сервисы.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-android-inzhener-sproektiroval-gateway-dlya-millionov-polzova">Как Android-инженер спроектировал gateway для миллионов пользователей: опыт перехода в инфраструктуру</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Оптимизация]]></category>
      <category><![CDATA[Парсинг]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[Практика]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Tor]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[Навыки]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[App Store]]></category>
      <category><![CDATA[Игра]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Kubernetes]]></category>
      <category><![CDATA[Инфраструктура]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 23 Jun 2026 07:41:54 GMT</pubDate>
      <content:encoded><![CDATA[<p><i>Перешёл из Android-разработки в инфраструктуру и спроектировал gateway для платформы с миллионами пользователей. Делюсь опытом: какие пробелы пришлось закрывать, почему мобильный бэкграунд — это преимущество, и с чего начать, если думаете о похожем переходе. </i></p><h2>Почему инфраструктура начинает привлекать больше, чем фичи</h2><p>С фичами всё прозрачно: написал код — увидел результат на экране. Быстрая и понятная обратная связь. Но со временем замечаешь, что проблемы повторяются. Приложение тормозит не из-за плохого кода, а потому что на один экран уходит пять-шесть сетевых вызовов. Логика на клиенте. Хочешь что-то изменить — готовь релиз, проходи App Store Review и жди недели, пока обновление дойдёт до всех.</p><p>Я перешёл в Android-инфраструктуру — начал делать инструменты для других мобильных разработчиков. Это помогло увидеть: главные проблемы не в фичах, а в слое между приложением и бэкендом.</p><p>Возвращаться к фичам стало неинтересно. В инфраструктуре задачи сложнее, результат измеряется метриками — latency, error rate, скорость релизов, — а влияние на всю систему, а не на один экран.</p><h2>Что Android даёт для инфраструктуры — а чему учиться с нуля</h2><p>Мобильный бэкграунд оказался не балластом, а преимуществом. Я понимал ограничения изнутри. Backend-инженер может прочитать, что мобильные сети ненадёжны, память ограничена, а батарея — критичный ресурс. Но прочитать и прочувствовать — разное. Я годами наблюдал, как приложение “захлёбывается” на устройствах среднего сегмента. Знал, что 60% пользователей сидят именно на таких. Видел, как баг, который мы починили за день, продолжает висеть у людей неделями — просто потому, что они не успели обновиться.</p><p>Когда я проектировал gateway, я точно знал, что почувствуют мобильные разработчики, если ошибусь. Добавить ещё один сетевой вызов — это будет не бесплатно. Оставить логику в приложении — значит отдать её на устройство, которое я не контролирую.</p><p><b>Чего именно не хватало?</b> Я неплохо понимал мобильную сторону, но совершенно не ориентировался в распределенных системах. Знал, например, что такое таймаут, но не представлял, как выставить его в цепочке из пяти сервисов так, чтобы одно медленное звено не обрушило весь экран пользователя. Понимал, что сети падают, но не умел проектировать систему, способную оставаться на плаву в таких условиях.</p><p><b>Чему пришлось учиться с нуля? </b>Операционному мышлению. В Android ты выпускаешь релиз — и он либо работает, либо нет. Если крашится, починишь в следующей версии. В инфраструктуре нет «следующей версии». Если gateway падает, всё приложение ложится для миллионов пользователей прямо сейчас.</p><p>Пришлось учиться думать в терминах деградации, частичных отказов, плавного падения.</p><p>Что делать, если один из пяти сервисов не ответил? Как понять, что мы катимся к инциденту, до того, как пользователи начнут жаловаться?</p><p>Этому в мобильной разработке не учат.</p><h2>Как я учился: пробелы, сроки и смена мышления</h2><p>Формального плана у меня не было — учился на практике. Это лучший, хотя и самый стрессовый способ. Пробелы выявляла практика. Столкнулся с нерешаемой задачей — понял, чего не знаю. Пошёл разбираться.</p><p>Учился итеративно, не пытаясь объять необъятное сразу. Gateway начинался как простой прокси. Затем добавили агрегацию ответов, потом — конфигурационные определения экранов. Каждый такой шаг вынуждал осваивать следующий уровень: circuit breakers, стратегии повторов, observability, планирование мощностей.</p><p>По срокам: техническая база уложилась в несколько месяцев. Паттерны осваиваются быстрее, чем кажется, особенно если сразу применять их к живой задаче. Гораздо дольше происходила смена образа мышления. Перейти от вопроса «работает ли фича?» к вопросу «что случится, когда это упадёт в три часа ночи?» — вот что заняло основное время.</p><h2>Что означает «выдающийся уровень» в инфраструктуре</h2><p><i>Когда говорят «спроектировать gateway с нуля и перевести на него живую платформу», за этими словами стоит не один навык, а целых три, и каждый требует совершенно разной подготовки.</i></p><p>Проектирование с нуля — это не рисование квадратиков на доске и не выбор модного стека. Это в первую очередь определение границ: что система будет делать, а что — категорически нет, и как с ней станут взаимодействовать десятки команд. Настоящая сложность здесь в том, чтобы предвидеть, что именно сломается, и заложить защиту от этого ещё до того, как написан хоть один файл с кодом.</p><p>Затем — миграция живой системы, где права на ошибку практически нет. Приложение нельзя выключить или отрепетировать в реальном масштабе. Остаётся только постепенный перевод трафика: shadow mode → 1% → 5% → 25% → 50% → 100%, с автоматическим откатом при любом росте ошибок. И всё это — пока миллионы пользователей активно работают с продуктом, не подозревая, что под капотом идёт замена двигателя на ходу. Такой уровень дисциплины и инструментации приходит только с практикой.</p><p>Наконец, владение надёжностью. Gateway — единая точка отказа: упал он, упало всё. Годы уходят на то, чтобы сделать его скучным и предсказуемым: резервирование, автомасштабирование, circuit breakers, режимы деградации, еженедельный пересмотр мощностей. Высший пилотаж — когда о системе просто не думаешь, потому что она работает.</p><h2>Почему путь в инфраструктуру доступнее, чем кажется?</h2><p>Карьерные траектории в инфраструктуре редко бывают чётко описаны. Здесь нет готового чек-листа в духе «диплом по Computer Science, пять лет в бэкенде, обязательное знание Kafka и Kubernetes». С одной стороны, такая неопределённость пугает. С другой — именно она и делает этот путь более доступным, чем принято думать.</p><p>Когда перед тобой лежит жёсткий список формальных требований, люди часто отсеивают себя сами, даже не попробовав. А в инфраструктуре по-настоящему важно только одно: можешь ли ты решать задачи. Я пришёл сюда без профильного диплома и учился ровно тому, что требовалось в моменте, потому что задачи сами подталкивали к этому.</p><p>Индустрия, к слову, до сих пор не слишком хорошо умеет проверять те навыки, которые на этом уровне оказываются решающими: умение видеть ограничения на стыке систем, предвидеть сценарии отказов, двигать людей к соглашению. Всему этому учатся не до начала работы, а непосредственно в процессе.</p><p>Поэтому если вы мобильный инженер и размышляете, можно ли перейти в инфраструктуру, — вопрос не в том, правильный ли у вас бэкграунд. Вопрос в другом: готовы ли вы учиться тому, чего пока не знаете, и способны ли обратить то, что уже понимаете, в собственное преимущество. Если ответ «да» — путь для вас открыт. Просто указателей на нём пока не расставили.</p><h2>Мобильный бэкграунд как преимущество архитектора</h2><p>Считаю ли я, что мобильный опыт сделал меня лучшим архитектором для mobile-first продуктов? Безоговорочно, да.</p><p>Я помнил, как ощущается медленный экран на устройстве среднего сегмента. Помнил, что случается, когда API возвращает слегка неправильные данные и приложение падает при парсинге. Помнил то чувство, когда баг уже в проде, а ты ждёшь App Store Review и ничего не можешь исправить.</p><p>Поэтому когда я проектировал gateway, я не занимался абстрактной «оптимизацией перформанса». Я опирался на совершенно конкретный опыт. Знал, что убрать один сетевой round trip — это подарок каждому мобильному разработчику. Знал, что перенос логики на сервер означает перенос в место, где я могу починить всё за минуты, а не за недели.</p><p>Лучшая инфраструктура для мобильных продуктов строится теми, кто сам их создавал и знает все узкие места не понаслышке. Этот опыт даёт верное направление: ты чувствуешь, где настоящие проблемы, потому что сталкивался с ними лично. Такому не учат по книгам.</p><h2>Коротко: что делать, если думаете о переходе</h2><ul><li>Найдите промежуточный шаг. Не прыгайте сразу в бэкенд. Начните с задач на стыке: оптимизация API, инструменты для мобильных разработчиков, улучшение сетевого слоя.</li><li>Используйте мобильный контекст как рычаг. Вы понимаете то, о чём бэкенд-инженеры только догадываются. Говорите об этом вслух.</li><li>Учитесь измерять невидимое. В инфраструктуре результат — это метрики: latency, error rate, скорость релизов. Учитесь рассказывать историю через цифры.</li><li>Проектируйте под отказ, а не тушите пожары. Senior-уровень — это определить, что сломается и кто за это отвечает, до того, как оно сломается.</li><li>Не ждите разрешения. Путь не размечен, но он открыт. Начните с малого — и двигайтесь туда, где задачи становятся интереснее.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Как приручить legacy-код: безопасная модернизация без заморозки фич</title>
      <link>https://tproger.ru/articles/kak-priruchit-legacy-kod-bezopasnaya-modernizaciya-bez-zamorozki</link>
      <comments>https://tproger.ru/articles/kak-priruchit-legacy-kod-bezopasnaya-modernizaciya-bez-zamorozki?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[KODE]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-priruchit-legacy-kod-bezopasnaya-modernizaciya-bez-zamorozki</guid>
      <description><![CDATA[<p>Как модернизировать legacy-код без остановки продукта: Strangler Fig Pattern, feature flags, shadow testing и безопасная миграция данных. Практика и антипаттерны.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-priruchit-legacy-kod-bezopasnaya-modernizaciya-bez-zamorozki">Как приручить legacy-код: безопасная модернизация без заморозки фич</a>»</p>]]></description>
      <category><![CDATA[Интернет]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Ruby]]></category>
      <category><![CDATA[MySQL]]></category>
      <category><![CDATA[Практика]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[Рефакторинг]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Tor]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[MIT]]></category>
      <category><![CDATA[Финтех]]></category>
      <category><![CDATA[ICO]]></category>
      <category><![CDATA[Redis]]></category>
      <category><![CDATA[QA]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Twitter]]></category>
      <category><![CDATA[Игра]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Kubernetes]]></category>
      <category><![CDATA[Библиотеки]]></category>
      <category><![CDATA[аналитик]]></category>
      <category><![CDATA[OpenTelemetry]]></category>
      <category><![CDATA[PostgreSQL]]></category>
      <category><![CDATA[DeFi]]></category>
      <category><![CDATA[Grafana]]></category>
      <category><![CDATA[Бизнес]]></category>
      <category><![CDATA[Legacy]]></category>
      <category><![CDATA[Техника]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 23 Jun 2026 06:16:57 GMT</pubDate>
      <content:encoded><![CDATA[<p>Legacy-код — одна из самых болезненных тем в инженерных командах. Обычно все понимают, что система устарела: архитектура мешает быстро выпускать изменения, новые фичи приходится встраивать через обходные пути, тесты либо неполные, либо отсутствуют, а любое изменение в одном модуле неожиданно ломает другой.</p><p>Но при этом к такому коду часто боятся прикасаться. И не без причины. В старых системах редко бывает понятная карта зависимостей. Документация устарела, часть знаний живет только в головах нескольких разработчиков, а бизнес при этом продолжает ждать новых релизов, интеграций и продуктовых экспериментов.</p><p>Так появляется классическая ловушка legacy: систему надо модернизировать, но остановить развитие нельзя. Переписать всё с нуля страшно, поддерживать как есть — всё дороже. В результате продукт обрастает временными решениями, скорость разработки падает, а стоимость каждого следующего изменения растет.</p><p>Хорошая новость в том, что модернизация legacy-кода не обязана быть большим взрывом. Старую систему можно менять постепенно, сохраняя рабочий продукт, не замораживая фичи и не устраивая один критический релиз, от которого зависит всё.</p><h2>Почему Big Bang-переписывание чаще всего заканчивается плохо</h2><p>Когда команда долго живет с устаревшей системой, идея переписать всё с нуля выглядит очень соблазнительно. Кажется, что можно наконец избавиться от технического долга, выбрать нормальную архитектуру, перепроектировать модули, покрыть всё тестами и начать «правильно».</p><p>На старте такой план часто звучит логично. Особенно если текущая система действительно мешает развитию. Например, мобильное приложение растет, у него уже миллионы пользователей, бэкенд написан несколько лет назад как монолит, а каждая новая фича требует изменений в десятке мест. Команда устала чинить регрессии, бизнес устал ждать, и всем хочется «один раз нормально переписать».</p><p>Проблема не в самой идее переписывания, а в условиях, при которых оно проваливается. Большой риск возникает, когда совпадают четыре фактора: переписывание занимает много месяцев, в это время бизнес продолжает развивать старую систему, новая версия покрывает сразу большую часть функциональности, а откат связан с миграцией данных. Если все четыре пункта присутствуют, Big Bang почти гарантированно превратится в долгий и дорогой проект.</p><p>Допустим, команда решила переписать модуль заказов в e-commerce-продукте. В старой версии есть корзина, промокоды, доставка и оплата. Команда планирует за полгода сделать новый сервис заказов. Но за эти полгода бизнес добавляет подписки, подарочные сертификаты, частичную оплату бонусами и новую логику возвратов. В итоге новая система, которую проектировали под старые требования, к моменту релиза уже нуждается в доработке.</p><p>Есть и другая проблема: большой релиз почти всегда несет максимальный риск. Если вы заменяете крупный кусок системы целиком, ошибка влияет сразу на большую часть пользователей. Откат тоже становится сложным, потому что новая логика уже связана с новыми данными, контрактами и интеграциями.</p><p>Big Bang всё-таки бывает оправдан — но в узких условиях. Если кодовая база молодая (год-два), пользователей мало, у системы нет критичного состояния в БД и продукт можно временно заморозить или вести в обоих контурах параллельно, полное переписывание может оказаться дешевле постепенной миграции. Это редкая ситуация, и она быстро исчезает по мере роста продукта. В зрелых системах безопаснее работает другой подход — постепенная архитектурная эволюция.</p><h2>Пример: как команда переписала сервис документов и потеряла полгода</h2><p>Команда сопровождала сервис — старый модуль на aiohttp с Pydantic v1, через который проходила вся обработка путевых листов и актов осмотра транспорта. Сервис существовал шесть лет, был покрыт тестами фрагментарно, а его API использовали мобильное приложение водителей, диспетчерская веб-панель и пакетный импорт.</p><p>Команда решила переписать сервис целиком: перейти на FastAPI, обновить Pydantic до v2, заодно почистить контракты и заменить внутреннее хранилище документов с MongoDB на PostgreSQL. План был рассчитан на четыре месяца.</p><p>Через восемь месяцев проект всё ещё не был готов к выкатке, а к десятому месяцу команда откатила миграцию полностью. Причин было несколько.</p><p>Во-первых, переписывание шло параллельно с продуктовой разработкой. За время миграции бизнес добавил два новых типа документов и изменил правила подписи актов. Новая система проектировалась под старые требования и к моменту готовности уже не соответствовала продукту.</p><p>Во-вторых, команда не написала характеристических тестов. Поведение «как есть» нигде не было зафиксировано, и расхождения находились только в продакшене после переключения.</p><p>В-третьих, у старого сервиса были скрытые побочные эффекты, о которых никто не помнил. При смене статуса документа публиковал событие в Kafka, которое читал биллинг и сервис аналитики. В новой реализации это поведение не было воспроизведено, потому что в коде оно выглядело как «лишний» вызов. После переключения биллинг перестал получать события, и расхождение обнаружили только через две недели — по жалобе финансового отдела.</p><p>В-четвёртых, переключение было сделано «в лоб»: маршрут в API Gateway просто перенаправили на новый сервис. Фича-флага не было, теневого запуска не было, плана отката не было. Когда выяснилось, что новый сервис строже валидирует исторические форматы документов и отклоняет часть старых записей, быстро вернуться на старую реализацию не получилось — её к тому моменту уже отключили на стенде, а в БД успели уйти записи в новом формате.</p><p>В итоге миграцию свернули, потратив около десяти человеко-месяцев и потеряв доверие бизнеса. Сервис до сих пор работает в исходной реализации, а команда переходит к плану, описанному ниже.</p><h2>Strangler Fig Pattern: как заменить систему по частям</h2><p>Один из самых практичных подходов к модернизации legacy-кода — Strangler Fig Pattern. В софтверном виде паттерн был сформулирован Мартином Фаулером в 2004 году под названием StranglerFigApplication. Идея проста: не переписывать систему целиком, а постепенно выносить отдельные части в новую реализацию.</p><p>Название пришло из биологии. Фикус-душитель растет вокруг дерева-хозяина и постепенно вытесняет его. В архитектуре принцип похожий: старая система продолжает работать, новая функциональность появляется рядом, а затем отдельные потоки постепенно переводятся на новую реализацию.</p><p>Представим старый монолит интернет-магазина. Внутри него есть каталог, корзина, заказы, платежи, скидки, личный кабинет и уведомления. Переписать всё сразу — рискованно. Но можно начать с относительно изолированного участка, например с уведомлений.</p><p>Сначала команда описывает текущий контракт: какие события приходят в модуль уведомлений, какие каналы используются, какие шаблоны отправляются, какие ошибки считаются допустимыми. Затем рядом создается новый сервис уведомлений, который реализует тот же контракт. На первом этапе он может даже не отправлять реальные сообщения, а только принимать события и логировать результат. После проверки часть трафика переводится на новую реализацию. Когда сервис стабилизируется, старый код уведомлений удаляется из монолита.</p><p>Strangler Fig хорошо работает там, где между старым и новым кодом есть сетевая граница: HTTP, message bus, RPC. Если такой границы нет — например, нужно постепенно заменить функцию или класс внутри одного процесса — используется родственный паттерн Branch by Abstraction: над старой реализацией создается абстракция, рядом пишется новая реализация, переключение происходит через конфигурацию или фича-флаг, после стабилизации старая ветка удаляется. Снаружи это выглядит как Strangler Fig, но без сетевого прокси.</p><p>Такой подход снижает риск. В системе нет одного большого релиза, где всё меняется сразу. Есть серия небольших контролируемых изменений. Каждое можно протестировать, измерить и откатить.</p><h2>Главное правило: сначала повторить поведение, потом улучшать</h2><p>Одна из частых ошибок при модернизации legacy-кода — попытка одновременно переписать систему и улучшить бизнес-логику. Команда смотрит на старый модуль и думает: «Раз уж мы его трогаем, давайте сразу сделаем нормальную архитектуру, изменим контракты, уберем странные кейсы и перепишем поведение».</p><p>Это опасный путь. В legacy-системах странное поведение часто существует не случайно. За ним может стоять неочевидное бизнес-правило, старый клиент, интеграция с внешней системой или исторический баг, на который уже кто-то завязался.</p><p>Например, в системе расчета налогов может быть правило: для контрактов, заключенных до 2018 года, НДС округляется в меньшую сторону до целого рубля, а для всех остальных — по математическим правилам. Новый разработчик может решить, что это ошибка, и «исправить» округление. Но потом выяснится, что часть крупных клиентов держит это поведение в своих сверках, а смена правила приведет к расхождениям в актах и претензиям.</p><p>Прежде чем менять поведение, его нужно зафиксировать. Для этого пишут характеристические тесты (characterization tests, иногда называемые golden master или approval tests). Идея простая: на реальных данных или их обезличенных копиях прогоняется старая реализация, её ответы сохраняются как эталон, и любые будущие изменения, отклоняющиеся от эталона, отлавливаются автоматически. Тесты пишутся не для красоты, а для того, чтобы зафиксировать существующее поведение — даже странное — перед тем, как его трогать. Подробно эта техника описана у Майкла Физерса в книге Working Effectively with Legacy Code; на практике её удобно реализовать через библиотеки семейства approval-tests (approvaltests-python, approvaltests-java и аналоги).</p><p>Поэтому первый этап модернизации — не улучшение, а воспроизведение текущего поведения. Новая реализация должна вести себя так же, как старая. Даже если старое поведение кажется странным. Только после стабилизации можно отдельно обсуждать, что именно стоит менять.</p><h2>Feature toggles: как включать новую логику без риска</h2><p>Feature toggles, или фича-флаги, — один из главных инструментов безопасной миграции. Они позволяют включать и выключать новую логику без деплоя.</p><p>В обычной разработке релиз часто выглядит бинарно: код либо выкатили, либо нет. При миграции legacy это неудобно. Гораздо безопаснее иметь возможность включить новую реализацию для 1% пользователей, затем для 10%, потом для половины аудитории и только после этого для всех.</p><p>Например, команда переносит расчет стоимости доставки из монолита в новый сервис. С помощью фича-флага это выглядит так:</p><p>user_id передается явно, чтобы решение «попал ли пользователь в новый сегмент» было стабильным от запроса к запросу. Иначе один и тот же клиент будет получать разные ответы при обновлении страницы, и поведение системы станет непредсказуемым.</p><p>На первом этапе флаг включают только для внутренней команды. Потом для тестового сегмента пользователей. Затем для небольшой доли реального трафика. Если метрики стабильны, долю увеличивают. Если появляются ошибки, флаг выключают, и пользователи снова идут в старую реализацию.</p><p>Важно различать два разных типа флагов. Флаг постепенной выкатки (rollout flag) меняется редко и контролирует, какой процент пользователей видит новую логику. Kill switch — отдельный флаг, единственная задача которого — мгновенно выключить новую реализацию при инциденте. Kill switch должен опрашиваться на каждом запросе, его кэширование должно жить секунды, а не минуты, и он принципиально не должен зависеть от той системы, которую он выключает. Иначе в момент аварии может оказаться, что выключатель сам недоступен.</p><p>В качестве инфраструктуры для флагов команды обычно берут одну из платформ: LaunchDarkly, Unleash, Flagsmith, GrowthBook, либо собирают собственную поверх Redis или конфигурационного сервиса. Для миграции важны три свойства: быстрое распространение изменений (секунды, а не минуты), поддержка таргетинга по пользователю/сегменту и аудит — кто и когда менял флаг.</p><p>Важно, что фича-флаг — это не просто if в коде. Для серьезной миграции нужны правила: кто может включать флаг, как быстро его можно отключить, какие метрики отслеживаются, когда флаг должен быть удален.</p><p>Последний пункт особенно важен. Если флаги не удалять, система быстро превращается в набор ветвлений, где никто уже не понимает, какая логика актуальна.</p><h2>Shadow testing: как проверить новую систему на реальном трафике</h2><p>Feature toggles помогают безопасно переключать пользователей. Но перед этим хорошо бы понять, совпадает ли новая логика со старой. Для этого используют shadow testing.</p><p>Shadow testing — это запуск новой реализации параллельно старой, но без влияния на пользователя. Пользовательский запрос по-прежнему обрабатывает старая система, а новая получает копию запроса и считает результат «в тени». Пользователю этот результат не показывается. Команда только сравнивает ответы.</p><p>Например, есть старый модуль расчета скидок. Он учитывает промокоды, сегмент пользователя, историю покупок, регион и партнерские условия. Команда пишет новый сервис скидок. Чтобы не переключать пользователей сразу, можно запустить теневой режим:</p><p>Два момента, на которые стоит обратить внимание в этом коде. Теневой вызов запускается через asyncio.create_task — корутина сразу планируется в event loop и начнёт выполняться, как только функция вернёт управление. И весь блок завернут в try/except: исключение в новой логике не должно ронять основной запрос. Без этих двух свойств shadow testing рискует ухудшить продакшен вместо того, чтобы безопасно его проверить.</p><p>Небольшая оговорка для продакшена: event loop держит на task только слабую ссылку, и без сохранённой ссылки задача может быть собрана сборщиком мусора прямо во время выполнения. В реальном коде Task имеет смысл класть в set фоновых задач и удалять оттуда через add_done_callback. В примере выше эта обвязка опущена для читаемости.</p><p>Для критичной доменной логики — платежей, биллинга, расчета тарифов — допустимый уровень расхождения должен быть около нуля: цель в shadow-режиме не «как можно меньше различий», а «понимаем каждое расхождение». Для менее чувствительных доменов (рекомендации, ранжирование результатов поиска) можно жить с расхождением в долях процента, но и там расхождения нужно классифицировать, а не игнорировать. Возможно, это баги новой реализации. А возможно, старая система содержит устаревшую логику, которую нужно отдельно обсудить с бизнесом.</p><p>Shadow testing особенно полезен для критичных доменных частей: платежей, биллинга, расчета тарифов, персональных предложений, транзакций. Там нельзя просто «попробовать на пользователях» и посмотреть, что будет.</p><p>При этом важно отличать теневую проверку чтения от теневой проверки записи. Чтение проверить относительно дёшево: запрос идёт в обе системы, ответы сравниваются, никаких внешних эффектов нет. С записью всё сложнее. Если новая реализация в shadow-режиме действительно создаст заказ, спишет деньги или отправит письмо, у пользователя возникнут двойные эффекты. Поэтому для writes либо вводят идемпотентные ключи и shadow-режим без реальных побочных действий (внешние вызовы заменены no-op-стабами, БД — отдельной shadow-копией), либо вообще отказываются от теневой проверки записи в пользу постепенной выкатки за фича-флагом.</p><p>Сравнение ответов в реальной системе тоже не сводится к одной функции compare. Нужно отдельно решать, как игнорировать «нормальный» шум (метки времени, идентификаторы, порядок коллекций), как сэмплировать трафик, чтобы не утопить хранилище расхождений, и как организовать триаж — кто и в каком ритме разбирает накопившиеся диффы. Готовые решения этого класса — GitHub Scientist (Ruby и его порты в другие языки), Twitter Diffy, либо собственный лёгкий регистратор поверх Kafka и таблицы расхождений.</p><h2>С чего начинать модернизацию</h2><p>Начинать лучше не с самого больного и не с самого центрального модуля. Это звучит контринтуитивно, потому что обычно хочется сразу взяться за главный источник проблем. Но если начать с ядра системы, команда быстро упрется в максимальное количество зависимостей и рисков.</p><p>Удобный способ выбрать первый кусок — оценить кандидатов по двум осям: насколько модуль критичен для бизнеса (low / high) и насколько сильно он связан с остальной системой (low / high). Начинать стоит с квадранта low-criticality + low-coupling: ошибки в нем не уронят бизнес-показатели, а малое количество зависимостей позволит провести миграцию полностью, не утянув за собой смежные модули. Высоко-критичные и сильно связанные части (платежи, ядро авторизации) трогают в последнюю очередь — на этот момент команда уже наберёт опыт безопасной миграции.</p><p>Хорошие точки входа обычно: уведомления, генерация отчетов, поиск, история операций, профиль пользователя, отдельная часть каталога. Важно, чтобы у команды была возможность описать контракт: какие данные входят, какие выходят, какие ошибки возможны, какие внешние системы участвуют.</p><p>Допустим, в банковском приложении есть старый модуль истории операций. Он медленный, сложно расширяется, но при этом не выполняет сами транзакции. Это хороший кандидат для первой миграции. Ошибка в истории операций неприятна, но обычно менее критична, чем ошибка в списании денег.</p><p>Команда может вынести чтение истории в отдельный сервис, сначала запустить его в shadow-режиме, потом включить для части пользователей, затем полностью перевести чтение на новую реализацию. При этом критичная транзакционная логика останется в старой системе до тех пор, пока команда не наберет опыт безопасной миграции.</p><h2>Миграция данных: самая сложная часть</h2><p>Большая часть статьи говорит о маршрутизации запросов и переключении трафика. Но в реальных проектах основная сложность лежит ниже — в данных. Старая и новая реализации почти всегда работают с общим состоянием: одной БД, одним хранилищем документов, одним набором очередей. Переехать туда «одним коммитом» нельзя.</p><p>Базовый рабочий приём — Expand-Contract (он же Parallel Change). Изменение схемы делается в три такта. На этапе expand в БД добавляются новые поля, таблицы или индексы, при этом старое поведение полностью сохраняется. Затем — migrate: обе реализации начинают писать и в старое, и в новое место (dual writes), а отдельный фоновый процесс делает backfill — заполняет новые поля историческими данными. После этого читатели по одному переключаются на новую схему. Только когда никто из читателей не использует старую структуру, наступает contract — удаление лишних колонок и таблиц.</p><p>Несколько практических деталей, которые часто упускают:</p><p>·         Dual writes — это не бесплатная операция. Две записи означают две точки отказа. Если одна из них упала, нужно решать, что делать: продолжать ли работу, ставить ли событие в очередь на повтор, помечать ли запись как несогласованную. Простое «сначала пишем туда, потом сюда» в продакшене на нагрузке приводит к расхождениям.</p><p>·         Backfill часто длиннее, чем кажется. На большой таблице миграция в одном UPDATE блокирует продакшен. Поэтому backfill делают батчами по N тысяч строк с паузами, отслеживают прогресс и предусматривают возможность остановить и продолжить.</p><p>·         Онлайн-изменения схемы на крупных таблицах делаются не штатным ALTER TABLE, а специализированными инструментами: gh-ost или pt-online-schema-change для MySQL, встроенные онлайн-механизмы PostgreSQL для индексов и колонок, Liquibase/Flyway — для управления версионированием изменений в репозитории.</p><p>·         Shadow testing данные не покрывает. Можно сравнить, что новая реализация возвращает то же, что и старая, но если за этим стоит другая схема в БД, проверка корректности самой миграции данных — это отдельная работа: сверки, контрольные суммы, выборочный аудит исторических записей.</p><p>Без этих шагов любая красивая фасадная архитектура наталкивается на разъезжающиеся данные — и тогда даже идеальный Strangler Fig снаружи не спасает.</p><h2>Прокси-слой как точка контроля</h2><p>Чтобы постепенно заменять legacy-код, нужно управлять маршрутизацией запросов. Для этого часто создают прокси-слой, API Gateway или фасад, через который проходит обращение к старой и новой логике. В терминах Domain-Driven Design такой слой часто называют Anti-Corruption Layer: он защищает новую реализацию от старых контрактов и наоборот, позволяя двум моделям сосуществовать без взаимного «загрязнения».</p><p>Без такой точки контроля миграция становится хаотичной. Часть клиентов ходит напрямую в старый модуль, часть — в новый, часть использует обходные пути, а команда теряет возможность централизованно переключать трафик.</p><p>Прокси-слой решает несколько задач. Он скрывает детали реализации от клиентов, позволяет направлять часть запросов в новую систему, поддерживает фича-флаги, собирает метрики и упрощает откат.</p><p>В качестве технической основы команды обычно берут один из трех вариантов: классический API gateway (Kong, AWS API Gateway), service mesh (Envoy, Istio) или более простой reverse proxy (NGINX, HAProxy). Service mesh особенно удобен, когда трафик уже идёт внутри Kubernetes-кластера: маршрутизацию можно менять конфигурацией, без правок кода клиентов и сервисов.</p><p>Например, мобильное приложение обращается к endpoint /orders/history. Раньше этот endpoint напрямую обслуживал монолит. После введения API Gateway приложение продолжает ходить по тому же контракту, но внутри gateway может решать, куда направить запрос: в legacy-модуль или новый сервис истории заказов.</p><p>Управление маршрутизацией обычно делается не «всё или ничего», а на основании атрибутов запроса: значения заголовка (X-Migration-Cohort: new), куки, хэша от user-id (стабильное разбиение пользователей на сегменты) или географического региона. Это позволяет выкатывать новую реализацию сначала на одну страну, на сотрудников самой компании или на тестовый сегмент — и только потом расширять охват.</p><p>Для клиента ничего не меняется. Для команды появляется управляемость.</p><h2>Наблюдаемость: без метрик миграция превращается в гадание</h2><p>Постепенная модернизация невозможна без нормальной наблюдаемости. Если команда не видит, что происходит внутри системы, она не сможет безопасно переключать трафик.</p><p>Минимальный набор — это логи, метрики и распределенная трассировка (distributed tracing). Нужно понимать, сколько запросов идет в старую и новую реализацию, сколько ошибок возникает, как меняется latency, где появляются таймауты, какие статусы возвращаются, какие бизнес-метрики проседают.</p><p>Технические метрики стоит формулировать не как «средний ответ» и «процент ошибок», а в терминах SLI и SLO: целевые показатели вида «99.9% запросов на /orders/history отвечают быстрее 300 ms за 30 дней» с явным error budget. Latency измеряется по перцентилям (p50, p95, p99) — среднее значение почти всегда обманчиво, а хвосты распределения говорят о реальном опыте пользователя. На время миграции имеет смысл выставить отдельные SLO для нового и старого пути и сравнивать их.</p><p>В качестве инструментов де-факто стандартом стал OpenTelemetry для трассировок, метрик и логов — единый протокол, который пишет в практически любое хранилище. Дальше — Prometheus и Grafana для метрик, Jaeger или Tempo для traces, Sentry или аналог для ошибок. Для миграции важна возможность фильтровать метрики по «варианту» — отдельно по старому и новому пути — иначе все цифры смешаются и реальную динамику будет не видно.</p><p>Технических метрик недостаточно. Если команда переносит оформление заказа, важно смотреть не только на 500 ошибки и время ответа, но и на конверсию в оплату, количество брошенных корзин, повторы запросов, обращения в поддержку.</p><p>Пример: новая система формально отвечает быстрее старой и не дает ошибок. Но после включения на 10% пользователей падает конверсия в оплату. Причина может быть не в серверной ошибке, а в изменении порядка полей, другом тексте сообщения или потере какого-то edge-case. Без бизнес-метрик команда может решить, что миграция успешна, хотя для продукта она уже создает проблему.</p><h2>Практическая последовательность миграции</h2><p>Рабочая последовательность обычно выглядит так.</p><p>Сначала команда выбирает ограниченный участок системы. На этом этапе важно не просто назвать модуль, а описать его границы. Какие сценарии он закрывает? Кто его вызывает? Какие данные он читает и пишет? Какие внешние интеграции использует? Какие неочевидные бизнес-правила в нем есть?</p><p>Затем поверх legacy-логики создается стабильный контракт. Это может быть API, фасад, gateway или отдельный слой внутри приложения. Главная задача — сделать так, чтобы клиенты зависели не от внутренней реализации, а от понятного интерфейса. На этом этапе полезно вспомнить про contract testing (Pact, Spring Cloud Contract): автотесты со стороны потребителей фиксируют, что именно они ожидают от API, и предупреждают о ломающих изменениях до того, как они доедут до продакшена.</p><p>После этого рядом пишется новая реализация. Она должна повторять текущее поведение, а не сразу становиться «идеальной версией будущего». На этом этапе полезно фиксировать все расхождения: где старая система работает странно, где требования не описаны, где бизнес-правила требуют уточнения.</p><p>Следующий этап — shadow testing. Новая система получает копии реальных запросов, считает результат, но пользователю по-прежнему возвращается ответ legacy. Команда сравнивает результаты и устраняет расхождения.</p><p>Когда новая реализация достаточно стабильна, начинается постепенное переключение через feature toggles. Сначала внутренние пользователи, потом 1% реального трафика, затем 5–10%, затем 50% и только после этого 100%.</p><p>На каждом этапе команда смотрит на метрики. Если всё стабильно, движение продолжается. Если появляются проблемы, флаг выключается, трафик возвращается в legacy, а команда разбирает причины.</p><p>Последний этап — удаление старого кода. Это не формальность, а обязательная часть миграции. И «удалить старый код» — это не один коммит, а явный Definition of Done: вырезана старая ветка кода, удалён фича-флаг, обновлена документация и схемы архитектуры, переименованы или удалены устаревшие дашборды и алерты, обновлены runbook’и для on-call и проведено короткое внутреннее обучение. Если этого не сделать, через полгода никто уже не вспомнит, какой путь актуален, и легаси-ветвление останется в коде навсегда.</p><h2>Откат миграций: дешёвый только пока не пошли записи</h2><p>Откатить миграцию, в которой ещё не было записи в БД, легко: достаточно переключить фича-флаг, и трафик снова идёт через старую реализацию. Откатить миграцию, в которой новая система уже неделю писала данные в новые таблицы, — отдельный, гораздо более тяжёлый разговор.</p><p>Поэтому ещё на этапе проектирования каждое изменение должно сопровождаться явным планом отката. Удобно различать три типа шагов.</p><p>Полностью обратимые шаги. Чтение через новый сервис, расчёт «в тени», новые метрики. Откат — выключить флаг. Это самый комфортный режим, и в нём стоит держать миграцию как можно дольше.</p><p>Обратимые с компенсацией. Новая реализация пишет дополнительные данные (например, дублирует операции в новую таблицу), но старый источник тоже обновляется. Откат возможен, но требует решить, что делать с уже записанными данными: оставить, очистить, синхронизировать. План этих действий должен быть написан до выкатки, не во время инцидента.</p><p>Forward-only. После некоторой точки откат становится невозможен — например, после того, как старая схема удалена или внешние интеграции перенастроены на новый сервис. Такие шаги допустимы, но к ним нужно приходить отдельно, осознанно, с особенно строгими SLO в предыдущем этапе. До forward-only-перехода имеет смысл подержать систему в режиме параллельной работы дольше, чем по графику.</p><p>Базовое правило: ни один шаг миграции не должен уходить в продакшен, если у команды нет письменного ответа на вопрос «как мы откатываемся в случае проблемы». Иначе при инциденте откатываться будут на ходу — и не факт, что успешно.</p><h2>Пример: как тот же сервис мигрировали со второй попытки</h2><p>После неудачного опыта команда взялась за тот же сервис заново, но изменила подход.</p><p>На первом шаге они зафиксировали поведение существующего сервиса. На самые часто используемые сценарии (создание путевого листа, подпись акта осмотра, выгрузка пакета документов за период) написали характеристические тесты на реальных продакшен-данных, обезличенных и сохранённых как фикстуры. Любое будущее изменение поведения теперь падало в CI как явное расхождение.</p><p>Параллельно команда провела инвентаризацию побочных эффектов. Из исходного кода и логов выяснилось, что сервис не только хранит документы, но и: публикует событие в Kafka при смене статуса, инкрементирует счётчик в Redis для рейтинга водителей, отправляет webhook во внешнюю систему партнёра, пишет в таблицу аудита. Каждый из этих эффектов попал в отдельный пункт чек-листа «что должно остаться» в новой реализации.</p><p>Затем команда выбрала первый кусок для выноса — не весь сервис, а только чтение документов (GET /documents/{id} и GET /documents/by-driver/{driver_id}). Это была наименее рискованная часть: ошибки в чтении неприятны, но не ломают финансовые потоки.</p><p>Новый сервис написали на FastAPI рядом со старым. На уровне API Gateway появилось правило маршрутизации: запросы на чтение шли в старый сервис, но в фоне дублировались в новый. Ответ пользователю всегда возвращал legacy, а ответ нового сервиса сравнивался с эталоном и записывался в отдельную таблицу для разбора. Использовали обёртку поверх asyncio.create_task — на ответ пользователя теневой вызов не влиял.</p><p>За три недели shadow-режима команда нашла четыре расхождения. Два оказались багами новой реализации (округление времени, неправильная сортировка вложений). Два — давно забытыми особенностями старого сервиса (одно поле возвращалось в UTC, другое — в локальной зоне; так было исторически, бизнес не возражал, но в новой реализации захотели единый формат). Все четыре зафиксировали явно: баги — починили, особенности — согласовали с продуктовой командой как осознанное изменение.</p><p>Когда расхождений не осталось, включили фича-флаг на сотрудников самой компании. Через неделю — на 1% реальных водителей. Дальше шаг по 5%, 25%, 50%, 100% с паузой в несколько дней между этапами. На каждом шаге следили не только за HTTP-ошибками и latency, но и за продуктовыми метриками: количество подписанных актов, время от открытия документа до подписи, доля повторных запросов. Один раз пришлось откатиться с 25% на 5% — в одном из регионов выросло время отклика из-за неэффективного запроса. Исправили, выкатили снова.</p><p>Через два месяца чтение полностью перешло в новый сервис. Старый код чтения и фича-флаг удалили в том же релизе. После этого по той же схеме мигрировали запись документов, потом публикацию событий, потом импорт из внешних систем. Полная миграция заняла девять месяцев — почти столько же, сколько провалившийся Big Bang, — но продукт всё это время продолжал развиваться, инцидентов не было, и в конце команда осталась с системой, которую понимает.</p><h2>Типичные ошибки при работе с legacy</h2><p>Первая ошибка — пытаться улучшить всё сразу. Команда одновременно меняет архитектуру, бизнес-логику, контракты и инфраструктуру. В результате становится невозможно понять, какая именно часть вызвала проблему. Правильнее сначала воспроизвести поведение, стабилизировать новую реализацию и только потом улучшать.</p><p>Вторая ошибка — недооценивать скрытые зависимости и побочные эффекты. Legacy-код часто делает больше, чем кажется. На один и тот же вызов могут быть навешаны: запись в таблицу аудита, инкремент счётчика в кэше, публикация события в очередь, обновление статуса связанной сущности, инвалидация кэша, дёрганье webhook’а во внешнюю систему. Если в новой реализации воспроизвести только явный путь, скрытые потребители молча перестанут получать данные — и узнают об этом через жалобу бизнеса, а не через ошибку в логах. Поэтому перед выносом любого модуля имеет смысл составить инвентаризацию побочных эффектов: пройтись по коду и логам и выписать каждое нелогичное действие отдельным пунктом чек-листа.</p><p>Третья ошибка — отсутствие наблюдаемости. Без логов, метрик и трассировки команда не управляет миграцией, а угадывает. Особенно опасно смотреть только на технические ошибки и игнорировать бизнес-показатели.</p><p>Четвертая ошибка — не договариваться с бизнесом. Модернизация не должна быть невидимой «инженерной активностью в стол». Её нужно встраивать в roadmap, объяснять эффект и договариваться о приоритетах. Если бизнес не понимает, зачем команда тратит время на миграцию, работа будет постоянно проигрывать новым фичам.</p><p>Пятая ошибка — не удалять старый код. Временное сосуществование старой и новой логики нормально. Вечное сосуществование — нет. Если legacy не удаляется, технический долг не уменьшается, а просто меняет форму.</p><p>Шестая ошибка — не удалять фича-флаги после миграции. Флаг, который сыграл свою роль и больше никогда не выключается, превращается в постоянное ветвление в коде. Через год команда не помнит, можно ли удалить такую ветку или там сидит важный edge-case. Через два — кода с такими «мёртвыми» флагами становится больше, чем основной логики. Поэтому каждый флаг должен заводиться с условием удаления («после полной выкатки и двух недель стабильной работы») и иметь ответственного, кто этим удалением займётся.</p><p>Отдельно стоит упомянуть организационную сторону. Закон Конвея работает и в обратную сторону: если новый и старый код владеются разными командами с разными приоритетами, миграция будет тормозиться независимо от выбранного паттерна. На время миграции имеет смысл явно проговорить, кто отвечает за переход, и не разделять старую и новую реализации между несовместимыми roadmap’ами.</p><h2>Компромиссы, к которым нужно быть готовыми</h2><p>Постепенная модернизация безопаснее Big Bang-переписывания, но она не бесплатна. Некоторое время система будет сложнее, чем раньше. В ней появятся старый и новый код, прокси-слой, фича-флаги, дублирование логики, дополнительные метрики.</p><p>Shadow testing увеличит нагрузку на инфраструктуру, потому что часть запросов будет обрабатываться дважды. Команде придется поддерживать дисциплину: документировать контракты, отслеживать флаги, удалять старую реализацию после миграции, поддерживать contract-тесты в актуальном состоянии.</p><p>Но это контролируемая сложность. Она распределена во времени и управляется инженерными практиками. В отличие от Big Bang-риска, где команда долго работает с минимальной обратной связью, а потом выкатывает один большой релиз с максимальной неопределенностью.</p><h2>Когда Strangler Fig особенно оправдан</h2><p>Постепенная миграция особенно хорошо подходит для систем, где downtime невозможен или слишком дорог. Это финтех, e-commerce, биллинг, мобильные бэкенды с большой аудиторией, высоконагруженные продукты, старые монолиты и системы с большим количеством интеграций.</p><p>Если продуктом ежедневно пользуются сотни тысяч или миллионы людей, нельзя позволить себе «переписать и посмотреть, что будет». Нужно менять архитектуру так, чтобы пользователь не замечал процесса миграции.</p><p>Этот подход также полезен там, где бизнес продолжает активно развивать продукт. Если фичи нельзя заморозить на полгода, модернизация должна идти параллельно с продуктовой разработкой.</p><h2>Когда модернизацию лучше не делать</h2><p>Постепенная миграция — мощный инструмент, но у неё тоже есть стоимость, и иногда правильный ответ — оставить систему как есть. Несколько сценариев, в которых модернизация плохо окупается.</p><p>Продукт, который уходит из эксплуатации. Если через год сервис будет выключен или заменён на покупное решение, тратить квартал на его рефакторинг бессмысленно. Достаточно стабилизировать то, что есть.</p><p>Модуль, который никто не трогает. Если код десятилетней давности продолжает работать, не падает, не требует изменений и не вызывает инцидентов, его «уродливость» — не повод его переписывать. Цель модернизации — упростить будущие изменения; если будущих изменений нет, цели тоже нет.</p><p>Регулируемые системы с тяжёлой ресертификацией. В банковских, медицинских и государственных контурах любое изменение в критичной системе может потребовать повторной сертификации, перепрохождения аудитов, обновления договорной обвязки. В таких условиях стоимость модернизации может на порядок превышать стоимость поддержки текущей реализации, и решение нужно принимать вместе с владельцем продукта и юристами, а не только инженерным составом.</p><p>Простой тест: если на вопрос «какой бизнес-сценарий мы откроем после миграции» нет внятного ответа — модернизацию имеет смысл отложить и заняться чем-то другим.</p><h2>Что получает команда</h2><p>Главный результат постепенной модернизации — управляемость. Команда начинает лучше понимать систему, контролировать изменения и снижать риск инцидентов.</p><p>Появляются понятные контракты, наблюдаемость, практика безопасных релизов, культура удаления старого кода. Разработчики перестают бояться legacy, потому что у них появляется метод, а не только желание «когда-нибудь всё переписать».</p><p>Для бизнеса это тоже выгодно. Продукт продолжает развиваться, сроки становятся более прогнозируемыми, риски крупных сбоев снижаются, а технический долг постепенно уменьшается.</p><h2>Модернизация — это процесс, а не проект</h2><p>Legacy нельзя «починить за квартал». Если система развивалась годами, она не станет простой после одного рефакторинга. Но её можно системно улучшать.</p><p>Strangler Fig Pattern, Branch by Abstraction, feature toggles, shadow testing и аккуратная миграция данных дают рабочую модель: выбрать ограниченный участок, описать контракт, реализовать новую версию, проверить её на реальном трафике, постепенно переключить пользователей и удалить старый код.</p><p>Это не самый быстрый путь. Зато он управляемый. А в зрелых продуктах управляемость важнее скорости.</p><p>Потому что цель модернизации — не написать красивую новую систему. Цель — сделать так, чтобы продукт продолжал развиваться, команда могла безопасно вносить изменения, а пользователи не становились участниками инженерного эксперимента.</p>]]></content:encoded>
    </item>
    <item>
      <title>Netflix построила Service Topology: живая карта микросервисов</title>
      <link>https://tproger.ru/articles/netflix-postroila-zhivuyu-kartu-servisov-kak-ustroena-service-top</link>
      <comments>https://tproger.ru/articles/netflix-postroila-zhivuyu-kartu-servisov-kak-ustroena-service-top?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/netflix-postroila-zhivuyu-kartu-servisov-kak-ustroena-service-top</guid>
      <description><![CDATA[<p>Как Netflix объединяет eBPF, IPC-метрики и tracing в единую карту зависимостей. Разбираем, почему статические схемы устарели и что перенести в свою систему.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/netflix-postroila-zhivuyu-kartu-servisov-kak-ustroena-service-top">Netflix построила Service Topology: живая карта микросервисов</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Linux]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Микросервисы]]></category>
      <category><![CDATA[Архитектура ПО]]></category>
      <category><![CDATA[DevOps]]></category>
      <category><![CDATA[Графы]]></category>
      <category><![CDATA[Архитектура приложений]]></category>
      <category><![CDATA[Инфраструктура]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 19 Jun 2026 07:47:47 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если вы хоть раз отлаживали микросервис ночью, знаете главный вопрос: это мой сервис сломался или его уронило что-то выше по течению? В системе из тысяч сервисов ответ приходится искать по кускам — метрики, логи и трейсы показывают симптомы, но не дают единой карту зависимостей. Netflix столкнулась с этой же болью и построила инструмент под названием Service Topology, который рисует живую карту зависимостей в реальном времени.</p><p>Service Topology — это не статическая схема из вики, а динамическая карта связей между сервисами. Она обновляется по мере того, как меняется трафик, появляются новые зависимости или старые исчезают. Карта показывает не только «кто с кем говорит», но и контекст: уровень доступности, бизнес-домен, владельца и текущее состояние здоровья.</p><p>Если тема микросервисов для вас новая, начните с базового разбора <a href="https://tproger.ru/articles/chto-takoe-mikroservisy--arhitektura--plyusy-i-minusy--primery">«Что такое микросервисы»</a>, а если выбираете архитектуру для проекта — сравните варианты в материале <a href="https://tproger.ru/articles/monolit-ili-mikroservisy--kak-vybrat-arhitekturu-dlya-novogo-proekta">«Монолит или микросервисы»</a>. Авторский разбор внутреннего устройства Netflix читайте в статье <a href="https://tproger.ru/articles/razrabotchik-izuchal-sistemu-rekomendacij-netflix-mesyacami--vot-chto-skryvaetsya-vnutri">«Разработчик изучал систему рекомендаций Netflix месяцами»</a>.</p><ul><li>Netflix объединила три источника данных: eBPF-сетевые потоки, IPC-метрики и распределённые трейсы.</li><li>Каждый источник строит свой граф; общий вид получается параллельным слиянием слоёв.</li><li>Карта обновляется почти в реальном времени и отвечает на запросы быстрее секунды.</li><li>Инженеры используют её для поиска причин сбоев, оценки зоны поражения и планирования изменений.</li><li>Подход можно перенести в любую распределённую систему, где нужно понимать зависимости.</li></ul><h2>Почему обычной наблюдаемости мало</h2><p>Традиционные инструменты наблюдаемости показывают фрагменты картины. Метрики говорят, что что-то болит. Логи рассказывают, что конкретно произошло в одном сервисе. Трейсы прослеживают путь отдельного запроса. Но ни один из этих сигналов не показывает полную топологию зависимостей — ту самую основу, на которой держится распределённая архитектуры.</p><p>Инженеру в три часа ночи приходится мысленно склеивать данные из разных источников. Это медленно, чревато ошибками и добавляет стресса. Netflix проанализировала тысячи обращений в поддержку за четыре года и увидела повторяющиеся вопросы: кто мои upstream и downstream, что упадёт вместе со мной, почему сервис отображается в панели мониторинга как Unknown (неизвестный сервис). Ответы на них требовали единого представления о зависимостях.</p><h2>Три источника данных Service Topology</h2><p>Главный вывод Netflix: ни один источник не рассказывает всю историю. Поэтому система строит три независимых графа и объединяет их по запросу.</p><h3>Сетевые потоки eBPF</h3><p>На сетевом уровне Netflix собирает потоки ядра через eBPF. Это даёт полноту: сюда попадают все соединения, независимо от того, инструментирован сервис или нет. Слой показывает связи между кластерами и приложениями такими, какими они есть на самом деле. Недостаток — не хватает прикладного контекста: видно, что сервис А достучался до IP-адреса сервиса Б, но неизвестно, какой конкретно endpoint вызывался.</p><h3>IPC-метрики</h3><p>На прикладном уровне собираются метрики межпроцессного взаимодействия. Когда сервис обращается к другому через gRPC, GraphQL или REST, он фиксирует endpoint, ошибки, задержки и протокол. Этот слой даёт детали, которых нет у сетевого: какой именно путь вызывается и с какой вероятностью ошибки. Ограничение очевидно: если сервис не отправляет метрики, его вызовов здесь не будет.</p><h3>Распределённые трейсы</h3><p>Третий слой — трейсинг запросов от начала до конца. Он показывает не «может ли сервис А позвонить сервису Б», а «звонил ли он в рамках этого конкретного пользовательского запроса». Это помогает увидеть поведение во время выполнения, ветвления, фича-флаги и редкие пути. Поскольку трейсы собирают выборочно, редкие сценарии могут не попасть в агрегированный вид.</p><p>Когда инженер запрашивает общую картину, система обходит все три графа параллельно и сливает результаты. Сеть обеспечивает полноту, IPC добавляет контекст, трейсы показывают реальное поведение. Каждый источник компенсирует слабости остальных.</p><h2>Как собирают Service Topology</h2><h3>Приём и обработка потоков</h3><p>За кулисами работает конвейер, который держит миллионы событий в секунду. Потоки сетевых логов читаются из Kafka в нескольких регионах AWS. Для обработки Netflix использует Apache Pekko Streams — форк Akka, который разбивает нагрузку по группам автомасштабирования и сам управляет обратным давлением.</p><h3>Восстановление прямых связей</h3><p>Сетевой лог показывает отдельные сетевые прыжки: например, приложение → балансировщик → приложение или приложение → NAT-шлюз → приложение. Чтобы получить настоящие связи, запускается трёхступенчатая агрегация. Первая стадия забирает сырые записи, вторая распознаёт посредников и восстанавливает прямые пути между приложениями, третья финализирует агрегаты и добавляет статус здоровья. Такой градуированный подход раскидывает нагрузку и не даёт горячим узлам уронить весь конвейер.</p><p>Готовая топология хранится в графовой базе Netflix — абстракции поверх распределённого хранилища «ключ — значение». Она заточена под быстрый обход графа в несколько хопов. Поверх базы — gRPC-API с фильтрами по уровню доступности и домену, постраничным выводом больших выборок и ответом менее чем за секунду.</p><h3>Хранение и API</h3><p>Отдельно стоит возможность «путешествия во времени». Система не хранит каждый момент отдельно, а накапливает данные в скользящих окнах. Это позволяет спросить «как выглядела топология вчера в полночь» без взрыва объёмов хранения.</p><h2>Что даёт инженерам</h2><p>Интерфейс и API дают инженерам несколько рабочих сценариев — от ручного расследования до автоматических проверок.</p><ul><li>Видеть upstream и downstream для любого сервиса с фильтрами по уровню доступности и домену.</li><li>Переключаться между единым видом и отдельными слоями: только сеть, только IPC или только трейсы.</li><li>Одним кликом переходить от узла топологии к логам, трейсам и детальным метрикам.</li><li>Оценивать зону поражения перед отключением сервиса на обслуживание и понимать, кого уведомлять.</li><li>Накладывать статус здоровья на граф и быстро понимать, локальная ли это проблема или каскадный сбой.</li><li>Обращаться к топологии программно — например, чтобы автоматически проверять классификацию доступности критичных сервисов.</li><li>Смотреть историю зависимостей и находить, что изменилось перед инцидентом.</li></ul><h2>Как перенести в свою систему</h2><p>Не каждая компания работает в масштабе Netflix, но логика подхода универсальна. Если у вас десятки сервисов, уже появляется эффект «тысячи кусочков пазла». Начать можно с малого: собрать список зависимостей из существующих источников и периодически сверять его с реальным трафиком.</p><p><b>Чек-лист для первых шагов:</b><br />1. Выберите один настоящий источник связей: логи балансировщика, агент на хосте или метрики вызовов.<br />2. Не пытайтесь сразу построить идеальную модель — начните с автоматически обнаруженных рёбер.<br />3. Добавьте контекст: владельца сервиса, уровень критичности и домен.<br />4. Сделайте карту доступной программно, а не только в интерфейсе — инцидент-боты и скрипты будут благодарны.<br />5. Проверяйте актуальность: в динамичной среде карты, устаревшие на несколько часов, быстро теряют ценность.</p><p>Для иллюстрации вот минимальный скрипт, который строит рёбра графа из логов балансировщика:</p><h2>Часто задаваемые вопросы</h2><h2>Выводы</h2><p>Service Topology — не просто красивая картинка для панели мониторинга. Это операционная основа, которая ускоряет расследования, снижает риск изменений и даёт автоматическим системам общую картину инфраструктуры. Netflix называет её knowledge graph foundation — фундаментом для интеллектуальной автоматизации, в том числе для автоматического поиска первопричины сбоев.</p><blockquote>Service topology provides the knowledge graph foundation that makes this kind of intelligent automation possible.</blockquote><p>Для российских команд, где инфраструктура тоже стремительно усложняется, главный урок в другом: не ждите идеальной полноты данных. Начните с одного реального источника, добавьте контекст, сделайте карту программно доступной — и она начнёт приносить пользу раньше, чем вы построите «полноценную» систему.</p><h2>Источники</h2><ul><li><a href="https://medium.com/netflix-techblog/from-silos-to-service-topology-why-netflix-built-a-real-time-service-map-0165ba13a7bc">From Silos to Service Topology: Why Netflix Built a Real-Time Service Map</a></li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Production-safe агентный цикл: как не дать ИИ сжечь бюджет</title>
      <link>https://tproger.ru/articles/production-safe-agentnyj-cikl-kak-ne-dat-ii-szhech-byudzhet</link>
      <comments>https://tproger.ru/articles/production-safe-agentnyj-cikl-kak-ne-dat-ii-szhech-byudzhet?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/production-safe-agentnyj-cikl-kak-ne-dat-ii-szhech-byudzhet</guid>
      <description><![CDATA[<p>Как построить production-safe агентный цикл на Python, чтобы ИИ не сжигал бюджет в бесконечных итерациях. Разбираем circuit breaker, ledger и human attestation.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/production-safe-agentnyj-cikl-kak-ne-dat-ii-szhech-byudzhet">Production-safe агентный цикл: как не дать ИИ сжечь бюджет</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Машинное обучение]]></category>
      <category><![CDATA[Фреймворки и библиотеки]]></category>
      <category><![CDATA[Информационная безопасность]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 17 Jun 2026 09:45:21 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если ваш ИИ-агент работает круглосуточно и не может остановиться — это не автономность, а биллинговая авария, которая уже идёт. В июле 2025 года рекурсивный агентный цикл в Claude Code сжёг от 16 000 до 50 000 долларов за пять часов. Агенты не падают и не выдают ошибку: они делают ровно то, что им сказали, — пока кто-то не скажет остановиться.</p><p>Через четыре месяца четырёхагентный пайплайн на LangChain крутился одиннадцать дней и стоил 47 000 долларов. Никто не заметил, пока не пришёл счёт. Тот же паттерн: цикл работал корректно, но у него не было условия выхода.</p><p>Проблема не в моделях, а в отсутствии условия остановки. В этой статье разберём, как собрать минимальный, но production-ready каркас агентного цикла: спецификацию до запуска, предохранитель по токенам и ходам, неизменяемый аудит и поверхность для человеческого согласования. Полный код и 80 тестов с 100% покрытием доступны в <a href="https://github.com/dannwaneri/production-safe-agent-loop">репозитории автора оригинала</a>.</p><p>Агентные циклы сжигают бюджет не из-за плохих моделей, а из-за нечёткого условия остановки.</p><p>Спецификация должна отвечать на три вопроса: что делает, что не делает и что значит «готово» — в одном предложении.</p><p>Circuit breaker режет цикл по жёстким потолкам: число ходов и суммарные токены. Проверка — до вызова модели, а не после.</p><p>Ledger в SQLite фиксирует каждый ход: хеш входа, дельту токенов, время, результат. Это аудит, а не лог для отладки.</p><p>Review surface даёт поверхность для обязательной человеческой аттестации и формирует аудиторскую квитанцию frame_hash, которую вызывающий код может использовать как условие передачи результата в прод.</p><h2>Что такое агентный цикл и почему он уходит в бесконечность</h2><p>Агентный цикл — это конструкция вида while True, внутри которой языковая модель получает задачу, вызывает инструменты, анализирует результат и решает, продолжать или закончить. Такие циклы лежат в основе оркестраторов вроде LangGraph, CrewAI и AutoGen, а также внутри coding-агентов. Если только начинаете разбираться с LLM, полезно сначала понять, <a href="https://tproger.ru/articles/chto-takoe-llm-dlya-nachinayushhih">как устроены большие языковые модели</a>, а для практики — заглянуть в <a href="https://tproger.ru/articles/python-dlya-nachinayushhih">основы Python</a>.</p><p>Цикл уходит в бесконечность не потому, что модель «глупая», а потому, что никто не определил, что значит «готово». Модель видит неоднозначность и пытается быть полезной: перефразирует вызов инструмента, запускает верифицирующего агента, тот находит «проблему», срабатывает корректирующий агент — и так далее. На дашбордах всё выглядит активно: растёт число вызовов инструментов, completion rate держится высоким, а бюджет течёт в пустоту.</p><p><b>Почему дорожает каждая итерация:</b><br />Агент не начинает с чистого листа. Он каждый раз перечитывает всё предыдущее окно контекста — все неудачные попытки, все промежуточные выводы. Итерация 1 стоит 100 токенов, итерация 10 — уже тысячи. Вы платите за каждый провал снова и снова.</p><h2>Почему компании сначала платят за чатбота, а потом за агентный рабочий процесс</h2><p>Gartner фиксирует разрыв в потреблении токенов между пилотными чатботами и production-агентными рабочими процессами в 5–30 раз. А отчёт FinOps Foundation за 2026 год говорит, что 73% компаний превысили изначальный бюджет на ИИ. Цифры взяты из <a href="https://www.freecodecamp.org/news/how-to-build-a-production-safe-agent-loop-from-exit-conditions-to-audit-trails/">оригинального туториала</a>; полные отчёты Gartner и FinOps Foundation доступны по платным подпискам. Причина разрыва — в неправильном масштабировании: команда планировала стоимость чатбота (~0,04 USD за взаимодействие), а в прод ушёл мультиагентный оркестр (~1,20 USD за взаимодействие, до 70x на сложных задачах).</p><blockquote>A loop that runs without an exit condition isn't autonomous. It's a billing event waiting to happen.</blockquote><h2>Пять примитивов, которые ловят большинство отказов</h2><p>Автор оригинального туториала предлагает не монолитный фреймворк, а пять независимых Python-модулей, которые можно встроить в любой проект. Вместе они покрывают три уровня риска: дисциплину до запуска, принудительную остановку во время работы и доказательства после.</p><ol><li><b>Spec writer</b> — заставляет ответить на три вопроса до первого вызова модели.</li><li><b>Circuit breaker</b> — режет цикл, если превышены потолки по ходам или токенам.</li><li><b>Ledger</b> — ведёт append-only журнал каждого хода в SQLite.</li><li><b>Agent loop</b> — связывает три компонента в единый цикл.</li><li><b>Review surface</b> — собирает пятиэлементный фрейм и требует человеческой аттестации перед выдачей результата.</li></ol><h2>Фаза 1. Определить «готово» до первой строчки кода</h2><p>Самая дорогая ошибка в разработке агентов — не выбор модели, а начало кодинга до того, как команда может одним предложением описать условие завершения. «Агент проверит сайт» — не подходит. «Агент обходит целевой URL, извлекает все теги &lt;title&gt; и &lt;meta name="description"&gt;, помечает отсутствующие или слишком длинные и останавливается» — подходит.</p><p>Spec writer интерактивно запрашивает три поля, сохраняет их значения в SQLite и возвращает неизменяемый SpecResult(frozen=True). Полученный session_id связывает спецификацию, строки журнала и итоговый результат в одну трассируемую сессию.</p><p><b>Почему frozen=True:</b><br />Спецификация — это обязательство, а не черновик. frozen=True запрещает переприсваивать поля объекта SpecResult, поэтому код цикла не может «подвинуть» условие завершения посреди запуска.</p><h2>Фаза 2. Принудить «готово» на лету</h2><p>Circuit breaker задаёт два жёстких потолка: turn_limit — максимальное число обращений к модели, и token_limit — суммарное число токенов за всю сессию. Каждый потолок — «строго больше»: если лимит 5 ходов, пятый ещё разрешён, шестой выбросит исключение.</p><p>Ключевое правило: breaker.check() вызывается до запроса к модели, а не после. Постфактум проверка бессмысленна: токены уже сожжены. Исключение, а не код возврата, — чтобы нельзя было промолчать.</p><h3>Как подобрать лимиты для продакшена</h3><p>Демонстрационные значения 5 ходов / 15 000 токенов слишком жёсткие для реальных задач. Для продакшена автор предлагает настроить лимиты под свой бюджет; в туториале приведён пример breaker = CircuitBreaker(turn_limit=10, token_limit=50000). Если одна сессия должна стоить не дороже 1 USD, а средний ход — 0,10 USD, получается порядка 10 ходов. Конкретный token_limit выбирается исходя из прайсинга модели и среднего размера контекста: чем длиннее история диалога, тем раньше сработает потолок.</p><ul><li>Стартуйте с жёсткими лимитами и разрешайте рост только по метрикам, не по интуиции.</li><li>Отдельно лимитируйте retry-политику: каждый повторный запрос увеличивает и turn_count, и объём контекста.</li><li>Не смешивайте лимит токенов с лимитом выходных токенов модели; circuit breaker считает сумму input + output.</li></ul><h2>Фаза 3. Записывать всё, что нельзя подделать</h2><p>Circuit breaker защищает бюджет. Ledger защищает понимание того, что произошло. Это не лог для отладки, а журнал аудита: каждая строка — один ход, append-only, без обновлений и удалений.</p><p>Три решения стоит взять на заметку. Во-первых, вместо исходного текста сохраняется SHA-256 хеш входа: так не утекают персональные данные, а одинаковые входы разных запусков можно сравнивать. Во-вторых, pass_fail хранится как INTEGER (1/0), потому что у SQLite нет булева типа. В-третьих, временная метка — datetime.now(timezone.utc).isoformat(), так как datetime.utcnow() объявлен устаревшим в Python 3.12.</p><h2>Фаза 4. Цикл, который уважает границы</h2><p>Agent loop — единственный компонент, который обращается к языковой модели. Всё остальное работает локально: проверка потолков, запись в журнал, оценка условия выхода.</p><p>Анатомия одного хода простая и строгая: сначала breaker.check(), потом вызов модели, потом ledger.write(), потом проверка stop_reason. Если модель вернула end_turn — возвращаем результат. Если нет — добавляем сообщение continue и идём на следующий круг.</p><p>Этот вариант цикла — минимальный текстовый. Если агент использует инструменты, в Anthropic API stop_reason может быть tool_use: тогда нужно выполнить инструмент, вернуть его результат в messages и только потом решать, продолжать или завершать.</p><p>Системный промпт обязательно включает все три поля спецификации, а не только done_looks_like. Модели нужна негативная область — то, что агент делать не должен (what_it_does_not), — не меньше, чем позитивная: иначе она начнёт «добавлять ценность» за рамками задачи.</p><h2>Фаза 5. Поверхность согласования: цикл бежит к человеку</h2><p>Circuit breaker и ledger решают технические проблемы, но не отвечают на вопрос: «Соответствует ли результат тому, что обещали?» Именно здесь ошибки проходят в прод: вывод выглядит аккуратным, дашборд зелёный, ревьюер ставит галочку.</p><p>Review surface собирает пятиэлементный фрейм из SQLite и требует явной аттестации:</p><ol><li><b>Исходное обещание</b> — три поля спецификации.</li><li><b>Критерий приёмки</b> — поле done_looks_like как явный бенчмарк.</li><li><b>Diff</b> — вход первого хода, выход последнего, число ходов, токены, сработал ли breaker.</li><li><b>Доказательства</b> — все строки ledger за сессию.</li><li><b>Неразрешённые допущения</b> — строки с breach_reason и failed-ходами.</li></ol><p>После согласования ревьюер вызывает attest(). Функция собирает пятиэлементный фрейм в каноническом порядке и считает от него SHA-256 — получается frame_hash. Это аудиторская квитанция: она доказывает, что ревьюер видел именно этот фрейм, а не краткое резюме.</p><h2>Практический пример: SEO-аудит по расписанию</h2><p>Автор приводит пример SEO-аудита. SEO-аудит имеет естественный ритм: обход, выявление проблем, исправление, ожидание переиндексации. Запускать агента 24/7 бессмысленно — он будет сжигать токены в паузах между событиями. Честная архитектура — cron-задача, которая запускает цикл по расписанию.</p><p><b>Пример упрощён:</b><br />В production-варианте стоит проверять URL (допустимые схемы и хосты) и оборачивать requests.get в try/except requests.RequestException, чтобы агент не падал при недоступности сайта.</p><p>Cron-строка выглядит так:</p><p>Агент выполняет работу, записывает ходы в ledger, и если circuit breaker сработал — результат уходит на человеческую проверку, а не в прод.</p><h2>Провайдер-независимость через адаптер</h2><p>Цикл работает с любым клиентом, удовлетворяющим протоколу LLMClient. По умолчанию используется Anthropic, но через адаптер можно подключить OpenAI, Gemini, Ollama, локальные модели или собственный сервер. В репозитории автора показан иллюстративный пример адаптера для OpenAI. Главное — привести ответ к форме, которую ожидает AgentLoop: usage.input_tokens, usage.output_tokens, content[0].text, stop_reason.</p><h2>Выводы: дисциплина дороже модели</h2><p>Большинство аварий с агентными циклами предотвращаются не интеллектом модели, а чёткими границами. Спецификация до запуска, жёсткие потолки ресурсов, неизменяемый аудит и человеческое согласование — это минимальный набор примитивов, который отделяет автономного агента от неконтролируемого биллингового события.</p><p>Для российских команд это означает, что внедрять LLM-агентов без бюджетных предохранителей — всё равно что запускать бесконечный цикл с доступом к корпоративной карте. Начните с пяти модулей, описанных выше, прогоните их на тестовом дубле модели и только после этого открывайте доступ к реальным API.</p><blockquote>Define what done looks like before you start. That's the job, and always has been.</blockquote><p>Полный код и 80 тестов с 100% покрытием доступны в репозитории автора оригинала: <a href="https://github.com/dannwaneri/production-safe-agent-loop">github.com/dannwaneri/production-safe-agent-loop</a>.</p><p><b>Источник:</b> <a href="https://www.freecodecamp.org/news/how-to-build-a-production-safe-agent-loop-from-exit-conditions-to-audit-trails/">How to Build a Production-Safe Agent Loop — From Exit Conditions to Audit Trails</a>, freeCodeCamp.</p>]]></content:encoded>
    </item>
    <item>
      <title>Чистое API на Node.js: практическое руководство</title>
      <link>https://tproger.ru/articles/chistoe-api-na-node-js-prakticheskij-gajd</link>
      <comments>https://tproger.ru/articles/chistoe-api-na-node-js-prakticheskij-gajd?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/chistoe-api-na-node-js-prakticheskij-gajd</guid>
      <description><![CDATA[<p>Как построить поддерживаемое REST API на Node.js: слои, Zod, единые ошибки, версионирование и Swagger. Проверьте свою архитектуру.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/chistoe-api-na-node-js-prakticheskij-gajd">Чистое API на Node.js: практическое руководство</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[TypeScript]]></category>
      <category><![CDATA[Node.js]]></category>
      <category><![CDATA[Фреймворки и библиотеки]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 16 Jun 2026 11:00:21 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если ваше Node.js-приложение начиналось с одного server.js, а через полгода превратилось в лабиринт маршрутов, где бизнес-логика растворилась в обработчиках Express — эта статья для вас. Чистое API проектируется не ради красоты, а чтобы команда могла добавлять конечные точки, не боясь сломать соседние.</p><p>Разберём минимальный, но готовый к продакшену скелет: разделение слоёв, валидацию входных данных, централизованную обработку ошибок, версионирование, ограничение частоты запросов и автоматическую документацию. Все принципы применимы и к Express, и к Fastify, и к NestJS.</p><p>Чистое API — это прежде всего разделение ответственности: роутер знает маршруты, контроллер переводит HTTP в вызовы сервиса, сервис отвечает за бизнес-логику, а схема проверяет входные данные. Такой подход делает код предсказуемым при любом масштабе.</p><p>Чистое API — это, прежде всего, разделение ответственности: роутеры, контроллеры, сервисы и валидация живут в разных слоях.</p><p>Валидация с помощью Zod выполняется на границе — до того, как запрос попадёт в бизнес-логику.</p><p>Централизованный обработчик ошибок — единственное место, где исключения превращаются в HTTP-ответы.</p><p>Стоит закладывать версионирование и документацию OpenAPI с первого дня: позже это обойдётся дороже.</p><p>Fastify и NestJS дают те же архитектурные идеи из коробки, но логика слоёв от этого не меняется.</p><h2>Что мы будем строить</h2><p>Возьмём намеренно простой домен — каталог товаров. Нам важна не бизнес-логика, а структура. К концу у нас будет REST API с единым форматом ответов, валидацией, версионированием по пути /api/v1, ограничением частоты запросов и интерактивной документацией Swagger.</p><h2>Структура проекта</h2><p>Прежде чем писать код, договоримся, где что лежит. Каждая фича — отдельная папка, а не рассыпанный по проекту набор файлов.</p><ul><li>api/v1/ — все маршруты версионированы с первого дня. Добавить v2 позже можно новой папкой, а не рефакторингом.</li><li>products/ — фичевая папка владеет роутером, контроллером, сервисом и схемой.</li><li>middleware/ — сквозная функциональность: защита, логирование, лимиты.</li><li>lib/ — утилиты без привязки к фреймворку.</li></ul><h2>Разделяем ответственность</h2><p>Самая частая ошибка в Express-приложениях — бизнес-логика внутри обработчика маршрута. Там же появляется валидация, работа с базой данных и формирование ответа. При росте проекта такой файл становится опасным для изменений.</p><h3>Роутер знает только «куда идти»</h3><h3>Промежуточный обработчик валидации</h3><p>Промежуточный обработчик validateRequest проверяет body, params и query до попадания в контроллер. Если данные не проходят проверку, ошибка передаётся в централизованный обработчик.</p><h3>Контроллер переводит HTTP в вызовы сервиса</h3><p>Контроллер не знает, где хранятся товары. Его задача — извлечь параметры из запроса, вызвать сервис и вернуть ответ. Всё остальное передаётся в централизованный обработчик ошибок через next(error).</p><h3>Сервис содержит бизнес-логику</h3><p>Сервис не зависит от HTTP. Когда придёт время заменить хранилище в памяти на настоящую базу данных, потребуется поправить только этот файл.</p><h2>Валидация на границе с Zod</h2><p>Любое API, принимающее внешние данные, должно их проверять. Без валидации один некорректный запрос способен превратиться в ошибку времени выполнения, некорректную запись в базе или уязвимость.</p><p>Zod даёт две вещи сразу: проверку во время выполнения и типы TypeScript, выведенные из одной схемы. Промежуточный обработчик validateRequest проверяет body, params и query до того, как запрос попадёт в контроллер. Если данные невалидны, дальше они не идут.</p><h2>Единый обработчик ошибок</h2><p>Разбросанная обработка ошибок — один из главных источников хаоса: где-то возвращается { error: '...' }, где-то { message: '...' }, а где-то случайно отдаётся HTML-страница. Решение — один обработчик, через который проходят все исключения.</p><p>Теперь клиент всегда получает предсказуемую форму ответа, а добавление логирования или отправки ошибок в мониторинг — однострочное изменение в одном месте.</p><h2>Единый формат ответов</h2><p>Успешный ответ всегда выглядит как { success: true, data: ... }, а ошибка — как { success: false, error: { code, message, details } }. Фронтенд или сторонний интегратор знает, чего ожидать от любого эндпоинта.</p><h2>Версионирование API</h2><p>Версионировать API с первого дня стоит недорого. Добавить версию позже — значит ломать существующих клиентов или городить сложную миграцию.</p><p>Новая версия — новая папка src/api/v2/ и новый префикс. Старые клиенты продолжают работать на /api/v1.</p><h2>Ограничение частоты запросов</h2><p>Rate limiting защищает API от случайных и намеренных перегрузок. Настроить его в Express помогает пакет express-rate-limit.</p><p>Глобальный лимит распространяется на все запросы; операции, которые изменяют данные, ограничены жёстче. Ответ тоже соответствует единому формату ошибки.</p><h2>Документация OpenAPI и Swagger</h2><p>API без документации годится только для автора. С помощью swagger-jsdoc и swagger-ui-express можно получить интерактивную документацию прямо из JSDoc-комментариев в роутерах.</p><p><b>Совет:</b><br />Держите описания эндпоинтов в одном файле с маршрутами, а glob в swagger.ts настройте на файлы, доступные во время работы приложения. Лучше генерировать спецификацию на этапе сборки, чем полагаться на исходники TypeScript.</p><h2>Fastify и NestJS: альтернативы Express</h2><p>Всё, что мы разобрали, работает и в Express. Но если вы начинаете проект с нуля, стоит взглянуть на альтернативы.</p><ul><li>Fastify — быстрее Express в бенчмарках (порой в два раза), имеет встроенный логгер Pino и валидацию по схеме. Разделение слоёв остаётся на совести разработчика.</li><li>NestJS — популярен в крупных компаниях: слои модулей, контроллеров и сервисов навязаны архитектурой, что упрощает введение новых разработчиков в проект.</li><li>Express — остаётся лучшим выбором, если вы присоединяетесь к существующему проекту или команда уже знает экосистему.</li></ul><p>Архитектурные принципы — разделение слоёв, единый формат ошибок, валидация на границе — не зависят от фреймворка. Меняется только синтаксис.</p><h2>FAQ</h2><h3>Минимальный набор для старта</h3><p>Для самостоятельного запуска понадобятся базовые зависимости и алиасы путей в tsconfig.json. Объявите @/* на папку src, и примеры заработают без ручных правок импортов.</p><h2>Выводы</h2><blockquote>Чистая структура API — это не переусложнение. Это минимум, при котором бэкенд можно поддерживать нескольким людям.</blockquote><p>Мы собрали минимальный, но масштабируемый каркас: папки по фичам, разделённые слои, валидацию на границе, централизованную обработку ошибок, единый формат ответов, версионирование, лимиты и автоматическую документацию. Ни один из этих шагов сложный сам по себе. Их ценность — в сочетании и в том, чтобы сделать всё это до того, как код разрастётся.</p><p>Если начинаете новый Node.js-проект, не откладывайте структуру «на потом». А в существующем — попробуйте вынести валидацию в схему и собрать ошибки в одном обработчике. Потом всегда дороже.</p><h2>Источники</h2><p>Идеи и примеры в статье основаны на материале Gavin Cettolo «<a href="https://dev.to/gavincettolo/clean-api-design-in-nodejs-a-practical-guide-3a32">Clean API Design in Node.js: A Practical Guide</a>» (dev.to).</p>]]></content:encoded>
    </item>
    <item>
      <title>A2A Java SDK 1.0.0: стабильный релиз для агентных приложений на Java</title>
      <link>https://tproger.ru/news/a2a-java-sdk-1-0-0-stabilnyj-reliz-dlya-agentnyh-prilozhenij-na</link>
      <comments>https://tproger.ru/news/a2a-java-sdk-1-0-0-stabilnyj-reliz-dlya-agentnyh-prilozhenij-na?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/a2a-java-sdk-1-0-0-stabilnyj-reliz-dlya-agentnyh-prilozhenij-na</guid>
      <description><![CDATA[<p>Вышел A2A Java SDK 1.0.0.Final — официальная Java-реализация протокола Agent2Agent. Разбираем ключевые изменения, как подключить SDK из Maven Central и зачем это Java-разработчикам.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/a2a-java-sdk-1-0-0-stabilnyj-reliz-dlya-agentnyh-prilozhenij-na">A2A Java SDK 1.0.0: стабильный релиз для агентных приложений на Java</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Сетевые протоколы]]></category>
      <category><![CDATA[Новости]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 16 Jun 2026 09:45:59 GMT</pubDate>
      <content:encoded><![CDATA[<p>Java-разработчики получили стабильный инструмент для создания агентных систем. <b>A2A Java SDK 1.0.0</b> вышел в релиз и доступен в Maven Central с groupId org.a2aproject.sdk. Для сборки клиента можно взять артефакт a2a-java-sdk-client или импортировать a2a-java-sdk-bom. Библиотека реализует протокол <b>Agent2Agent (A2A)</b> — открытый стандарт, управляемый Linux Foundation, для взаимодействия ИИ-агентов друг с другом.</p><p><b>Agent2Agent</b> — это протокол, управляемый Linux Foundation (изначально представленный Google), который позволяет агентам на разных фреймворках и языках находить друг друга, делегировать задачи и обмениваться результатами. Для Java-экосистемы выпуск SDK версии 1.0.0 означает переход от экспериментальных сборок к инструменту, готовому к промышленной эксплуатации.</p><p>Релиз 1.0.0 появился на прошлой неделе, как сообщает InfoQ в очередном выпуске Java News Roundup. В него вошли исправления ошибок, обновление зависимостей и несколько новых возможностей: интеграционный тестовый набор на базе Quarkus для проверки совместимости разных SDK, а также расширение интерфейса A2AHttpResponse и класса A2AClientHTTPError для доступа к HTTP-заголовкам ответов.</p><ul><li>A2A Java SDK 1.0.0 вышел в GA — первая стабильная версия для Java.</li><li>Реализует протокол Agent2Agent для взаимодействия ИИ-агентов.</li><li>Появился интеграционный тестовый набор на базе Quarkus.</li><li>Доступен в Maven Central: org.a2aproject.sdk.</li><li>Параллельно вышел A2A Jakarta 1.0.0.CR1 для Jakarta EE серверов.</li></ul><h2>Что вошло в релиз A2A Java SDK 1.0.0</h2><ul><li>Новый интеграционный тестовый набор (ITK) на базе Quarkus для проверки кросс-SDK совместимости.</li><li>Возможность получать HTTP-заголовки ответов через интерфейс A2AHttpResponse и класс A2AClientHTTPError.</li><li>Исправления ошибок и обновление зависимостей.</li><li>Готовность к использованию в production вместе с A2A Protocol Specification 1.0.</li></ul><blockquote>I am pleased to announce the release of A2A Java SDK 1.0.0.Final — our first GA release. The A2A Java SDK is the official Java implementation of the Agent2Agent (A2A) Protocol, an open standard that enables AI agents to communicate and collaborate regardless of underlying framework, language, or vendor.</blockquote><p>Параллельно команда выпустила первый релиз-кандидат <b>A2A Jakarta 1.0.0.CR1</b>. Эта интеграция помогает запускать A2A-агентов внутри Jakarta EE серверов, таких как WildFly. В CR1 переименованы пакеты и артефакты, обновлён набор TCK для работы с A2A Java SDK 1.0.0 и настроен запуск CI на Windows.</p><h2>Зачем это Java-разработчикам</h2><p>SDK позволяет строить агентные приложения на Java без привязки к Python-стеку. Агенты могут общаться с агентами на Google ADK, LangGraph, CrewAI и других фреймворках через единый протокол. Это особенно важно для команд, где основная инфраструктура уже написана на Java. Рядом с A2A развивается протокол <a href="https://tproger.ru/news/anthropic-zapustila-mcp-tunneli-i-sendboksy-dlya-korporativnyh-ai">MCP</a>: если MCP соединяет агента с инструментами, то A2A — агента с агентом.</p><p>A2A Java SDK 1.0.0 делает Java полноценной платформой для агентных приложений: теперь можно подключить SDK из Maven Central и начать строить агентов, которые работают в одной экосистеме с Python- и TypeScript-решениями.</p><p><b>Источник:</b> <a href="https://www.infoq.com/news/2026/06/java-news-roundup-jun08-2026/">InfoQ — Java News Roundup: A2A Java SDK 1.0, Jakarta EE 12, JNoSQL, GraalVM, Micrometer, OpenXava, Gradle</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Представляем MDN MCP server</title>
      <link>https://tproger.ru/translations/predstavlyaem-mdn-mcp-server</link>
      <comments>https://tproger.ru/translations/predstavlyaem-mdn-mcp-server?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/predstavlyaem-mdn-mcp-server</guid>
      <description><![CDATA[<p>MDN MCP server переносит актуальную документацию и данные о совместимости браузеров прямо в редактор или AI-агента. Разбираем, как подключить и почему точнее.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/predstavlyaem-mdn-mcp-server">Представляем MDN MCP server</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Браузеры]]></category>
      <category><![CDATA[Mozilla]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 15 Jun 2026 11:30:35 GMT</pubDate>
      <content:encoded><![CDATA[<p>Перевод статьи The MDN Team из MDN Blog, оригинал: <a href="https://developer.mozilla.org/en-US/blog/introducing-mdn-mcp-server/">Introducing the MDN MCP server</a>.</p><p>Мы рады анонсировать выпуск MDN MCP server. MCP (Model Context Protocol) — открытый стандарт, который позволяет ИИ-инструментам подключаться к внешним источникам данных. MDN MCP server использует этот протокол, чтобы перенести документацию MDN и данные о совместимости браузеров прямо в вашего ИИ-агента или IDE.</p><ul><li>MDN MCP server — экспериментальный сервер по протоколу MCP.</li><li>Даёт ИИ-агентам и IDE доступ к актуальной документации MDN и данным о совместимости браузеров.</li><li>Работает с VS Code, Zed, Cursor, Claude Code, Codex CLI, Antigravity CLI и Claude Desktop.</li><li>В тестах с Claude Code Opus 4.7 MDN MCP дал гораздо точнее и надёжнее результаты о поддержке браузеров.</li><li>Ответы с MDN MCP были вдвое быстрее, чем без него.</li></ul><h2>Зачем мы создали MDN MCP</h2><p>Всё больше ИИ-инструментов интегрируется в рабочие процессы веб-разработки, но они могут выдавать устаревшую информацию о веб-платформе из-за обучающих данных и даты знания модели.</p><p>Например, LLM или агент для написания кода может не знать, что существует функция вроде @view-transition CSS at-rule, или не знать, достигла ли она статуса Widely Available в Baseline и безопасна ли для использования во всех браузерах.</p><p>MDN MCP даёт вашему агенту для написания кода доступ к точной и актуальной информации о веб-платформе. Также он упрощает доступ к последней документации, не покидая привычные инструменты.</p><p>Сервер сейчас находится в экспериментальном статусе. Подробности об обработке данных в этой фазе — в нашей <a href="https://developer.mozilla.org/en-US/mcp#privacy_and_data_retention">заметке о приватности</a>.</p><h2>Как использовать MDN MCP</h2><p>MDN MCP server работает с любым MCP-совместимым клиентом, включая:</p><ul><li><b>Редакторы</b>: VS Code, Zed и Cursor.</li><li><b>CLI-агенты</b>: Claude Code, Codex CLI и Antigravity CLI (ранее Gemini CLI).</li><li><b>Чат-приложения</b>: Claude Desktop.</li></ul><p>Ссылки в этом списке ведут к инструкциям по настройке MCP для каждого инструмента. Инструкции по установке и другие детали — на нашей странице <a href="https://developer.mozilla.org/en-US/mcp">MDN MCP server</a>.</p><p>Как быстрый пример, чтобы использовать его с Claude Code, нужно выполнить следующую команду:</p><p>Мы с нетерпением ждём, как вы интегрируете его в свой рабочий процесс веб-разработки и в каких сценариях он окажется наиболее полезен.</p><h2>Какую разницу даёт MCP</h2><p>Учитывая недетерминированную природу LLM и разнообразие доступных моделей, часто сложно сравнивать их поведение с включёнными или выключенными навыками, промптами, инструментами и MCP.</p><p>Мы протестировали Claude Code Opus 4.7 с MDN MCP и без него на нескольких функциях, недавно появившихся в Firefox 150 и 151, спрашивая, как использовать функции и какая у них поддержка браузеров. А именно:</p><ol><li>Как использовать CSS-функцию light-dark() для изображений и какие браузеры её поддерживают?</li><li>Как использовать CSS-псевдокласс :buffering и какие браузеры его поддерживают?</li><li>Как использовать атрибут shadowrootslotassignment на элементе  и какие браузеры его поддерживают?</li><li>Как использовать Web Serial API и какие браузеры его поддерживают?</li></ol><p>Мы заметили определённые закономерности в результатах. В большинстве случаев заметки по использованию от Claude Code с MDN MCP и без него были сопоставимы. Часть ответов, использовавших MCP, была структурирована лучше и полнее. Например, заметки для CSS-функции light-dark() также включали примеры с линейными градиентами, которые не были прямо упомянуты в вопросе, но тоже поддерживаются.</p><p>Когда дело дошло до информации о поддержке браузеров, победитель был очевиден: MDN MCP дал намного точнее и надёжнее результаты. Claude Code без MCP правильно определил поддержку браузеров только в одном случае — для псевдокласса :buffering.</p><p>Например, Claude Code без MCP настаивал, что декларативный атрибут shadowrootslotassignment поддерживается в Chrome 120 и Safari 18.3, возможно, путая его с опцией slotAssignment метода Element.attachShadow(). Но на самом деле Firefox 151 — первый браузер, в котором появилась поддержка этого атрибута.</p><p>Без MCP Claude Code также не дал никакой конкретной информации о поддержке браузеров для использования изображений в функции light-dark(): «поддержка менее однородна, чем вариант с цветом», тогда как с MCP он выдал полную таблицу с указанием Firefox 150 и Chrome (за флагом) как поддерживающих браузеров.</p><p>Худший результат Claude Code без MCP показал на вопросе про Web Serial API. Firefox 151 получил поддержку Web Serial API в мае 2026 года. Однако Claude Code без MCP правильно упомянул браузеры на базе Chromium как поддерживающие эту функцию, но также настаивал, что в Firefox она:</p><blockquote>Не реализовано (и не в планах — см. позицию Mozilla по стандартам: «вредно»).</blockquote><p>С включённым MCP Claude Code правильно определил, что Firefox 151 поставляет поддержку Web Serial API, согласно примечаниям к выпуску.</p><p>Кроме того, мы заметили, что в наших тестах ответы с использованием MDN MCP были вдвое быстрее. Без MCP Claude Code приходилось загружать и парсить немало HTML-страниц, чтобы найти актуальную информацию, что занимало время, но даже тогда не давало точных результатов.</p><h2>Поучаствовать</h2><p>Ваш отзыв помогает нам становиться лучше. Если вы столкнулись с проблемами, есть комментарии или предложения или хотите поделиться, как используете MDN MCP, мы будем рады услышать вас. Заходите в канал platform в нашем Discord. Если заметили проблемы, сообщайте о них в репозиторий <a href="https://github.com/mdn/mcp">mdn/mcp</a> на GitHub.</p><h2>Что дальше</h2><p>По мере того как ИИ-инструменты становятся всё большей частью рабочих процессов веб-разработки, мы стремимся сделать документацию MDN доступной там, где она вам нужна. Этот релиз — один шаг к этой цели, и мы с нетерпением ждём возможности продолжить улучшать опыт с вашей помощью.</p><p>Источник: <a href="https://developer.mozilla.org/en-US/blog/introducing-mdn-mcp-server/">Introducing the MDN MCP server — MDN Blog</a>.</p><p>Попробуйте подключить MDN MCP к своему редактору или агенту и проверьте, насколько точнее станут ответы о веб-платформе.</p>]]></content:encoded>
    </item>
    <item>
      <title>Локализация через Enum, неожиданный Дзен, быстрее только телепатия</title>
      <link>https://tproger.ru/articles/lokalizaciya-cherez-enum-neozhidannyj-dzen-bystree-tolko-telepat</link>
      <comments>https://tproger.ru/articles/lokalizaciya-cherez-enum-neozhidannyj-dzen-bystree-tolko-telepat?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Самир Гёзалов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/lokalizaciya-cherez-enum-neozhidannyj-dzen-bystree-tolko-telepat</guid>
      <description><![CDATA[<p>Надоело плодить JSON/ARB файлы при локализации Flutter-приложения? Автор делился личным опытом и показал, как элегантно настроить локализацию через Enum без внешних зависимостей, генераторов кода и боли в рантайме.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/lokalizaciya-cherez-enum-neozhidannyj-dzen-bystree-tolko-telepat">Локализация через Enum, неожиданный Дзен, быстрее только телепатия</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Массивы и строки]]></category>
      <category><![CDATA[Красивый хак]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[Мобильная разработка]]></category>
      <category><![CDATA[JSON]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Flutter]]></category>
      <category><![CDATA[Dart]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 04 Jun 2026 04:45:17 GMT</pubDate>
      <content:encoded><![CDATA[<p>Решил давеча добавить локализацию в свое приложение на Flutter. Задачка-то простая: пара кнопок, пару десятков переменных. Казалось бы, делов на пять минут. Но Flutter «из коробки» сразу попытался всучить мне какую-то дичь в виде ARB и JSON файлов. Хмм, из прошлого с такими реализациями лишь печаль, так что…</p><h2>Попытка №1. Путь в лоб: Классы и интерфейсы</h2><p>Самый очевидный способ - создать родительский класс с переменными, а языки сделать его наследниками. Но это просто… фиаско. Даже если не писать from/toJson, процесс выглядит так:</p><ol><li>Объявил переменную в родителе.</li><li>Прописал её в конструкторе.</li><li>Повторил то же самое для всех дочерних классов (всех языков).</li></ol><p>Если бы я работал на аутсорсе в Индии и мне платили за количество строк кода - это был бы идеальный вариант. Но я хотел, чтобы одной строки при объявлении было достаточно.</p><h2>Попытка №2. Стандарт (ARB/JSON)</h2><p>Я поплевался, но решил попробовать - «стандарт» всё-таки. Мало ли, может чего поменялось за годы. Вроде всё завелось, но сам процесс… это боль. Бегать по разным файлам, чтобы добавить одну строчку - так себе удовольствие.</p><p>Почему я от него окончательно отказался? Когда данных становится реально много (десятки языков, тысячи строк), ты попадаешь в ловушку: тебе нужно эту махину либо целиком держать в памяти, либо постоянно подгружать и парсить. Ради смены одного слова на кнопке заставлять девайс ворочать тяжелые JSON-ы в рантайме - так себе затея для производительности.</p><h2>Попытка №3. Таблицы и костыли</h2><p>Подумал: «Окей, почему бы не подтянуть старый добрый CSV или вообще закинуть всё в табличку?». И тут официальный пакет локализации сказал: «Извини, мужик, тут наши полномочия всё».</p><p>Ну, я тоже не пальцем деланный. Решил припахать нейросеть, чтобы она написала мне собственный генератор. Флоу получился такой:</p><ol><li>Добавляю строку в таблицу.</li><li>Запускаю генератор.</li><li>Он лепит «родительский» файл.</li><li>После Freezed генерит toJson, fromJson…</li></ol><p>Короче, весело не было. Мало того, я понимал: если языков станет много, мне придется добавлять их все разом и единовременно, иначе в рантайме всё начнет плеваться ошибками. Плюс та же проблема с памятью: таблица - это структура, которую надо парсить и хранить.</p><h2>Красный флаг для программиста</h2><p>Но главная проблема даже не в этом. Необходимость запускать генератор после добавления каждой переменной - это для любого программиста красный флаг.</p><p>Что происходит на практике? Когда ты пишешь код и тебе нужно добавить одну несчастную строку, тебе лень (читать: нехочется выходить из потока творения) запускать весь этот цикл с генерацией. Ты просто её хардкодишь в надежде «потом скопом всё добавлю одним махом». А «потом» наступает тогда, когда уже весь проект завален хардкодом, и вычищать его - то еще удовольствие. Даже нейросетки с такими запросами помогают не с первого раза, и с сомнительной эффективностью.</p><p>Нутром чуял - флоу неправильный. В итоге я пришел к тому, что называю идеальной локализацией.</p><h2>Эволюция лени: почему Enum победил интерфейсы</h2><p>Я начал мучить нейросеть разными вариантами реализации. Для меня в первую очередь был важен флоу работы: мне было тупо лень писать больше одной строки кода, чтобы добавить переменную.</p><p>Моя философия проста: строку захардкодить - моментально. Добавление даже одной строки в другом файле требует доп. действий. НО, если действий минимум, то кодер поймет, что выигрыш во времени сейчас мизерный против больших потерь в будущем, и исправно добавит строку в правильное место. Этого не произойдет, если для добавления строки нужно «отчитаться» в десяти местах.</p><h2>Попытка №4. Рекорды (Records)</h2><p>Присматривался к рекордам. С ними удобно: не нужно писать конструкторы. Но есть подвох: как только ты добавил переменную в один язык, компилятор тут же сходит с ума и требует добавить её во все остальные прямо сейчас. Никакой гибкости и возможности оставить «на потом».</p><h2>Идеальный костыль: Enum</h2><p>В итоге я пришел к самому, казалось бы, «неправильному» способу, который оказался идеальным. Enum. Само название намекает на перечисления и цифры, но оказалось, что хранить в нем буквы и целые фразы - это лучший путь для локализации.</p><p>Знаете, мне моё решение так понравилось, что я пошел к нейросетям и проверил его со всех сторон. Все модели  остались в полном восторге. Под это дело я даже подготовил монументальную «нейро-статью» на полтора часа внимательного чтения, со всеми графиками, бенчмарками и анализом производительности.</p><p>Но потом я заглянул в правила Хабра, прислушался к голосу разума и понял: никто не хочет читать полтора часа сухой статистики. Лучше я просто расскажу вам свою историю «от первого лица», как я докатился до такой жизни. Ну, а если вы совсем уж фанаты цифр - просто скормите этот текст любой нейронке, она вам перескажет всё в лучших академических тонах с графиками на любой вкус.</p><p>А здесь мы будем говорить по делу.</p><p>Ниже я выкатываю сам код. Код тут не для зубрежки, а лишь чтобы указать направление / идею. Самая большая прелесть этой системы в том, что она оставляет гигантское пространство для любого типа реализации. Это архитектурный каркас, который чертовски сложно сломать. Главное — уловить принцип.</p><h2>Реализация</h2><p>Принцип разделения:</p><ul><li>enum Strings → типизированный контракт (что существует).</li><li>translator → источник данных (откуда берётся текст).</li></ul><p>Структура файлов - минимальная. Никаких внешних зависимостей:</p><h2>Ядро - strings.dart</h2><p>Весь контракт локализации в одном enum. Два режима - хардкод switch и серверный кеш - за одним и тем же</p><p>. Даже сообщения об ошибках локализации — сами локализованы:</p><h2>Список языков - languages_enum.dart</h2><p>Каждый язык - самодостаточная единица: знает свой код, название, направление текста и как себя загрузить:</p><p>Хотите грузить с сервера? Одна строка + loader. И</p><p>- тоже одна строка, потому что</p><p>уже является registry:</p><h2>Переводчик - i18n/russian.dart</h2><p>Как это выглядит в жизни (и почему я перестал хардкодить) Я намеренно не привожу здесь код оберток виджетов или конкретных стейт-менеджеров. Всё это - чистая «вкусовщина». Для работы системы нужен лишь элементарный вещатель событий (Notifier), повешенный на метод смены языка.</p><p>Но главное - это мой ежедневный флоу. Сейчас, чтобы добавить строку в UI, я просто вызываю нужный мне ключ: Strings.someKey(). Без контекста, везде.</p><p>А если ключа еще нет? Я тупо иду в Strings и добавляю одну строчку в Enum. Всё.</p><p>Благодаря дефолтному конструктору, приложению абсолютно плевать, что у меня там еще 100 языков не переведены. Оно компилируется и работает здесь и сейчас. А дальше в дело вступают гит-хуки: при комите нейросетка сама подхватывает изменения и заполняет недостающие поля в переводчиках.</p><p>Знаете, какое самое странное чувство? Мне сейчас реально проще и быстрее завести переменную в локализации, чем хардкодить строку в коде. Кажется, это и есть признак здоровой архитектуры - когда делать «правильно» становится физически удобнее, чем делать «быстро» и криво.</p><p>Собственно если в кратце это все о чем я хотел рассказать. Если тема зайдет или кто-то сам не сможет допереть, как прикрутить это к своей архитектуре - пишите в комментариях, разберемся.</p><p>Надеюсь, мой опыт сэкономит вам пару литров нервных клеток. Всех благ и чистого кода без «магических строк»!</p>]]></content:encoded>
    </item>
    <item>
      <title>Claude Opus 4.8: рекордные бенчмарки и дешёвый fast mode</title>
      <link>https://tproger.ru/news/anthropic-vypustila-claude-opus-4-8-s-rekordnymi-benchmarkami-i-d</link>
      <comments>https://tproger.ru/news/anthropic-vypustila-claude-opus-4-8-s-rekordnymi-benchmarkami-i-d?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/anthropic-vypustila-claude-opus-4-8-s-rekordnymi-benchmarkami-i-d</guid>
      <description><![CDATA[<p>Claude Opus 4.8 работает надёжнее в агентных сценариях, честнее оценивает ошибки и предлагает fast mode втрое дешевле. Разбираем ключевые улучшения и цены.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/anthropic-vypustila-claude-opus-4-8-s-rekordnymi-benchmarkami-i-d">Claude Opus 4.8: рекордные бенчмарки и дешёвый fast mode</a>»</p>]]></description>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Новости]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 29 May 2026 06:16:33 GMT</pubDate>
      <content:encoded><![CDATA[<p>Anthropic обновила флагманскую модель <b>Claude Opus</b> до версии 4.8. Новинка работает надёжнее в агентных сценариях, честнее оценивает собственные ошибки и при этом сохраняет прежнюю цену за токены. Для разработчиков главное новшество — режим fast mode стал втрое дешевле.</p><p>Claude Opus 4.8 — это топовая модель семейства Claude, ориентированная на сложные задачи: программирование, юридический анализ, глубокое исследование и многошаговые рабочие процессы. Версия 4.8 пришла на смену 4.7 и доступна уже сегодня через API и веб-интерфейс claude.ai.</p><p>Claude Opus 4.8 вышел 28 мая 2026 года и заменил версию 4.7 по той же цене.</p><p>Fast mode ускоряет работу в 2,5 раза и стоит втрое меньше, чем раньше.</p><p>Модель показывает рекордные результаты на бенчмарках кодирования, юридических задач и компьютерного использования.</p><p>В Claude Code появились динамические рабочие процессы с сотнями параллельных подагентов.</p><p>Opus 4.8 в 4 раза реже пропускает собственные ошибки в коде, чем предшественник.</p><h2>Что улучшилось</h2><p>По словам Anthropic, ключевое изменение — <b>надёжность в агентных задачах</b>. Ранние тестировщики отмечают, что модель задаёт правильные уточняющие вопросы, замечает неточности в планах и не пытается «продавить» заведомо слабое решение. На бенчмарке <b>Super-Agent</b> Opus 4.8 стал единственной моделью, которая завершила все тестовые сценарии от начала до конца, обойдя GPT-5.5 при равной стоимости.</p><p>В программировании прирост заметен на всех уровнях сложности: по данным <b>CursorBench</b>, вызов инструментов стал эффективнее — модель использует меньше шагов для достижения того же результата. На юридическом бенчмарке <b>Legal Agent Benchmark</b> модель впервые преодолела порог в 10% по стандарту all-pass — показатель, который ранее был недостижим для языковых моделей.</p><p>Ещё один важный аспект — <b>честность</b>. Anthropic специально обучает модели избегать необоснованных заявлений, и в 4.8 этот навык заметно усилился: по внутренним оценкам, модель в четыре раза реже пропускает ошибки в собственном коде без комментариев.</p><h2>Новые функции платформы</h2><p>Вместе с моделью Anthropic выпустила несколько обновлений инфраструктуры:</p><ul><li>Dynamic workflows в Claude Code — возможность запускать сотни параллельных подагентов в одной сессии для масштабных задач вроде миграции кодовой базы.</li><li>Effort control в claude.ai — ползунок, который позволяет выбирать между скоростью и глубиной ответа.</li><li>System entries в Messages API — разработчики теперь могут обновлять системные инструкции прямо в массиве сообщений, не прерывая кеш подсказок.</li></ul><h2>Цены и доступность</h2><p>Обычный режим стоит прежние <b>5 долларов за миллион входных токенов</b> и <b>25 долларов за миллион выходных</b>. Fast mode — <b>10 и 50 долларов</b> соответственно, что втрое ниже, чем у предыдущих версий. Модель доступна через Claude API под именем claude-opus-4-8.</p><h2>Выводы</h2><p>Основные улучшения Claude Opus 4.8 сосредоточены вокруг надёжности агентных задач и честности модели. Для разработчиков это означает, что Claude Code станет более самостоятельным инструментом, способным вести масштабные проекты с меньшим контролем со стороны человека. Снижение цен на fast mode делает флагманскую модель более доступной для задач, где важна скорость.</p><p>В ближайшие недели Anthropic планирует выпустить семейство <b>Mythos</b> — модели ещё более высокого интеллектуального уровня, чем Opus. Они уже проходят тестирование в рамках проекта Glasswing, но для массового запуска требуются дополнительные кибербезопасные меры.</p><p>Источник: <a href="https://www.anthropic.com/news/claude-opus-4-8">Anthropic — Introducing Claude Opus 4.8</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Скрытый сбой идемпотентности в финтех-системе: разбор инцидента</title>
      <link>https://tproger.ru/articles/skrytyj-sboj-idempotentnosti-v-finteh-sisteme-razbor-incidenta</link>
      <comments>https://tproger.ru/articles/skrytyj-sboj-idempotentnosti-v-finteh-sisteme-razbor-incidenta?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Дмитрий Москалюк]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/skrytyj-sboj-idempotentnosti-v-finteh-sisteme-razbor-incidenta</guid>
      <description><![CDATA[<p>Разбор реального production-инцидента в финтех-системе: почему ошибка HTTP 500 не остановила операцию создания карты и как сбой идемпотентности в API Gateway вызвал массовые дубликаты. Практический кейс о микросервисной архитектуре, distributed systems, request-id, API idempotency и техническом долге.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/skrytyj-sboj-idempotentnosti-v-finteh-sisteme-razbor-incidenta">Скрытый сбой идемпотентности в финтех-системе: разбор инцидента</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[Микросервисы]]></category>
      <category><![CDATA[Рефакторинг]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Финтех]]></category>
      <category><![CDATA[Фронтенд]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[микро]]></category>
      <category><![CDATA[faq]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 18 May 2026 04:55:17 GMT</pubDate>
      <content:encoded><![CDATA[<h2>Как все началось</h2><p>Всё началось с безобидного, почти рутинного тикета в саппорт:</p><p><i>«У меня тут несколько одинаковых карт создалось. Я вроде один раз нажимал, а их штук пять висит в приложении». </i></p><p>Для финтеха подобная фраза — не мелкая UI-аномалия, а сигнал тревоги высшего уровня. Когда речь идёт о платёжных инструментах, дубль сущности мгновенно переходит из разряда «странностей» в категорию «полноценный инцидент».</p><p>Поначалу казалось, что это просто один случай. Но на самом деле, проблема уже какое-то время была, хоть и скрытно: люди получали дубликаты своих банковских карт, но массово на это никто не жаловался. На уровне первой линии поддержки это ошибочно классифицировали как пользовательские ошибки</p><p>Настоящий шум поднялся не внутри компании, а уже в соцсетях. Один из клиентов выложил пост. Там была фотография посылки, а в ней — примерно сотня одинаковых карт. Пост очень быстро стал популярным, и вот тогда-то и возникли проблемы с репутацией, а команда разработчиков только тогда и узнала о случившемся. И особенно тревожно это звучало на фоне того, что мы считали что таких проблем быть не может - ведь считалось, что у  нас глобальная идемпотентность на все запросы.</p><p>Мы начали разбираться. Стандартный мониторинг показывал норму: дашборды зелёные, в логах тихо, метрики CPU и памяти без отклонений. При этом в базе обнаруживались дубликаты, которых быть не должно. И только тогда, когда мы внимательно посмотрели на коммунальный API Gateway, то поняли что одно изменение от другой команды поменяло идемпотентность работы endpoint-а.</p><p>Проблема была структурно невидима для тех, кто находился ближе всего к ней. Отсутствие видимой проблемы не равно отсутствию риска — система просто ждала подходящего момента.</p><h2>Что произошло: хронология инцидента</h2><p>Архитектура была классической: Клиент → API Gateway → микросервисы,.</p><p>Сценарий развивался почти незаметно для стандартных средств наблюдения:</p><p>1. Фронтенд: Пользователь нажимает кнопку «Выпустить карту».</p><p>2. Gateway: Запрос начинает обрабатываться в API Gateway.</p><p>3. Микросервис по созданию карт: честно выполняет работу: создаёт запись в БД и возвращает `200 OK` в Gateway.</p><p>4. Новый микросервис: API Gateway вызывает новый микросервис и получает HTTP 500 в ответ от него. Исключение возникает уже после успешного вызова нашего микросервиса, и это ключевая точка разрыва: Gateway считает весь запрос неудавшимся, а ответ нашего микросервиса теряется.</p><p>5. Клиент: получает HTTP 500</p><p>6. Реакция: Пользователь видит красную плашку ошибки и логично решает: «Не сработало, пробую снова». Более того, с точки зрения протокола HTTP - запросы, в ответ на которые пришла ошибка HTTP 500, можно пытаться отправлять опять.</p><p>7. Петля: Микросервис, ничего не зная о судьбе предыдущих ответов, послушно создавал карту за картой.</p><p>Круг замкнулся. Эпидемия началась.</p><p>В компании такого уровня это не было предусмотрено. И это такая обидная ошибка.</p><h2>Как так получилось?</h2><p>Вскрылось ошибочное предположение:</p><p><i>«В API Gateway вызов микросервиса создания карт всегда идет последним». </i></p><p>Таким образом идемпотентность достигалась «формально» - ведь если создание карты завершалось с ошибкой - это точно означало что и вызов API Gateway тоже завершится с ошибкой. Сработало ложное чувство безопасности.</p><p>Ответ на вопрос “почему так было сделано?” очень простой - это было осознанное упрощение на старте. Все знали об этом, но задача на фикс потерялась в недрах бэклога на очень долгое время. Это классический пример того, как архитектурное допущение и отложенный рефакторинг годами живут в проде, пока их не вскрывает редкая последовательность отказов.-</p><h2>Что потребовалось изменить</h2><p>Пришлось в срочном порядке внедрять полноценный механизм идемпотентности по request-id, который не зависел бы от порядка вызова downstream-сервисов. И это было достаточно тяжело, потому что окно для легкого внедрения закрывается в первый день продакшена: до этого момента нет ни живых пользователей, ни накопленных данных, ни клиентов старых версий, с которыми нужно сохранять обратную совместимость. Ниже — ответы на вопросы, которые мы получили от коллег, когда разбирали этот инцидент.</p><h2>FAQ: Часто задаваемые вопросы</h2><p><b>1. Почему нельзя просто заблокировать кнопку на фронте?</b></p><p>Блокировка кнопки решает проблему только при стабильной сети. Если запрос ушёл, сервер создал сущность, но ответ потерялся — кнопка разблокируется по таймауту, и пользователь нажмёт снова. Это не устраняет корневую причину, а лишь слегка снижает вероятность дубля.</p><p><b>2. Чем идемпотентность отличается от дедупликации в БД?</b></p><p>Дедупликация через уникальные индексы защищает от дублей в хранилище, но не решает проблему сайд-эффектов: повторный запрос всё равно вызовет отправку SMS, печать банковской карты, генерацию событий в шине или списание средств. Идемпотентность гарантирует, что вся цепочка выполнится ровно один раз — включая все внешние вызовы и побочные действия.</p><p><b>3. Как долго хранить ключи идемпотентности?</b></p><p>На практике мы хранили ключи в основной базе данных без ограничения срока — затраты на хранение UUID по всем сущностям оказались небольшими. В общем случае минимальный срок зависит от конкретных сценариев использования — кому-то хватит и  часа, а кому-то нужна неделя. В любом случае, окна должно быть достаточно, чтобы покрыть сценарии, когда пользователь возвращается к повтору запроса, например, на следующий день или когда клиентское приложение автоматически перезапускает отложенные запросы после восстановления сети. Бессрочное хранение не обязательно, но слишком короткий TTL создаёт риск дублей при длительных сетевых проблемах.</p><p><b>4. Что делать со старыми клиентами, которые не шлют request_id?</b></p><p>Мы сделали несколько версий API для создания карт — под разные версии приложения. Для новых клиентов работала полноценная идемпотентность с клиентским ключом. Для старых версий приходилось принимать риски и генерировать request_id на стороне сервера. Альтернативой может быть хэширование payload запроса, но это менее надежно и сложнее: таймстемпы и случайные поля могут отличаться от вызова к вызову. Поэтому мы выбрали  подход с генерацией ключа на сервере для устаревших клиентов: риски дублей на переходный период оказались меньше, чем сложность поддержки двух схем валидации одновременно.</p><p><b>5. Обязательно ли делать идемпотентность для всех методов API?</b></p><p>Идемпотентность требуется только для методов, которые изменяют состояние системы — POST, PUT, PATCH и иногда DELETE. Методы чтения (GET, HEAD, OPTIONS) не изменяют данные, поэтому считаются идемпотентными по умолчанию.</p><p><b>6. Как понять, что в вашей системе уже есть скрытая проблема с дублями?</b></p><p>Лучший способ — ввести метрики превентивно, не дожидаясь жалоб пользователей. Отслеживайте количество повторных вызовов с одинаковым ключом идемпотентности и сравнивайте его с общим числом запросов. Если метрики уже показывают ненулевое значение — проблема есть, даже если внешне всё работает незаметно.</p><p>Если метрик ещё нет, вот три косвенных признака, которые помогут заподозрить неладное:</p><ul><li>В базе данных периодически появляются записи с одинаковым содержимым, созданные с разницей в несколько секунд.</li><li>Пользователи жалуются на дубликаты карт, заказов или платежей, но вы не можете воспроизвести проблему локально, списываете на то, что пользователи что-то делают не так</li><li>В логах API Gateway периодически всплывают HTTP 500 ошибки, но downstream-сервисы при этом отрабатывают успешно.</li></ul><p>Если заметили хотя бы один из этих симптомов — простого решения уже не будет. Однако остаётся возможность исправить ситуацию до того, как проблему заметят пользователи. В нашем случае дубли проявлялись редко и стали массовыми только при повышении нагрузки. Если отложить решение, скрытая проблема перейдет на уровень, где её последствия станут заметны снаружи и потребуют значительно больших усилий.</p><h2>Итог</h2><p>Главный урок, который мы вынесли: идемпотентность — это общая ответственность всех команд разработки, и поломать её может быть проще, чем кажется. А добавить в уже работающую систему быстро и дёшево — почти невозможно.</p><p>Метрик на всплески повторных запросов у нас не было. А зря — это самый дешёвый способ увидеть проблему до того, как она обрушит продакшен. Системы, спроектированные на 10% нагрузки, ломаются на 60% — и обычно это становится неожиданностью для команды.</p><h2>Практический чек-лист: что проверить в своей системе уже сегодня</h2><ul><li>Убедитесь, что все критические мутирующие эндпоинты поддерживают ключ идемпотентности.</li><li>Настройте алерты на аномальное количество запросов на создание сущностей от одного пользователя за короткий промежуток времени.</li><li>Проверьте, как ваш API Gateway обрабатывает ошибки — не теряет ли он ответы downstream-сервисов.</li><li>Убедитесь, что фронтенд корректно обрабатывает не только 200, но и 500, 502, 504, не провоцируя пользователя на повторные клики без необходимости.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Как построить API-интеграцию оплаты для цифровых ключей и игровых сервисов</title>
      <link>https://tproger.ru/articles/kak-postroit-api-integraciyu-oplaty-dlya-cifrovyh-klyuchej-i-igrovy</link>
      <comments>https://tproger.ru/articles/kak-postroit-api-integraciyu-oplaty-dlya-cifrovyh-klyuchej-i-igrovy?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-postroit-api-integraciyu-oplaty-dlya-cifrovyh-klyuchej-i-igrovy</guid>
      <description><![CDATA[<p>Как построить API-интеграцию оплаты для цифровых ключей и игровых сервисов. Автоматизация платежей, пополнение Steam, выбор API-партнера и масштабирование магазина.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-postroit-api-integraciyu-oplaty-dlya-cifrovyh-klyuchej-i-igrovy">Как построить API-интеграцию оплаты для цифровых ключей и игровых сервисов</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Xbox]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Игра]]></category>
      <category><![CDATA[Epic Games]]></category>
      <category><![CDATA[PlayStation]]></category>
      <category><![CDATA[Discord]]></category>
      <category><![CDATA[Steam]]></category>
      <category><![CDATA[Инфраструктура]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 15 May 2026 04:43:34 GMT</pubDate>
      <content:encoded><![CDATA[<p>Рынок цифровых товаров за последние несколько лет вырос в полноценную инфраструктурную индустрию. Продажа игровых ключей, внутриигровой валюты, подписок и пополнений кошельков давно перестала быть «серой нишей» и превратилась в высококонкурентный сегмент e-commerce с миллионами транзакций ежедневно. Steam, PlayStation, Xbox, Nintendo, Epic Games, Discord Nitro, Game Pass — пользователи привыкли получать цифровой продукт мгновенно, без задержек и ручной обработки.</p><p>Для владельцев маркетплейсов, игровых магазинов и сервисов автоматизация оплаты сегодня становится не преимуществом, а обязательным условием масштабирования. Именно поэтому API-интеграции для цифровых платежей и автоматического пополнения игровых сервисов стали ключевым технологическим инструментом в индустрии.</p><h2>Почему ручная обработка больше не работает</h2><p>Большинство начинающих проектов стартуют одинаково: оператор вручную проверяет оплату, подтверждает заказ и отправляет ключ или проводит пополнение аккаунта. Пока заказов немного — схема кажется рабочей. Но после роста трафика начинаются проблемы:</p><ul><li>задержки обработки;</li><li>ошибки операторов;</li><li>потеря заказов;</li><li>возвраты из-за долгого подтверждения;</li><li>невозможность работать 24/7;</li><li>высокий риск мошенничества.</li></ul><p>В сегменте цифровых товаров пользователь ожидает моментальную выдачу. Если пополнение Steam занимает не секунды, а минуты — конверсия падает. Особенно в периоды распродаж, релизов крупных игр и сезонных акций.</p><p>Именно поэтому современные площадки переходят на автоматизированную архитектуру: платежный шлюз + API поставщика цифровых услуг + система мгновенной обработки заказов.</p><h2>Почему бизнес выбирает GGPay</h2><p>На фоне растущего рынка особое внимание получают сервисы, которые совмещают удобный API, стабильную инфраструктуру и понятную финансовую модель.</p><p>Одним из таких решений сегодня является<a href="https://ggpay.gg/steam?utm_id=928fe578" rel="follow"> GGPAY</a> — сервис для пополнения Steam и других цифровых платформ с поддержкой автоматизированной обработки платежей.</p><p>Платформа ориентирована как на конечных пользователей, так и на владельцев цифровых магазинов, маркетплейсов и игровых сервисов. Среди ключевых преимуществ:</p><ul><li>стабильная работа API;</li><li>автоматическое проведение платежей;</li><li>поддержка популярных способов оплаты;</li><li>низкие комиссии;</li><li>высокая скорость зачисления;</li><li>работа 24/7;</li><li>удобная интеграция для сайтов и Telegram-проектов.</li></ul><p>Для владельцев цифровых площадок особенно важно, что подобные сервисы позволяют быстро запускать автоматизированную продажу без необходимости строить собственную сложную платежную инфраструктуру с нуля.</p><h2>Как устроена API-интеграция цифровых платежей</h2><p>С технической точки зрения система выглядит достаточно просто, хотя внутри скрывается сложная логика маршрутизации и проверки транзакций.</p><p>Типовой процесс выглядит следующим образом:</p><ol><li>Пользователь выбирает цифровой товар или пополнение.</li><li>Сайт формирует заказ.</li><li>Платежный шлюз принимает оплату.</li><li>После подтверждения транзакции сервер обращается к API поставщика.</li><li>API выполняет пополнение или выдает цифровой ключ.</li><li>Клиент получает результат автоматически.</li></ol><p>Подобная модель давно используется в международной игровой индустрии и интегрируется через REST API, callback-уведомления и защищенные webhook-системы.</p><p>Главное преимущество такой схемы — отсутствие ручной обработки. Бизнес получает возможность масштабироваться практически без увеличения штата.</p><h2>Какие задачи решает API для цифровых товаров</h2><p>Современные API-платформы позволяют автоматизировать практически весь цикл продажи:</p><ul><li>пополнение Steam;</li><li>продажу игровых ключей;</li><li>выдачу gift card;</li><li>оплату подписок;</li><li>работу с региональными балансами;</li><li>массовую обработку заказов;</li><li>автоматический возврат;</li><li>мониторинг статусов транзакций;</li><li>защиту от дублирования платежей.</li></ul><p>Для крупных площадок особенно важна возможность работать с несколькими поставщиками одновременно. Это позволяет распределять нагрузку, снижать комиссии и поддерживать стабильность даже во время пикового спроса.</p><h2>На что обращать внимание при выборе API-партнера</h2><p>Ошибка многих проектов — выбор поставщика исключительно по размеру комиссии. На практике стабильность API намного важнее разницы в 1–2%.</p><p>При выборе сервиса необходимо оценивать:</p><h3>1. Скорость обработки</h3><p>Для игровых сервисов критична мгновенная выдача. Пользователь не готов ждать 10–15 минут после оплаты.</p><h3>2. Аптайм инфраструктуры</h3><p>Если API регулярно падает во время крупных распродаж Steam — бизнес теряет деньги и репутацию.</p><h3>3. Наличие webhook и callback-систем</h3><p>Это основа автоматизации статусов платежей.</p><h3>4. Документация</h3><p>Качественная документация сокращает время интеграции в разы.</p><h3>5. Поддержка популярных способов оплаты</h3><p>СБП, банковские карты, криптовалюты, электронные кошельки — современный рынок требует гибкости.</p><h3>6. Защита от мошенничества</h3><p>Антифрод-механизмы и валидация заказов особенно важны в сегменте цифровых товаров.</p><h2>Почему рынок активно переходит на автоматические пополнения Steam</h2><p>Steam остается крупнейшей игровой платформой мира, а пополнение кошелька — одним из самых востребованных цифровых продуктов в СНГ и Восточной Европе.</p><p>После изменений в международной платежной инфраструктуре спрос на альтернативные способы пополнения вырос кратно. На этом фоне появились специализированные сервисы, работающие через API-интеграции и автоматические платежные шлюзы.</p><p>Сегодня пользователи ожидают:</p><ul><li>низкую комиссию;</li><li>мгновенное зачисление;</li><li>стабильную работу;</li><li>поддержку разных регионов;</li><li>прозрачный курс конвертации;</li><li>отсутствие ручных подтверждений.</li></ul><p>Именно поэтому автоматизированные сервисы показывают значительно более высокую конверсию по сравнению с полуавтоматическими решениями.</p><h2>Как выглядит современная архитектура цифрового магазина</h2><p>Профессиональная инфраструктура обычно включает несколько уровней:</p><ul><li>frontend магазина;</li><li>платежный шлюз;</li><li>сервер обработки заказов;</li><li>API-поставщик цифровых товаров;</li><li>систему логирования;</li><li>антифрод-модуль;</li><li>резервные каналы оплаты.</li></ul><p>Дополнительно многие проекты подключают аналитические сервисы, отслеживающие:</p><ul><li>процент успешных транзакций;</li><li>скорость выдачи;</li><li>причины отказов;</li><li>нагрузку по регионам;</li><li>эффективность платежных методов.</li></ul><p>Такой подход позволяет масштабировать платформу практически без ограничений.</p><h2>Какие технологии будут доминировать дальше</h2><p>Рынок цифровых платежей продолжит двигаться в сторону полной автоматизации. Уже сейчас активно развиваются:</p><ul><li>direct top-up через Steam ID;</li><li>мультивалютные API;</li><li>криптовалютные расчеты;</li><li>AI-антифрод;</li><li>распределенные платежные системы;</li><li>автоматические системы маршрутизации транзакций.</li></ul><p>При этом требования пользователей становятся только жестче: скорость, надежность и прозрачность превращаются в стандарт индустрии.</p><h2>Заключение</h2><p>API-интеграция оплаты для цифровых ключей и игровых сервисов — это уже не дополнительная функция, а фундамент современного digital-бизнеса. Автоматизация позволяет масштабировать продажи, снижать издержки, минимизировать ошибки и обеспечивать мгновенную выдачу цифрового товара.</p><p>Именно поэтому проекты, работающие в сегменте игровых пополнений и цифровых товаров, всё чаще выбирают готовые инфраструктурные решения вместо ручной обработки заказов.</p><p>А сервисы вроде GGPAY становятся частью новой экосистемы цифровых платежей, где скорость обработки, стабильность API и удобство пользователя напрямую влияют на рост бизнеса и удержание аудитории.</p><p><i>Реклама. Рекламодатель: ОсОО «НОВАПЭЙ», ИНН:9909710276, erid: 2SDnjf2S7a2</i></p>]]></content:encoded>
    </item>
    <item>
      <title>Что такое REST API и почему ваш — вероятно, не REST</title>
      <link>https://tproger.ru/translations/chto-takoe-rest-api-i-pochemu-vaw-veroyatno-ne-rest</link>
      <comments>https://tproger.ru/translations/chto-takoe-rest-api-i-pochemu-vaw-veroyatno-ne-rest?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/chto-takoe-rest-api-i-pochemu-vaw-veroyatno-ne-rest</guid>
      <description><![CDATA[<p>6 ограничений Филдинга и почему большинство JSON API соответствуют лишь 2–3 из них. Проверьте, сколько из них выполняет ваш API — с примерами кода.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/chto-takoe-rest-api-i-pochemu-vaw-veroyatno-ne-rest">Что такое REST API и почему ваш — вероятно, не REST</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Лучшая практика]]></category>
      <category><![CDATA[Паттерны проектирования]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 14 May 2026 14:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Большинство разработчиков хотя бы раз строили «REST API». Мало кто читал диссертацию, которая его определяет. Этот разрыв между популярным пониманием и оригинальной спецификацией порождает повторяющиеся архитектурные проблемы и нестабильность API.</p><p>REST API — это веб-сервис, удовлетворяющий шести архитектурным ограничениям, выведенным Роем Филдингом в докторской диссертации «Architectural Styles and the Design of Network-based Software Architectures» (UC Irvine, 2000 год). Начав с «нулевого стиля» — пустого набора без ограничений — Филдинг добавлял каждое из них последовательно, анализируя порождаемые ими свойства распределённых гипермедиа-систем (систем, где переходы между состояниями описаны прямо в ответах сервера). Результат получил название «Передача репрезентативного состояния» (Representational State Transfer).</p><p>Индустрия взяла название и проигнорировала большинство ограничений. «REST» теперь означает «любой API, который отправляет JSON по HTTP». Если вы строите публичный API или API для команд за пределами вашей организации — пропущенные ограничения начинают стоить денег.</p><p>REST — это шесть архитектурных ограничений, сформулированных Роем Филдингом в 2000 году, а не «любой JSON-over-HTTP API».</p><p>Большинство API выполняют лишь 2–3 ограничения из шести: клиент-сервер, stateless и частично слоистую систему.</p><p>Самое игнорируемое ограничение — HATEOAS: сервер передаёт клиенту список доступных действий прямо в ответе.</p><p>HATEOAS решает три дорогостоящие проблемы: пагинацию, версионирование API и обнаруживаемость ресурсов.</p><p>Для небольшой команды с одним потребителем пропуск HATEOAS оправдан. Для публичного API — нет.</p><h2>Шесть ограничений REST API: разбор по порядку</h2><h3>Ограничение 1: Клиент-сервер</h3><p>Клиент и сервер имеют разные зоны ответственности. Клиент отвечает за интерфейс, сервер — за данные и логику. Большинство API справляются с этим по умолчанию. Нарушение появляется, когда сервер начинает диктовать, как клиент должен <i>отображать</i> информацию.</p><p>Например, если API возвращает displayOrder: 3 и buttonColor: "#ff0000" для какого-либо действия — это нарушение. Порядок отображения должен следовать из позиции элементов в ответе. Цвет должен определяться семантическим свойством вроде class: ["danger"], которое каждый клиент интерпретирует самостоятельно.</p><h3>Ограничение 2: Stateless (без состояния)</h3><p>Каждый запрос содержит всю информацию, необходимую серверу для его обработки. Сервер не хранит состояние сессии между вызовами.</p><p>Если вы отправляете GET /path-1 с сессионной cookie, и сервер ищет её в памяти, чтобы получить ваш ID пользователя — это серверное состояние. Stateless-версия включает ID прямо в запрос: JWT или тело POST-запроса переносят его вместе с запросом и могут вернуть в ответе для повторного использования клиентом.</p><h3>Ограничение 3: Кэшируемость</h3><p>Ответы должны быть явно или неявно помечены как кэшируемые или некэшируемые. Клиент или промежуточный узел может повторно использовать закэшированные ответы, не обращаясь к серверу. Филдинг рассматривал кэшируемость как архитектурную задачу первого класса, повышающую эффективность и воспринимаемую производительность за счёт снижения средней задержки.</p><p>Большинство JSON API полностью игнорируют кэширование. Вы отправляете GET /articles/42, а в ответе нет ни Cache-Control, ни ETag, ни Last-Modified. Клиент обращается к серверу каждый раз, даже если статья не менялась неделями.</p><h3>Ограничение 4: Единый интерфейс (Uniform Interface)</h3><p>Это главное ограничение. Филдинг разбил его на четыре подограничения — три описываются ниже, четвёртое (HATEOAS) вынесено в отдельный раздел из-за его значимости.</p><p><b>4.1 URI идентифицируют ресурсы.</b> Единообразие здесь — это сама спецификация URI: схема, authority, путь, запрос, фрагмент. Ограничение ничего не говорит о структуре сегмента пути: /articles/42, /x?id=42 и /a/b/c — всё это валидные URI. «Используйте чистые URL-пути» — популярное соглашение и хороший SEO-инструмент, но не то, что требует Филдинг.</p><p><b>4.2 Управление ресурсами через представления.</b> Вы выполняете GET в /whatever, чтобы получить представление ресурса. Заголовок Content-Type сообщает серверу формат тела запроса. Заголовок Accept сообщает, какие медиатипы (форматы обмена данными) поддерживает клиент для ответа.</p><p><b>4.3 Самоописывающие сообщения.</b> Ответ с Content-Type: application/vnd.collection+json сообщает клиенту, как разбирать тело, без каких-либо предположений.</p><h3>Ограничение 4.4: HATEOAS — то, что пропускают почти все</h3><p>HATEOAS (Hypermedia As The Engine Of Application State) — четвёртое подограничение Uniform Interface. С первыми тремя большинство API справляются. HATEOAS — место, где останавливается почти каждый.</p><p>Разница хорошо видна на примере API для списка чтения. Без HATEOAS вы получаете просто данные, похожие на запись в базе:</p><p>Клиент ничего не знает о том, что он может сделать дальше. Чтобы отметить статью как прочитанную, клиент уже должен знать endpoint: PATCH /articles/42 с {"status": "read"}. Разработчик захардкодил эти знания, прочитав документацию. Сам API их не сообщил.</p><p>С HATEOAS сервер сообщает клиенту о доступных действиях в стандартизированном виде. Вот тот же ответ с использованием <a href="https://github.com/kevinswiber/siren">Siren</a> — одного из стандартизированных медиатипов для гипермедиа-API:</p><p>Клиент не хардкодит URL и HTTP-методы. Массив actions сообщает, что можно сделать. Навигация приходит из links. Если статья уже прочитана — сервер исключает действие mark-as-read из ответа. Кнопка исчезает в UI. Без единого условного выражения в клиентском коде.</p><p>Сервер добавляет новое действие — и каждый клиент подхватывает его при следующем запросе, без деплоя. Это принципиальное отличие: сервер управляет доступными переходами состояния.</p><h3>Ограничение 5: Слоистая система</h3><p>Клиент не может определить, общается ли он с конечным сервером или с промежуточным узлом. Балансировщики нагрузки, CDN и API-шлюзы должны быть прозрачны для вызывающей стороны. Большинство API выполняют это ограничение автоматически. Самый распространённый вид нарушения — когда сообщения об ошибках раскрывают имя хоста бэкенд-сервиса, тем самым нарушая прозрачность слоёв.</p><h3>Ограничение 6: Код по требованию (необязательное)</h3><p>Сервер может передавать исполняемый код клиенту. Думайте о JavaScript, подключаемом через тег &lt;script&gt; на веб-странице. Для API это ограничение почти не применимо. Филдинг сделал его единственным необязательным.</p><h2>Что HATEOAS решает на практике</h2><p>Филдинг разработал HATEOAS для решения тех самых проблем, с которыми API-команды сейчас борются вручную, многократно и каждый раз по-разному.</p><h3>Пагинация</h3><p>Без HATEOAS каждый API изобретает собственную схему. Один использует page и pageSize. Другой — offset и limit. Третий — токены на основе курсора. С HATEOAS сервер включает ссылку с отношением «следующая страница». Клиент следует этому отношению. Схема пагинации может измениться, не сломав ни одного клиента: клиент не знал деталей схемы и не знает формата URL.</p><h3>Версионирование</h3><p>Без HATEOAS команды версионируют API через URL-пути (/v1/, /v2/) или кастомные заголовки вроде X-API-Version. Поддержка нескольких версий занимает месяцы, клиенты привязываются к версии и ломаются при её выводе из эксплуатации. С HATEOAS сервер вводит новые действия, добавляя ссылки. Старые ссылки продолжают работать.</p><h3>Обнаруживаемость</h3><p>Без HATEOAS первый шаг разработчика — чтение Swagger-документации, второй — хардкодинг каждого endpoint в клиент. С HATEOAS корень API возвращает ссылки на все доступные ресурсы. Клиент исследует API так же, как браузер исследует веб-сайт.</p><h2>Сколько ограничений выполняет ваш API</h2><p>Итого шесть ограничений. Большинство API удовлетворяют двум-трём: клиент-сервер, слоистую систему и частичную безгосударственность. Большинство нарушают кэшируемость по умолчанию. Большинство полностью игнорируют HATEOAS.</p><ul><li><b>Клиент-сервер</b> — разделение ответственности за интерфейс и данные</li><li><b>Stateless</b> — каждый запрос самодостаточен, без серверных сессий</li><li><b>Кэшируемость</b> — явные заголовки Cache-Control, ETag, Last-Modified</li><li><b>Единый интерфейс</b> — URI, представления, самоописывающие сообщения и HATEOAS</li><li><b>Слоистая система</b> — прозрачность промежуточных узлов</li><li><b>Код по требованию</b> — опционально, для API почти не применимо</li></ul><p>Это не оценка. Это карта компромиссов, которые вы приняли — намеренно или случайно. Для небольшой команды с одним потребителем и Slack-каналом для координации пропуск HATEOAS оправдан. Публичный API с сотнями потребителей платит за каждый пропущенный раунд миграции версий. Подробнее об эволюции REST-архитектуры — в <a href="https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm">главе 5 диссертации Филдинга</a>.</p><h2>Выводы</h2><blockquote>Я разочарован тем, что многие не знакомы с 15-летними исследованиями в области гипермедиа, которые стоят за REST. Большинство так называемых REST API — это просто удалённые вызовы процедур через HTTP.</blockquote><p>Пройдитесь по шести ограничениям и посчитайте, сколько из них выполняет ваш API. Это даст не оценку, а карту принятых компромиссов — осознанных или случайных. Упражнение отвечает на один вопрос: ваш API — это Representational State Transfer или просто HTTP-транспорт, закрытый для расширения?</p><p>Оригинальная статья: <a href="https://fagnerbrack.com/what-is-a-rest-api-and-why-yours-probably-isnt-one-7e5fb65ece4d">Fagner Brack — What Is a REST API, and Why Yours Probably Isn't One</a>. Первоисточник: <a href="https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm">Глава 5 диссертации Роя Филдинга, UC Irvine</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как подключить общую память к Claude Code и Cursor за 5 минут</title>
      <link>https://tproger.ru/articles/kak-podklyuchit-obshhuyu-pamyat-k-claude-code-i-cursor-za-5-minut</link>
      <comments>https://tproger.ru/articles/kak-podklyuchit-obshhuyu-pamyat-k-claude-code-i-cursor-za-5-minut?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[C0Ally]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-podklyuchit-obshhuyu-pamyat-k-claude-code-i-cursor-za-5-minut</guid>
      <description><![CDATA[<p>Как подключить общую память к Claude Code и Cursor за 5 минут, общая shared память для ИИ-агентов. Общий контекст и экономия ресурсов. CoAlly</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-podklyuchit-obshhuyu-pamyat-k-claude-code-i-cursor-za-5-minut">Как подключить общую память к Claude Code и Cursor за 5 минут</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Рефакторинг]]></category>
      <category><![CDATA[Slack]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[Навыки]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 09 May 2026 07:40:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Работаю с Claude Code и Cursor параллельно. Claude Code хорош для архитектурных задач и рефакторинга, Cursor - для быстрого редактирования и code review. Проблема одна: они друг про друга ничего не знают. И даже при выполнении задач в одной среде разработки через пару дней уже и не вспомнишь что решил, почему, приходится опять просить агента изучить контекст и разобраться чтобы получить нужную информацию. Это время и токены.</p><p>Сделал себе инструмент, который это решает. Потом оформил в продукт. Называется <b>CoAlly</b> - сервер, который дает агентам общую память.</p><h2>Что он делает</h2><p>Агент автоматически сохраняет контекст работы: какие решения принял, какие файлы затронул, почему сделал так, а не иначе. Когда другой агент (или тот же, но в новой сессии) берется за связанную задачу, он находит этот контекст через семантический поиск.</p><p>Запрос "проблемы с авторизацией" найдет запись про "token refresh rotation", хотя слова совершенно разные. Работает через эмбеддинги и косинусное расстояние, скоро выйдет фича с анализом смысловой корреляции при поиске.</p><h2>Подключение</h2><h2>Шаг 1: регистрация</h2><p>Заходим на <a href="https://coally.cortexally.ai">coally.cortexally.ai</a>, создаем аккаунт. Получаем API ключ.</p><h2>Шаг 2: подключение к агенту (Claude, Cursor и др.)</h2><p>Одна команда в терминале:</p><p>claude mcp add coally-nexus --transport sse https://coally.cortexally.ai/sse --header "Authorization: Bearer ВАШ_КЛЮЧ"</p><p>Перезапускаем Claude Code. В списке MCP-инструментов должен появиться coally-nexus.</p><p><b>Cursor, Windsurf, VSCode</b></p><p>Заходим в настройки Cursor -&gt; Settings -&gt; MCP -&gt; Settings (значок шестеренки) или создаем/редактируем файл `.cursor/mcp.json` в корне проекта (или в домашней директории для глобального подключения):</p><p>Файл `~/.codeium/windsurf/mcp_config.json` для Windsurf или соответствующее меню для VSCode и других его форков.</p><p>Перезапускаем IDE|Agent. Готово.</p><h2>Первая сессия</h2><p>После подключения агент при первом взаимодействии проиндексирует проект автоматически. Если нет - попросите: "<i>проиндексируй этот проект через CoAlly</i>".</p><p>Что происходит при индексации: сканируется дерево проекта, находятся конфиги, важные воспоминания, memorybanks и др., все это эмбеддится и сохраняется как контекст.</p><p>Дальше агент сам начнет сохранять контекст работы после значимых изменений. Если нужно явно сохранить что-то: "<i>сохрани контекст этой задачи в CoAlly</i>".</p><h2>Что получаем</h2><p>На вопрос "<i>что вчера делали по задаче авторизации? какой статус бага с токеном и сколько времени потребуется на доработку</i>" Агент достает из <b>CoAlly</b> записи: "<i>вчера в Cursor поправили ротацию токенов, причина была в TTL, затронули два файла. Могу сразу продолжить и на основе коммитов ... исправить точечно флоу, время на исправление — N минут.</i>"</p><p>Если работаете в команде - еще полезнее. Контекст коллеги тоже доступен. Его экспертиза и навыки также постепенно приобретают цифровую версию. Не нужно ждать стендап или писать в Slack.</p><p><b>Ограничения</b></p><p>Агенты иногда игнорируют инструкции и не сохраняют контекст. Бывает. Можно просить явно.</p><p>Семантический поиск хорош, но не идеален. Если запрос слишком общий ("что нового?"), результаты будут размытыми. Конкретные вопросы работают лучше.</p><p>Бесплатный тариф - 2 проекта. Для личного использования хватает. Для команд - тарифы Team и Enterprise.</p>]]></content:encoded>
    </item>
    <item>
      <title>Addy Osmani зашил сениор-инженерную дисциплину в скиллы для AI-агентов</title>
      <link>https://tproger.ru/news/addy-osmani-zawil-senior-inzhenernuyu-disciplinu-v-skilly-dlya-ai-a</link>
      <comments>https://tproger.ru/news/addy-osmani-zawil-senior-inzhenernuyu-disciplinu-v-skilly-dlya-ai-a?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/addy-osmani-zawil-senior-inzhenernuyu-disciplinu-v-skilly-dlya-ai-a</guid>
      <description><![CDATA[<p>Addy Osmani выложил 20 markdown-навыков, которые заставляют AI-агента писать спеки, тесты, ревью и не пропускать сениорские шаги. Разбираем пять принципов.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/addy-osmani-zawil-senior-inzhenernuyu-disciplinu-v-skilly-dlya-ai-a">Addy Osmani зашил сениор-инженерную дисциплину в скиллы для AI-агентов</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Нейронные сети]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Markdown]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 06 May 2026 09:30:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>AI-агент пишет фичу за минуту, а спецификация, тесты и ревью где-то теряются. Addy Osmani — бывший Engineering Lead Chrome Developer Experience в Google, сейчас Director в Google Cloud AI — собрал на GitHub репозиторий из 20 «навыков», которые заставляют агента не пропускать сениорские этапы работы. К моменту разбора в блоге репозиторий собрал 27 тысяч звёзд, к моменту этой публикации — уже больше 29 тысяч.</p><p>Скилл — это markdown-файл со специальной шапкой (frontmatter — служебный блок с метаданными в начале файла), который Claude Code или Anthropic Agent SDK подгружают в контекст агента по триггеру. Не справочник, а пошаговый workflow с чекпоинтами и критерием выхода: написать падающий тест, запустить, увидеть, что он падает, написать минимальный код, увидеть, что тест прошёл.</p><p>Поведение по умолчанию у любого AI-агента — кратчайший путь к «готово». Просишь функцию — он пишет функцию. Не задаёт вопросов про спеку, не пишет тест перед реализацией, не думает про границы доверия и не смотрит, как diff будет выглядеть в ревью. Скиллы прибивают сениорский каркас обратно.</p><ul><li>Addy Osmani опубликовал на GitHub набор из 20 скиллов для AI-агентов — markdown-файлов, в которых процесс встроен прямо в инструкции.</li><li>За несколько недель проект собрал 27 000 звёзд и устанавливается в Claude Code одной командой.</li><li>Скиллы покрывают шесть этапов цикла разработки: определение, планирование, сборка, верификация, ревью и выкат, плюс сквозной режим упрощения кода.</li><li>Главные принципы дизайна: процесс важнее текста, антирационализационные таблицы, обязательная верификация, прогрессивное раскрытие, дисциплина по объёму.</li><li>Формат переносится: те же markdown-файлы работают в Claude Code, Cursor, Gemini CLI, Codex, Aider, OpenCode.</li></ul><h2>Что внутри: 20 скиллов на шесть этапов разработки</h2><p>Двадцать скиллов организованы вокруг шести фаз жизненного цикла, поверх которых сидят семь slash-команд. Это та же модель, по которой работают здоровые инженерные команды, просто с другой лексикой.</p><ul><li>Define — /spec: что именно мы строим.</li><li>Plan — /plan: разбиение работы на куски.</li><li>Build — /build: реализация вертикальными слайсами.</li><li>Verify — /test: доказательство, что работает.</li><li>Review — /review: что ускользнуло от автора.</li><li>Ship — /ship: безопасный выкат.</li><li>Cross-cutting — /code-simplify: упрощение в любой фазе.</li></ul><p>Большая фича может активировать одиннадцать скиллов подряд, мелкий багфикс — три. Решает мета-роутер с именем using-agent-skills: он смотрит на запрос и подгружает только релевантные.</p><h2>Пять принципов, на которых всё держится</h2><h3>1. Процесс важнее текста</h3><p>Скилл — это последовательность шагов, а не эссе. Если положить в контекст агента двухтысячный текст «о лучших практиках тестирования», агент прочитает, сгенерирует правдоподобный ответ и тестов не напишет. Если положить workflow (пиши падающий тест → запусти → убедись, что упал → пиши код → убедись, что прошёл → рефактори), у агента есть, что делать, а у тебя — что проверять.</p><p>Это правило одинаково работает и для людей: справочник на 200 страниц никто не открывает в дедлайн, маленький workflow с чекпоинтами выполняется.</p><h3>2. Антирационализационные таблицы</h3><p>В каждом скилле есть таблица «оправданий» с заранее написанными контраргументами. Примеры:</p><ul><li>«Эта задача слишком простая для спеки» → критерии приёмки всё равно нужны. Пять строк подойдёт; ноль строк нет.</li><li>«Тесты напишу позже» → «позже» — это слово-обманка. Никакого «позже» не будет: пиши падающий тест сейчас.</li><li>«Тесты прошли — мержим» → проходящий тест — это улика, а не доказательство. Запусти приложение, проверь поведение, дай человеку посмотреть diff.</li></ul><p>LLM хорошо умеет в правдоподобную аргументацию: «именно эта задача спеки не требует, именно этот merge безопасный без ревью». Антирационализационная таблица — это заранее заготовленные ответы на отговорки, которые агент пока ещё даже не придумал. Тот же приём отлично работает в человеческих командах.</p><h3>3. Верификация — не опция</h3><p>Каждый скилл заканчивается конкретной уликой: тесты прошли, билд чистый, трейс рантайма показывает ожидаемое поведение, ревьюер подписался. «Кажется, ОК» — недостаточно никогда. Агент-генератор всегда скажет, что всё хорошо, поэтому нужен отдельный сигнал, что работа действительно сделана.</p><h3>4. Прогрессивное раскрытие</h3><p>Все 20 скиллов в контекст не загружаются. На старте сессии активен только маленький мета-навык using-agent-skills, который выбирает релевантный скилл под текущую задачу. Каждый лишний токен в контексте где-то уменьшает качество, поэтому подгружать нужно только то, что реально применимо.</p><h3>5. Дисциплина по объёму</h3><p>Мета-скилл фиксирует жёсткое правило: трогай только то, о чём попросили. Не рефактори соседние модули. Не сноси код, который не понимаешь до конца. Это самый частый параметр, по которому пулреквест агента становится немёрджибельным: где-то по пути он решил «заодно отрефакторить».</p><h2>ДНК Google в каждом скилле</h2><p>Скиллы насыщены практиками из книги <b>Software Engineering at Google</b> и публичной инженерной культуры. Это сделано осознанно: большая часть того, что заставляет работать большой код, задокументирована — и именно это агент пропускает первым делом.</p><ul><li>api-and-interface-design — закон Хайрама: любое наблюдаемое поведение API кто-то рано или поздно начнёт использовать.</li><li>test-driven-development — пирамида ~80/15/5 (unit / integration / e2e) и правило Бейонсе: «если функционал тебе нравится — обязательно прикрой его тестом». DAMP важнее DRY в тестах: тест должен читаться как спецификация, даже ценой дублирования.</li><li>code-review-and-quality — пулреквесты по 100 строк и метки Critical / Nit / Optional / FYI. Большие PR не ревьюят, их штампуют.</li><li>code-simplification — забор Честертона: не сноси, пока не понял, зачем поставили. Удалённый код имеет привычку возвращаться багом.</li><li>git-workflow-and-versioning — trunk-based development и атомарные коммиты.</li><li>ci-cd-and-automation — shift-left и feature-флаги: лови проблемы как можно раньше, выкат и релиз — разные операции.</li><li>deprecation-and-migration — код как обязательство: каждая строка живёт ровно столько, сколько её обслуживают.</li></ul><p>Любая модель видела в обучении словосочетание «закон Хайрама», но не применяет его, проектируя API в три часа ночи. Скиллы — способ сделать так, чтобы применяла.</p><h2>Три режима использования</h2><p><b>Режим 1: установка плагином в Claude Code.</b></p><p>Получаешь все slash-команды, скиллы активируются автоматически по контексту.</p><p><b>Режим 2: ручной импорт markdown в свой инструмент.</b> Скиллы — это plain-markdown, переносится куда угодно. В Cursor — в .cursor/rules/. Gemini CLI, Codex, Aider, Windsurf, OpenCode — у каждого свой путь, но workflow одинаковый.</p><p><b>Режим 3: ничего не устанавливать, читать как спеку.</b> Открыть <i>code-review-and-quality.md</i> и применить пятиосевую шкалу серьёзности замечаний (Critical / Nit / Optional / FYI плюс blocking-комментарий) к ревью своей команды. Открыть <i>test-driven-development.md</i> и закрыть следующий спор «нужно ли писать тест первым». Открыть мета-навык и взять оттуда пять non-negotiables в свой AGENTS.md.</p><h2>Выводы</h2><p>Главная идея проекта не в самих скиллах, а в подходе. AI-агент — это крайне способный джуниор без инстинкта на ту часть работы, которая не попадает в diff. Сениор-инженерные шаги — спека, размер изменений, оставленные доказательства, отказ мержить непрослеживаемое — именно то, что агент пропустит, если пропуск возможен в принципе.</p><blockquote>Задача всё чаще сводится к тому, чтобы закодировать эту дисциплину так, чтобы агент не мог уговорить себя её обойти.</blockquote><p>Репозиторий лежит на <a href="https://github.com/addyosmani/agent-skills" rel="noopener">github.com/addyosmani/agent-skills</a> под лицензией MIT, разбор подхода <a href="https://addyosmani.com/blog/agent-skills/" rel="noopener">опубликован в блоге</a> Addy Osmani. Те же markdown-файлы можно прочитать как описание того, как должна выглядеть инженерия с AI-агентами — и забрать оттуда пять non-negotiables в свой AGENTS.md без установки чего-либо.</p><p>Берите одну фазу — спеку, ревью или верификацию — и закрепляйте её в правилах своего агента. Дальше расширяйте по мере того, какие шаги команда чаще всего пропускает.</p>]]></content:encoded>
    </item>
    <item>
      <title>Сэкономили на CMS при запуске магазина — а через полгода заплатили втройне за переезд</title>
      <link>https://tproger.ru/articles/sekonomili-na-cms-pri-zapuske-magazina-a-cherez-polgoda-zaplati</link>
      <comments>https://tproger.ru/articles/sekonomili-na-cms-pri-zapuske-magazina-a-cherez-polgoda-zaplati?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Pavel Pat]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/sekonomili-na-cms-pri-zapuske-magazina-a-cherez-polgoda-zaplati</guid>
      <description><![CDATA[<p>Зачем CMS для магазина — это не «витрина», а контур продаж: каталог, 1С, промо, масштаб. Разбор Битрикса, WooCommerce, облака и самописа, плюс честно про миграцию и ошибки на старте.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/sekonomili-na-cms-pri-zapuske-magazina-a-cherez-polgoda-zaplati">Сэкономили на CMS при запуске магазина — а через полгода заплатили втройне за переезд</a>»</p>]]></description>
      <category><![CDATA[Интернет]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[SEO]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Быстрый старт]]></category>
      <category><![CDATA[PHP]]></category>
      <category><![CDATA[DevOps]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[WordPress]]></category>
      <category><![CDATA[Magento]]></category>
      <category><![CDATA[OpenCart]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Маркетинг]]></category>
      <category><![CDATA[Игра]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Дизайн]]></category>
      <category><![CDATA[CMS]]></category>
      <category><![CDATA[Бизнес]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 06 May 2026 08:20:34 GMT</pubDate>
      <content:encoded><![CDATA[<p>Мне часто приносят историю в таком виде: «Сделали сайт дёшево, всё летало на старте». Потом каталог раздувается до десятков тысяч SKU, поиск начинает подвисать, 1С не дружит с админкой — и вместо продаж получается проект спасения.</p><p>Один такой кейс я помню особенно болезненно. Заказчик специально ушёл от «тяжёлых» платформ ради самописного решения: быстрее сроки, ниже чек на входе. Полгода спустя каталог перевалил за 10 000 позиций. Страницы открывались по 8–12 секунд, поиск фактически умер, обмен с учёткой превратился в ручной ад. В итоге пришлось пересобирать магазин на другой системе — и суммарно это стоило примерно в три раза больше, чем если бы выбрать нормальный фундамент сразу.</p><p>Вывод простой и непопулярный: для интернет-магазина CMS — это не «движок сайта», а контур бизнеса. Если он не тянет каталог, склады, оплаты и промо — экономия на старте превращается в налог на переделку.</p><h2>Почему «красивая витрина» не спасает</h2><p>Товар и дизайн важны. Но когда речь про оборот, в игру входят другие вещи: скорость выдачи каталога под нагрузкой, связка с 1С или CRM, гибкость скидок, безопасность оплат, возможность масштабировать без ручного копания в ядре.</p><p>Я бы проверял любую платформу не по «можно ли сделать красиво», а по чек-листу: большой каталог без комы в выдаче, интеграции без лютого кастома, промо-логика без боли, понятный путь от заказа до оплаты. Всё остальное — уже вторичный дизайн.</p><h2>Где Битрикс реально оправдан</h2><p>На корпоративных и сетевых историях Битрикс заходит потому, что это не «лендинг с корзиной», а связка магазина с процессами: каталог, заказы, складские и клиентские сценарии из коробки, обмен с 1С как отдельная экосистема.</p><p>Был у нас запуск для стройсети: 80 000 товаров, несколько складов, отдельная математика скидок для B2B. На чистом PHP такое можно дописать, но это месяцы и жирный бюджет. На готовом контуре мы вышли в прод заметно быстрее — потому что решали задачу бизнеса, а не изобретали велосипед.</p><p>Цена лицензии и сервера — да, это не «бесплатный WordPress». Зато это честная модель: вы платите за то, что масштаб и интеграции уже заложены в архитектуру, а не пробиты латками.</p><h2>Kогда разумнее WooCommerce и облако</h2><p>Если у вас не миллион SKU и не десять складов, а тысяча позиций и простая воронка — связка WordPress + WooCommerce часто выигрывает по скорости запуска и по цене входа. Экосистема плагинов закрывает типовые задачи без заказной разработки на каждый чих.</p><p>Облачные SaaS вроде Shopify годятся, когда компании нужен быстрый старт без администрирования сервера и команды DevOps. Комиссии и ограничения платформы нужно закладывать в юнит-экономику заранее — но для проверки гипотезы это иногда лучший компромисс.</p><p>OpenCart и аналоги я чаще видел у проектов, где важна предсказуемость и «руки разработчика на аутсорсе»: проще найти исполнителя, меньше сюрпризов, чем на экзотике. Magento и тяжёлый enterprise-класс имеют смысл, когда команда уже сильная технически и каталог — это отдельный продукт, а не «сайт с корзиной».</p><h2>Самопис — не зло, но это отдельная ставка</h2><p>Своя CMS имеет смысл, когда продукт по сути уникален и типовые решения мешают. Во всех остальных случаях вы покупаете не «уникальность», а дорогую поддержку собственного монстра: каждый апдейт PHP, каждый новый способ оплаты — ваш головняк.</p><h2>Если уже понятно, что платформа не та</h2><p>Переезд между системами редко бывает «копипастой базы». Обычно это заново собранная карточка товара, перепроверенные атрибуты, аккуратная переездная SEO-схема и пауза в маркетинге на время технических работ. Я закладываю такие работы как отдельный проект с понятным бэклогом — иначе получится хаос и простой продаж.</p><p>На этом этапе экономить опаснее всего: «перенесём как получится» почти всегда означает битые URL, дубли в выдаче и потерянные заказы в переходный месяц. Если уж делаете миграцию — делайте её один раз и основательно.</p><h2>Что мы делаем перед выбором</h2><ul><li>Считаем не «стоимость запуска», а стоимость трёх лет жизни: лицензии, хостинг, доработки, интеграции.</li><li>Фиксируем сценарии: каталог, промо, B2B/B2C, обмен с учёткой, маркетплейсы.</li><li>Закладываем буфер на рост — если через год SKU вырастет в пять раз, платформа должна выдержать без полной переделки.</li><li>Перед подписанием уточняем у подрядчика три неудобных вещи: сколько стоит час поддержки после запуска, как закрываются интеграции «не из коробки», и что будет, если через полгода понадобится второй склад или новый тип оплаты.</li></ul><p>Ответы без конкретики («сделаем как надо») для меня красный флаг. Нормальный исполнитель называет риски и диапазоны хотя бы порядка величины.</p><p>Если очень коротко: не экономьте на фундаменте там, где сайт — канал продаж. Экономия почти всегда вернётся чеком на миграцию.</p><p>Подробнее разобрал платформы и критерии в материале на сайте: <a href="https://webfull.ru/blog/vybor-cms-dlya-internet-magazina/">как выбрать CMS для интернет-магазина — сравнение подходов</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как я написал E2EE-мессенджер на Spring Boot и WebCrypto — и почему сервер не видит сообщения</title>
      <link>https://tproger.ru/articles/kak-ya-napisal-e2ee-messendzher-na-spring-boot-i-webcrypto-i-poch</link>
      <comments>https://tproger.ru/articles/kak-ya-napisal-e2ee-messendzher-na-spring-boot-i-webcrypto-i-poch?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Василенков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-ya-napisal-e2ee-messendzher-na-spring-boot-i-webcrypto-i-poch</guid>
      <description><![CDATA[<p>Разбор архитектуры E2EE-мессенджера на Spring Boot 3, React и WebCrypto: X3DH, symmetric ratchet, AES-GCM, WebSocket, multi-device и ограничения реализации.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-ya-napisal-e2ee-messendzher-na-spring-boot-i-webcrypto-i-poch">Как я написал E2EE-мессенджер на Spring Boot и WebCrypto — и почему сервер не видит сообщения</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[Stack Overflow]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[iOS]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Tor]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[Базы данных]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[React]]></category>
      <category><![CDATA[Docker]]></category>
      <category><![CDATA[MIT]]></category>
      <category><![CDATA[Алиса]]></category>
      <category><![CDATA[Redis]]></category>
      <category><![CDATA[QA]]></category>
      <category><![CDATA[Мессенджер]]></category>
      <category><![CDATA[5g]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Взлом]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[1C]]></category>
      <category><![CDATA[PostgreSQL]]></category>
      <category><![CDATA[Grafana]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 05 May 2026 05:35:02 GMT</pubDate>
      <content:encoded><![CDATA[<figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/240e412b-4307-49f9-b24f-bde7e0a7fd9a.webp" alt="" /></figure><p>Я Java-разработчик и в основном работаю с backend: Spring Boot, базы данных, интеграции, авторизация, WebSocket — всё то, что обычно находится за интерфейсом.</p><p>В какой-то момент я поймал себя на мысли: я каждый день пользуюсь мессенджерами, но плохо понимаю, как они устроены внутри. Окей, JWT, WebSocket, PostgreSQL, Redis — это понятно. Но что технически означает фраза "end-to-end encryption"? Как сервер доставляет сообщения, если он не должен их читать? Где живут ключи? Что хранится в базе? Что происходит, если у пользователя два устройства?</p><p>Решил разобраться через практику. Написал мессенджер с нуля. Назвал Chaos Messenger.</p><p>Сразу честно: криптографическую часть я изучал вместе с Claude и ChatGPT — читал спецификации X3DH и Double Ratchet, разбирал примеры, задавал вопросы, пока не сложилась цельная картина. Frontend тоже делался с активной помощью ChatGPT: я backend-разработчик, React для меня не основная среда. Но архитектура, backend, интеграция WebCrypto, модель конвертов, хранение сообщений и принципиальные решения — мои.</p><p>Для меня AI здесь был не заменой понимания, а инструментом — примерно как документация, Stack Overflow и ревью коллег. Без понимания threat model и архитектуры такой проект всё равно не собрать.</p><p>В статье расскажу, как работает E2EE изнутри: как устанавливается сессия через X3DH, как каждое сообщение получает отдельный ключ через Symmetric Ratchet, почему сервер хранит только зашифрованные конверты, и какие ошибки я допустил по дороге.</p><p>Стек: Spring Boot 3, React 18, WebCrypto API, PostgreSQL, Redis, WebSocket/STOMP, Prometheus, Grafana.</p><figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/4b028f37-2de1-46ea-a247-567f74fb3081.webp" alt="" /></figure><h2>Важная оговорка про web-E2EE</h2><p>Когда я говорю, что сервер не может прочитать сообщения, я имею в виду backend, базу данных, WebSocket-слой и уже сохранённые ciphertext-конверты. У них нет ключей и plaintext.</p><p>Но у web-E2EE есть отдельная проблема: frontend-код тоже приходит с сервера. Теоретически скомпрометированный сервер может отдать изменённый JavaScript, который украдёт ключи или plaintext до шифрования. Это ограничение не конкретно моего проекта, а браузерной модели в целом.</p><p>Поэтому корректная формулировка такая: backend не получает ключи и не может расшифровать уже переданные или сохранённые сообщения. Защита от подмены клиентского кода — отдельный слой безопасности: подпись сборок, независимая верификация клиента, desktop/mobile-приложения, reproducible builds.</p><h2>Почему обычный подход не работает</h2><p>Большинство "мессенджеров" на GitHub выглядят примерно так:</p><p>Сервер знает всё. Видит каждое сообщение. Если БД утекла — утекла вся переписка. Если сервер взломали — читай что хочешь. Если завтра компания решит продать данные — технически ничего не мешает.</p><p>E2EE решает это радикально: backend не получает ключи и не хранит plaintext. Сообщение шифруется на устройстве отправителя до отправки в сеть, а расшифровывается только на устройстве получателя.</p><p>Это уже не вопрос политики конфиденциальности в стиле "мы обещаем не читать". Это архитектурное ограничение: если у сервера нет ключа, он не может превратить ciphertext обратно в текст.</p><p>Звучит как магия. На самом деле — два протокола и немного WebCrypto.</p><h2>Главная идея: конверты</h2><p>Представь что Алиса хочет написать Бобу. Вместо того чтобы положить письмо на стол и надеяться что никто не прочитает — она кладёт его в запечатанный конверт. Конверт может открыть только Боб своим ключом. Сервер просто передаёт конверт не заглядывая внутрь.</p><p>Именно так это работает в коде. В базе данных у меня это выглядит так:</p><p>Когда я впервые увидел</p><p>в своей БД вместо текста — стало понятно, что модель наконец работает правильно: сервер создал сообщение, доставил его, сохранил метаданные, но так и не узнал содержимое.</p><p>А вот что сервер возвращает при запросе списка чатов через API:</p><p>Не</p><p>. Не</p><p>. Буквально</p><figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/b466ad91-20da-4e64-8b78-f6e08d2851d5.webp" alt="" /></figure><p>(DevTools → Network → ответ API с</p><p>)</p><h2>Откуда берутся ключи: X3DH</h2><p>Главный вопрос: как Алиса и Боб получают общий секрет, если они никогда раньше не общались? И как сделать это так, чтобы сервер только помог передать публичные данные, но сам не смог вычислить итоговый ключ?</p><p>Для этого используется X3DH — Extended Triple Diffie-Hellman, протокол из экосистемы Signal. Его задача — установить общий секрет между двумя устройствами, используя долгосрочные и временные ключи.</p><h2>Что хранится на сервере</h2><p>Когда пользователь регистрирует устройство, он загружает на сервер пакет публичных ключей:</p><p>На сервер уходят только публичные части. Приватные ключи сериализуются и хранятся локально в браузере — и никогда не покидают устройство в сеть.</p><p>Здесь важно сказать честно: хранение приватных ключей в</p><p>Более строгий вариант — использовать Web Crypto API с</p><p>, чтобы приватный ключ жил внутри браузерного crypto runtime и его нельзя было экспортировать в байты. Но у этого подхода есть практическая сложность: ключи нужно переживать между перезагрузками страницы, синхронизировать с IndexedDB, аккуратно восстанавливать состояние устройства и не сломать UX.</p><p>В браузерных E2EE-приложениях обычно приходится выбирать между несколькими вариантами:</p><ul><li>Сериализуемые ключи в localStorage или IndexedDB — проще реализовать, но нужно очень серьёзно относиться к XSS и целостности frontend-кода.</li><li>extractable: false + IndexedDB — безопаснее, но сложнее в реализации и восстановлении состояния.</li><li>Нативное secure storage вроде Android Keystore или iOS Secure Enclave — лучший вариант для мобильных клиентов, но он недоступен обычному web-приложению.</li></ul><p>В текущей версии Chaos Messenger используется первый вариант. Это осознанный компромисс для pet/open-source проекта и удобного запуска в браузере. Переход на non-extractable ключи и более строгую модель хранения стоит в roadmap.</p><p>Ключевой момент: backend всё равно не получает приватные ключи и не может расшифровать сохранённые ciphertext-конверты. Но защита ключей на клиенте — отдельная задача, и её нельзя честно замалчивать.</p><h2>Установка сессии</h2><p>Когда Алиса открывает переписку с Бобом впервые, происходит следующее:</p><p>В классическом X3DH четвёртая DH-операция с one-time prekey опциональна: она выполняется, если сервер выдал доступный OPK получателя. В моей реализации устройство публикует набор one-time prekeys при регистрации, поэтому первое сообщение обычно использует DH4. Если OPK закончились, сессию всё равно можно установить через остальные DH-компоненты, но это уже менее сильный вариант.</p><p>Боб, получив конверт с эфемерным публичным ключом Алисы, повторяет те же операции со своими приватными ключами и получает тот же самый</p><p>. Математика симметрична.</p><p>Сервер в этот момент видит только публичные ключи и зашифрованный конверт. Он помогает устройствам найти друг друга, но не участвует в вычислении секрета.</p><p>Получить</p><figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/e7bbacf3-4fd2-4710-863a-2c710b1f6759.webp" alt="" /></figure><h2>Как шифруется каждое сообщение: Symmetric Ratchet</h2><p>X3DH даёт нам стартовый</p><p>. Но использовать один и тот же ключ для всех сообщений — плохая идея. Если использовать один ключ для всей переписки, компрометация этого ключа сразу открывает весь поток сообщений.</p><p>Решение — симметричный ratchet. После каждого сообщения цепочка ключей продвигается вперёд:</p><p>Визуально это выглядит так:</p><p>используется для шифрования одного сообщения через AES-GCM, после чего уничтожается. Если атакующий компрометирует</p><p>— он прочитает только второе сообщение.</p><p>В рамках такой симметричной цепочки это даёт forward secrecy назад по цепочке: зная текущий или отдельный</p><figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/939a74f7-60c5-4816-85f0-05b5afdc9845.webp" alt="" /><figcaption>(диаграмма схемы chainKey → messageKey)</figcaption></figure><p>Само шифрование сообщения:</p><p>А вот что уходит на сервер — живой пример из DevTools:</p><p>Сервер получает</p><p>и</p><p>. Расшифровать без</p><figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/b5e24cda-6fd9-4b15-9f27-3eb9b4f843b0.webp" alt="" /></figure><h2>Важная оговорка: это ещё не полный Double Ratchet</h2><p>В этом проекте реализован Symmetric Ratchet — цепочка, где из</p><p>для каждого сообщения выводится отдельный</p><p>Это защищает прошлые сообщения: если атакующий узнает текущий ключ или отдельный</p><p>, он не сможет откатить HMAC назад и получить старые ключи.</p><p>Но это не полный Double Ratchet из Signal Protocol.</p><p>В полном Double Ratchet есть ещё DH ratchet step: стороны периодически выполняют новый Diffie-Hellman обмен и обновляют root key. Это даёт break-in recovery — возможность восстановить безопасность будущих сообщений после компрометации части состояния.</p><p>В моей реализации DH ratchet step пока нет. Если атакующий получит актуальное состояние сессии на устройстве и сможет продолжать его читать, он сможет расшифровывать будущие сообщения до переустановки сессии. Это честное ограничение текущей версии, и оно стоит первым пунктом в roadmap.</p><h2>Мультиустройство: один пользователь, несколько конвертов</h2><p>Первый неочевидный момент: в E2EE сообщение адресуется не просто пользователю, а конкретным устройствам пользователя.</p><p>Если у Боба два устройства — телефон и ноутбук — нужен отдельный encrypted envelope для каждого устройства. Сервер не может взять один конверт, расшифровать его и "переупаковать" для второго устройства: у него нет ключей и он не знает plaintext.</p><p>Значит при отправке сообщения нужно зашифровать его отдельно для каждого устройства каждого участника чата.</p><p>Для чата где у каждого по 2 устройства — 4 конверта на одно сообщение. Для группы из 10 человек — потенциально 20 конвертов. Это нормально, это цена безопасности.</p><h2>Сервер: хранение и доставка конвертов</h2><p>На сервере сообщение создаётся с контентом</p><p>, а конверты сохраняются отдельно:</p><p>После сохранения — fanout по WebSocket. Каждое устройство получает свой конверт и только его:</p><p>Это важное отличие от обычного WebSocket-чата. В обычном чате сервер рассылает одно и то же событие всем участникам. В E2EE-чате сервер рассылает разные события разным устройствам: payload для каждого устройства содержит свой</p><p>Топик</p><p>— строго персональный. Устройство А не получает конверт устройства Б. Никакого broadcast — только адресная доставка.</p><h2>Архитектура целиком</h2><figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/de0e3257-d893-459f-86ed-7ed8eace5d56.webp" alt="" /></figure><h2>Баг который долго не замечал</h2><p>В панели чатов показывается превью последнего сообщения. Я реализовал это через</p><p>Запускаю — в списке чатов у всех написано</p><p>.</p><p>Конечно. Сервер же не знает что там написано.</p><p>Я полчаса думал как решить это на сервере. Потом дошло: нельзя решить это на сервере — у него нет ключей. Решение только на клиенте.</p><p>После того как пользователь открыл чат и сообщения расшифровались — кешируем последнее в памяти:</p><p>Это хороший пример того, как E2EE меняет привычное мышление backend-разработчика. В обычном приложении preview — это поле в SQL-запросе. В E2EE-приложении preview — это локальное клиентское состояние, потому что только клиент видел plaintext.</p><p>Простое решение. Но чтобы к нему прийти нужно было полностью принять идею что сервер здесь просто не при делах — и перестать пытаться решить задачу на его стороне.</p><h2>Rate limiting: дыра которую легко не заметить</h2><p>Эндпоинт</p><p>отправляет SMS с кодом. Без защиты любой скрипт может дёргать его тысячи раз — это называется SMS pumping fraud, SMS стоят реальных денег.</p><p>Redis у нас уже был для хранения онлайн-статусов. Добавил rate limiting поверх него:</p><p>При превышении — HTTP 429 с заголовком</p><p>. Клиент знает через сколько секунд можно повторить.</p><p>Важный нюанс: в текущей реализации, если Redis недоступен, сервис не блокирует авторизацию полностью. Для pet-проекта это приемлемый компромисс: лучше рискнуть одним лишним SMS, чем положить вход в приложение.</p><p>В production я бы сделал строже: fallback in-memory лимит на инстанс, отдельные лимиты по IP и телефону, антифрод-логику и алерты на всплески отправки кодов.</p><h2>Авторизация WebSocket</h2><p>Отдельная история — авторизация WebSocket соединений. HTTP-эндпоинты защищены Spring Security автоматически, но WebSocket — другое дело. STOMP-соединение устанавливается один раз, и нужно проверять JWT при каждом подключении.</p><p>Отдельно важно не только проверить JWT, но и связать WebSocket-соединение с конкретным устройством. Пользователь может быть один, но устройств у него несколько, а encrypted envelope адресован именно</p><p>Поэтому при подключении я проверяю не только токен, но и</p><p>: устройство должно быть зарегистрировано и принадлежать текущему пользователю. Иначе легко случайно превратить per-device E2EE-доставку обратно в обычный broadcast по пользователю.</p><h2>Что получилось — живые скрины</h2><figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/1fdfa006-f5c6-4731-a40f-50559be8832d.webp" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/137649/2026-04-29/c99164a5-021c-49ac-bcc4-3e38f9cd1c31.webp" alt="" /></figure><p>Что реализовано:</p><ul><li>E2EE-модель с per-device encrypted envelopes</li><li>X3DH session setup + Symmetric Ratchet + AES-GCM</li><li>Мультиустройство</li><li>Личные и групповые чаты</li><li>Realtime доставка через WebSocket/STOMP</li><li>Статусы SENT → DELIVERED → READ</li><li>Редактирование и soft delete сообщений</li><li>Online presence, typing indicator</li><li>Фото-вложения</li><li>Поиск пользователей</li><li>Rate limiting на SMS через Redis</li><li>Prometheus метрики + Grafana дашборд</li><li>Swagger UI с JWT авторизацией</li><li>24 backend-теста на Testcontainers, 12 frontend на Vitest, E2E на Playwright</li><li>GitHub Actions CI</li></ul><p>Что ещё не сделано:</p><ul><li>Полный Double Ratchet с DH ratchet step и break-in recovery</li><li>Ротация signed prekey и аккуратное пополнение one-time prekeys</li><li>Более строгая модель хранения приватных ключей на клиенте: non-extractable CryptoKey + IndexedDB</li><li>Защита от подмены frontend-кода: подпись сборок, независимая верификация клиента, reproducible builds</li><li>Android-клиент с Android Keystore</li><li>Реальный SMS-провайдер вместо кода в backend-логах</li><li>Push-уведомления без утечки содержимого сообщений</li><li>Более строгая metadata-модель для групповых чатов</li></ul><h2>Главный инсайт</h2><p>E2EE — это архитектурное решение, а не библиотека.</p><p>Нельзя взять обычный Spring Boot чат и просто "включить шифрование". Нужно с самого начала проектировать систему так, чтобы backend не был участником доверенной зоны: он не должен получать plaintext, не должен иметь ключи и не должен уметь пересобирать сообщение из данных в базе.</p><p>Это меняет почти всё:</p><ul><li>структуру БД — вместо текста появляются encrypted envelopes</li><li>API — сервер отдаёт [encrypted], а не preview сообщения</li><li>WebSocket — доставка идёт не по пользователю, а по конкретному устройству</li><li>мультиустройство — одно сообщение превращается в несколько ciphertext-конвертов</li><li>frontend — становится полноценной криптографической частью системы, а не просто UI</li></ul><p>Второй инсайт: мессенджер — это не "чат с WebSocket". В E2EE-модели это система доставки зашифрованных конвертов с адресацией по устройствам. Как только это принимаешь, многие странные на первый взгляд решения становятся логичными.</p><h2>Репозиторий</h2><p>Код открыт: <a href="https://github.com/vaazhen/chaos-messenger">github.com/vaazhen/chaos-messenger</a></p><p>В репозитории есть README на русском и английском, диаграммы, скриншоты, security audit, Docker Compose и запуск одной командой.</p><p>Проект не претендует на уровень production-криптомессенджера вроде Signal. Это учебный и инженерный open-source прототип, цель которого — показать, как E2EE меняет архитектуру backend, frontend и realtime-доставки.</p><p>Если вы делали что-то похожее — особенно интересно сравнить подходы к ротации prekey-ов, хранению non-extractable ключей в браузере и реализации DH ratchet step. Вопросы и критика приветствуются.</p>]]></content:encoded>
    </item>
    <item>
      <title>Страница статусов снизила нагрузку на поддержку в три раза. Как мы к этому пришли</title>
      <link>https://tproger.ru/articles/stranica-statusov-snizila-nagruzku-na-podderzhku-v-tri-raza-kak</link>
      <comments>https://tproger.ru/articles/stranica-statusov-snizila-nagruzku-na-podderzhku-v-tri-raza-kak?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Алексей Симоненков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/stranica-statusov-snizila-nagruzku-na-podderzhku-v-tri-raza-kak</guid>
      <description><![CDATA[<p>Разбор кейса: как страница статусов сократила количество тикетов во время инцидентов на 67%. Что пробовали до этого, как устроен нормальный incident workflow и что важно при выборе инструмента для российского рынка.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/stranica-statusov-snizila-nagruzku-na-podderzhku-v-tri-raza-kak">Страница статусов снизила нагрузку на поддержку в три раза. Как мы к этому пришли</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[Новости]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Tor]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Telegram]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Системное администрирование]]></category>
      <category><![CDATA[Высокие нагрузки]]></category>
      <category><![CDATA[Техподдержка]]></category>
      <category><![CDATA[Сервер]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 28 Apr 2026 06:40:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Несколько лет назад я работал в компании, которая делала платёжный процессинг. Не скажу название - NDA жив до сих пор. Но расскажу про один конкретный вечер в пятницу, который изменил то, как я думаю об инцидентах.</p><p>Около семи вечера начали падать транзакции. Не все - примерно 15%. Команда сразу занялась разбором: логи, метрики, трейсы. Стандартный процесс. Проблему нашли и починили за 40 минут. По меркам платёжки - нормально.</p><p>Но пока мы разбирались, в поддержку пришло 300 тикетов. Три сотни «что происходит», «у нас не проходят платежи», «когда заработает». Саппорт ничего не знал - он ждал, пока инженеры выплывут из логов. Клиенты ждали саппорт. Всё это время тишина с нашей стороны читалась как безразличие.</p><p>Проблему починили за 40 минут. Разгребали тикеты три дня.</p><h2>Почему молчание хуже, чем «мы знаем о проблеме»</h2><p>Есть простая психология: человек переносит неопределённость хуже, чем плохие новости. Если транзакция не прошла и нет никакой информации - клиент начинает строить сценарии. Деньги потерялись. Сервис умер. Нас кинули. Он пишет в поддержку. Потом пишет ещё раз. Потом оставляет отзыв.</p><p>Если транзакция не прошла, но есть страница</p><p>с записью «Повышенное время отклика платёжного шлюза. Investigating. 19:12» - большинство людей закрывают вкладку и ждут. Не все. Но большинство.</p><p>Мы это проверили. После того как поставили нормальную страницу статусов, количество тикетов во время инцидентов упало примерно в три раза. Точнее - на 67% по среднему за квартал. Это не магия, это просто информация в нужный момент.</p><h2>Что мы пробовали до этого</h2><p>Расскажу честно, через что прошли, потому что это типичный путь.</p><p>Шаг первый: Telegram-канал. Завели канал «Статус сервиса». Писали туда когда что-то падало. Работало ровно до тех пор, пока кто-то не забыл написать. А потом написал через два часа когда уже всё починилось. Клиенты не понимали что происходило. Доверие к каналу упало быстро.</p><p>Шаг второй: статус в шапке сайта. Зелёный кружок когда всё хорошо. Ручной - кто-то должен был его менять. Понятно куда это ведёт: кружок всегда зелёный, потому что некогда, потому что забыли, потому что «сейчас разбираемся, потом обновим».</p><p>Шаг третий: Atlassian Statuspage. Это уже нормальный инструмент. Он решил проблему. Но у него есть два неудобства для русскоязычного рынка: оплата в долларах (что в 2022 стало практической проблемой) и серверы за пределами России (что для ряда клиентов принципиально с точки зрения регулирования).</p><h2>Как устроен нормальный incident workflow со страницей статусов</h2><p>Я говорю «нормальный» - имею в виду тот, который не требует героизма от дежурного инженера в 2 ночи.</p><p>Всё начинается с мониторинга. HTTP/TCP-проверки каждую минуту на все критичные эндпоинты: API, веб, база, очереди. Когда что-то падает - автоматическое создание инцидента и уведомление команды. Это не новость, большинство так и делают.</p><p>Новость в том, что параллельно с уведомлением команды - автоматическое обновление публичной страницы статусов. Не «кто-то должен написать туда», а именно автоматически. Клиент видит «Degraded performance» раньше, чем успевает написать в поддержку.</p><p>Дальше инженер работает по стандартному процессу: Investigating - Identified - Monitoring - Resolved. Каждый статус обновляется на странице. Клиенты, подписавшиеся на уведомления, получают апдейты в Telegram или email. Поддержка может в один клик скопировать ссылку на инцидент и отправить клиенту вместо объяснений.</p><p>После разрешения - postmortem прямо на странице. Клиенты видят что случилось, почему и что сделано чтобы не повторилось. Это, как ни странно, повышает доверие сильнее, чем если бы инцидента не было совсем.</p><h2>Что важно при выборе инструмента</h2><p>Несколько технических вещей, на которые стоит обратить внимание.</p><p>Uptime самой страницы статусов. Она должна быть на отдельной инфраструктуре. Если ваш основной сервис упал и страница статусов на той же инфраструктуре - вы получили идеальный шторм: сервис не работает и статус показать невозможно.</p><p>Собственный домен.</p><p>вместо</p><p>. Это доверие и брендинг.</p><p>Telegram-уведомления. Для российской аудитории это важнее email. Люди читают Telegram, а не почту, когда ищут статус сервиса в панике.</p><p>Локализация данных. Если работаете с персональными данными российских пользователей - вопрос где физически хранятся данные о ваших инцидентах становится юридическим, а не техническим.</p><p>Мы в Flaree делаем страницу статусов именно для таких случаев - серверы в России, Telegram из коробки, оплата в рублях. Сейчас открыт ранний доступ, первые 50 команд получают 3 месяца Pro бесплатно: <a href="https://flaree.ru/">flaree.ru</a></p><h2>Что в итоге</h2><p>Страница статусов - это не инструмент для больших команд. Это инструмент для любого сервиса, у которого есть клиенты и бывают инциденты. То есть для всех.</p><p>Настройка занимает 15 минут. Первый же инцидент, который клиенты узнают из статусной страницы раньше, чем напишут в поддержку - окупает это время с запасом.</p><p>P.S. Если у вас уже есть страница статусов - напишите в комментариях какой инструмент используете. Интересно что прижилось у разных команд.</p>]]></content:encoded>
    </item>
    <item>
      <title>Слово за ИИ: как речевая аналитика меняет телекоммуникации</title>
      <link>https://tproger.ru/articles/slovo-za-ii-kak-rechevaya-analitika-menyaet-telekommunikacii</link>
      <comments>https://tproger.ru/articles/slovo-za-ii-kak-rechevaya-analitika-menyaet-telekommunikacii?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Александр Красников]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/slovo-za-ii-kak-rechevaya-analitika-menyaet-telekommunikacii</guid>
      <description><![CDATA[<p>Рассказываем, как ИИ помогает бизнесу говорить на одном языке с клиентом в поддержке и повышать продажи.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/slovo-za-ii-kak-rechevaya-analitika-menyaet-telekommunikacii">Слово за ИИ: как речевая аналитика меняет телекоммуникации</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 23 Apr 2026 06:00:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Бизнес активно внедряет речевую аналитику, о чем говорит быстрый рост глобального рынка подобных решений. По данным <a href="https://www.datainsightsmarket.com/reports/speech-analytics-industry-14722">отчета</a> аналитической компании Data Insight, в 2025 году он оценивался на уровне 3,13 млрд долларов, а средний годовой темп его роста составит в период с 2025-го по 2033 годы 15,6%. Эта динамика во многом объясняется быстрым развитием облачных ИИ-решений, которые становятся доступны не только крупному, но  малому и среднему бизнесу.</p><p>В России также востребована речевая аналитика прежде всего банками, поставщиками страховых услуг, медицинскими и телекоммуникационными компаниями. Интерес к таким сервисам растет, потому что бизнес уделяет все больше внимания повышению качества клиентского опыта и заинтересован в получении маркетинговой информации, которую в изобилии приносит анализ всех разговоров с клиентами.</p><p>Кроме того, росту рынка способствует развитие омниканальных решений связи, в которых также очень часто задействованы сервисы для анализа коммуникаций. Российский рынок речевой аналитики, по ранее опубликованному <a href="https://telecomdaily.ru/news/2023/11/09/iaa-telecomdaily-rossiyskiy-rynok-ra-budet-rasti-v-srednem-na-15-ezhegodno">прогнозу</a> TelecomDaily, растет схожими с мировым темпами: в 2025 году он должен был увеличиться на 16% и составить 1,56 млрд руб.</p><p>Если говорить упрощенно, то речевая аналитика — это ИИ-анализ коммуникаций, то есть любых диалогов с помощью больших языковых моделей. Нейросети переводят голос в текст и, выполняя поставленные им задачи, отслеживают соответствие речи оператора или клиента заранее настроенным параметрам.</p><p>Такие сервисы умеют выделять диалоги с повышенным, отрицательным эмоциональным фоном, оценивать уровень уверенности в речи менеджера по продажам, наличие в разговоре логики, ключевых слов, соответствия скриптам. На основе этих данных алгоритмы формируют отчеты, которые дают бизнесу представление об уровне сервиса и эффективности продаж.</p><p>Разумеется, такой анализ требуется прежде всего в отделах клиентской поддержки и продаж, чтобы контролировать качество работы менеджеров, видеть узкие места, типичные ошибки в коммуникационных сценариях. На основе речевой аналитики можно принимать решения о корректировке бизнес-процессов и даже стратегические. Использование таких сервисов нельзя сравнить с ручным анализом, ведь они достигают нужной цели на порядки быстрее человека.</p><p>Если упростить: чтобы проанализировать час разговора с клиентом, порой требуется потратить тот же час. ИИ сделает это за несколько минут.</p><h2>Речевая аналитика и предубеждения</h2><p>Сегодня не приходится говорить о том, что речевая аналитика — будущее компаний. Эти технологии уже находятся на высоком уровне развития и внедряются во многих сферах. Еще больше на них возлагается надежд, связанных с тем, что они полностью изменят бизнес и сделают его радикально эффективнее, помогут исправить все недостатки в бизнес-процессах. Однако это не совсем так: ИИ в телекоммуникациях — это условие для принятия верных решений, а не инструмент для устранения проблем.</p><p>Например: речевая аналитика способна выявить ключевые маркеры эффективности менеджеров. А вот что делать с результатами анализа, как их обратить на пользу бизнесу — отдельная задача для стратегов. Анализ действительно может показать, например, что менеджеры по продажам допускают ошибки, предлагая конкретный продукт (или не предлагают его вовсе). Однако нейросети просто предоставляют отчет, суммаризируют диалоги и оценивают их результативность, и это лишь констатация факта, с которым необходимо дальше работать.</p><p>Второй предрассудок — якобы предельно высокая стоимость внедрения речевой аналитики и похожих ИИ-решений. Какое-то время назад они действительно были доступны только крупному бизнесу, а для среднего и малого оставались далеко не всегда рациональным расходованием средств. Это было связано с высокой ценой решений на этапе их выхода на рынок. Но сейчас стоимость LLM, как и оборудования, на которых они работают, снижается.</p><p>Растут конкуренция и выбор ИИ-решений, а общая их эффективность повышается, что делает их внедрение все более оправданным для компаний любого масштаба. Даже с учетом того, что затрат требуют не только оборудование и программы, но и работа квалифицированных сотрудников, которых на рынке пока не хватает ( следовательно, их зарплаты находятся на высоком уровне и растут).</p><p>Впрочем, к оценке стоимости проектов по внедрению речевой аналитики необходимо подходить не линейно: их цена должна рассматриваться в контексте повышения эффективности работы бизнеса. Если компания благодаря внедрению ИИ получает полмиллиона дополнительной прибыли, и это стоит ей 300 тысяч на ежемесячную зарплату инженеру — выбор вполне очевиден.</p><h2>LLM становятся доступнее</h2><p>Стоимость больших языковых моделей падает, так как их становится больше. Сегодня выбор ИИ-решений в области распознавания и анализа речи на рынке достаточно широк, хотя фундаментально такие технологии разрабатывают лишь несколько крупнейших ИТ-компаний. Но предложение не ограничивается проприетарными LLM: в открытом доступе присутствуют разработки open source, например от LLaMA, Qwen и других компаний.</p><p>У моделей с открытым программным кодом есть свои преимущества. Они создаются на основе совместных исследований разработчиков ИИ-решений, обычно поддерживают несколько языков, а главное — компаниям проще кастомизировать их под свои потребности, чем в случае с проприетарными LLM.</p><p>При этом стоит отметить, что у отечественных моделей тоже есть важный плюс: они изначально лучше подходят для русскоязычных пользователей, ведь обучаются на русском языке. Это отчасти обусловливает тот факт, что российские решения нередко (но не всегда) дают более качественные ответы, чем зарубежные. Выбор модели в любом случае зависит от потребностей компании в кастомизации продукта, от масштабов и бюджета бизнеса.</p><p>То же касается и решения — разворачивать ли ИИ-сервисы в собственном контуре или в облаках. Как правило, среднему и малому бизнесу экономически невыгодно локализовывать ИИ-агентов полностью в своей инфраструктуре.</p><h2>Принцип работы моделей</h2><p>Важно понимать, что на сегодняшний день в большинстве случаев нет возможности поставить модели любую задачу и получить решение на основе свободной мысли и воли искусственного интеллекта. Большинство из них формулируют ответы, используя в работе уже загруженную в них информацию, при этом они постоянно нуждаются в обучении. Их внутреннюю базу знаний приходится периодически пополнять, а также при необходимости настраивать доступ моделей к внешним источникам информации. Ими могут быть интернет либо внутренние базы знаний в компании. При этом, если модель ищет информацию в сети, то ее ответы будет сложно верифицировать. Поэтому чаще всего в чат-боты, ИИ-ассистенты, умные помощники операторов контакт-центра встроены модели, которые используют данные только из внутренних информационных систем бизнеса. Они выделяют нужное, формулируют ответы и списки источников, которыми пользовались, а человек только проверяет результаты. Но специалист пока остается последним звеном и фильтром тех решений, которые предлагает нейросеть. Потому что галлюцинации ИИ все равно неизбежны.</p><p>Как ни странно, это связано с принципиальным устройством «мышления» моделей: на самом деле у них нет задачи ответить на вопрос верно. Они просто обязаны дать любой ответ. Насколько точным он окажется, полностью зависит от качества данных, на которых обучена модель, и умения сотрудников ставить задачи для ИИ. В этом деле самое важное — понимать, что модель не умеет видеть смыслы и у нее нет обязательного для любого человека интеллектуального бэкграунда.</p><p>Проще говоря, у нее отсутствуют априорные знания о явлениях и предметах (солнце — желтое), поэтому идеальный промпт должен быть максимально подробным: не стоит опасаться перегнуть палку с формализацией при описании задач. Может показаться, что такой промпт предназначен ребенку — что же, пока ИИ, к счастью или  сожалению, и правда не дорос до уровня человеческого осознания.</p>]]></content:encoded>
    </item>
    <item>
      <title>Вышел OpenSSL 4.0 — выпилены engines, SSLv3 и ASN1_STRING</title>
      <link>https://tproger.ru/news/vywel-openssl-4-0-vypileny-engines-sslv3-i-asn1-string</link>
      <comments>https://tproger.ru/news/vywel-openssl-4-0-vypileny-engines-sslv3-i-asn1-string?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/vywel-openssl-4-0-vypileny-engines-sslv3-i-asn1-string</guid>
      <description><![CDATA[<p>OpenSSL 4.0 — первый мажор с 2021 года. Удалили engine-интерфейс (ломает gost-engine), SSLv3, сделали ASN1_STRING непрозрачным. Узнайте, как мигрировать с 3.x.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/vywel-openssl-4-0-vypileny-engines-sslv3-i-asn1-string">Вышел OpenSSL 4.0 — выпилены engines, SSLv3 и ASN1_STRING</a>»</p>]]></description>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Библиотеки]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 15 Apr 2026 09:00:04 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если в вашей сборке крутится что-то линкованное с OpenSSL — посмотрите, не сломает ли вас переход на 4.0: релиз выкидывает engine-интерфейс (на нём держится gost-engine для ГОСТ-криптографии), поддержку SSLv3, скрипт c_rehash и делает непрозрачной структуру ASN1_STRING. Следом едут новые фичи — Encrypted Client Hello, гибридный постквант-обмен и FFDHE в TLS 1.2.</p><p>14 апреля 2026 года OpenSSL Project <a href="https://openssl-library.org/post/2026-04-14-openssl-4.0/">выпустил OpenSSL 4.0</a> — первый мажорный релиз со времён 3.0 (сентябрь 2021). За четыре с половиной года накопилось много удалений и чуть поменьше новых возможностей. Разбираем, что именно сломается при апгрейде и ради чего всё это затевалось.</p><ul><li>OpenSSL 4.0 — первый мажор с 2021 года. Релиз 14 апреля 2026.</li><li>Engine-интерфейс удалён полностью. Ломает gost-engine, старые PKCS#11- и TPM-адаптеры — мигрируйте на providers.</li><li>Поддержка SSLv3 вырезана из кода (выключена по умолчанию была с 2016 года).</li><li>ASN1_STRING стал непрозрачным — прямой доступ к полям через -&gt; больше не компилируется.</li><li>Появилась поддержка ECH (RFC 9849) — TLS прячет SNI от провайдера.</li><li>Добавлен гибридный постквантовый обмен SM2+ML-KEM-768 и подпись ML-DSA-MU.</li></ul><h2>Что выпилили: список для миграции</h2><p>OpenSSL 3.0 в 2021 году ввёл архитектуру providers и одновременно объявил engine-интерфейс устаревшим. Четыре года переходного периода закончились: engines больше нет в коде, опция сборки no-engine всегда включена, макрос OPENSSL_NO_ENGINE — всегда определён. Это самое болезненное для тех, кто держал кастомный крипто-плагин: GOST, аппаратные HSM, PKCS#11-токены со старым драйвером.</p><p>Из публичных API в 4.0 пропали или стали непрозрачными:</p><ul><li>Engine-интерфейс целиком — <a href="https://www.openssl.org/docs/man3.0/man7/provider.html">providers</a> теперь единственный способ подключить внешнюю криптографию.</li><li>Поддержка SSLv2 Client Hello и SSLv3. SSLv3 деприкейтнули ещё в 2015 году (<a href="https://datatracker.ietf.org/doc/html/rfc7568">RFC 7568</a>), в 1.1.0 выключили по умолчанию в 2016-м, теперь удалили из кода.</li><li>Структура ASN1_STRING стала непрозрачной. Прямой доступ к полям — через функции-аксессоры.</li><li>ERR_get_state(), ERR_remove_state(), ERR_remove_thread_state() — объект ERR_STATE теперь непрозрачный.</li><li>Кастомные методы EVP_CIPHER, EVP_MD, EVP_PKEY, EVP_PKEY_ASN1 — устаревшие API удалены.</li><li>X509_cmp_time() и семейство деприкейтнуты в пользу X509_check_certificate_times().</li><li>Скрипт c_rehash — использовать openssl rehash.</li><li>BIO_f_reliable() — был сломан с 3.0 и без жалоб прожил все эти годы.</li><li>Опция msie-hack в команде openssl ca.</li><li>Таргеты сборки darwin-i386 и darwin-ppc.</li><li>Устаревшие эллиптические кривые в TLS (<a href="https://datatracker.ietf.org/doc/html/rfc8422">RFC 8422</a>) выключены в сборке по умолчанию — включаются флагом enable-tls-deprecated-ec.</li><li>Explicit EC curves — аналогично, флаг enable-ec_explicit_curves.</li></ul><p>Отдельно изменилось поведение глобальной очистки. libcrypto больше не ставит обработчик на atexit(); OPENSSL_cleanup() теперь вызывается как глобальный деструктор при выходе процесса — значит, освобождение памяти по умолчанию происходит позже и в непредсказуемом порядке относительно других деструкторов. Если вам нужна детерминированная очистка до завершения процесса (например, чтобы выявлять утечки под valgrind), вызывайте OPENSSL_cleanup() явно.</p><h2>Что это значит для ГОСТ-криптографии</h2><p><a href="https://github.com/gost-engine/engine">gost-engine</a> — основной проект, который даёт OpenSSL понимание российских алгоритмов (ГОСТ Р 34.10-2012, ГОСТ Р 34.11-2012, «Кузнечик» и «Магма» по ГОСТ Р 34.12-2015). Как понятно из названия, он реализован именно как engine и без engine-слоя собраться и загрузиться в OpenSSL 4.0 не сможет.</p><p>Альтернатива — <a href="https://github.com/provider-corner/gostprov">gostprov</a>, провайдер от того же сообщества на новом API. На 15 апреля 2026 года gostprov покрывает базовые примитивы — ГОСТ Р 34.10-2012 (подпись), ГОСТ Р 34.11-2012 (хеш «Стрибог») и блочный шифр «Магма»/«Кузнечик» (ГОСТ Р 34.12-2015). Что ещё не закрыто по сравнению с gost-engine: часть схем шифрования CMS (ГОСТ-обёртки ключей), VKO KEK-2012 и ряд нишевых TLS-свитов. Если ваш продукт сертифицирован по требованиям ФСБ или продаётся в госсектор — апгрейд на 4.0 нужно планировать заранее, с пересертификацией.</p><p>Ветки 3.x продолжают поддерживаться: 3.5 — LTS до апреля 2030 года, 3.4/3.3 — обычные релизы с обновлениями безопасности. Если с 4.0 спешить некуда — остановитесь на 3.5 и дождитесь, пока gostprov покроет нужные вам примитивы.</p><h2>Что добавили</h2><h3>Encrypted Client Hello (ECH)</h3><p>ECH — это <a href="https://datatracker.ietf.org/doc/rfc9849/">RFC 9849</a>, принятый в марте 2026 года. В обычном <a href="https://tproger.ru/articles/tls-handshake-explained">TLS-рукопожатии</a> первый Client Hello содержит SNI — имя сайта, к которому вы подключаетесь — в открытом виде. Провайдер видит его и по нему можно фильтровать трафик или собирать метаданные. ECH делит Client Hello на две части: ClientHelloOuter с именем фронтового домена идёт в открытую, а ClientHelloInner с настоящим SNI шифруется публичным ключом, опубликованным через DNS (HTTPS-запись).</p><p>OpenSSL 4.0 — первая мажорная версия с ECH в основной ветке. Серверная и клиентская стороны поддерживают draft-final в полном объёме. Документация проекта — <a href="https://github.com/openssl/openssl/blob/master/doc/designs/ech-api.md">doc/designs/ech-api.md</a>.</p><h3>Гибридный постквант: SM2+ML-KEM-768</h3><p>OpenSSL поддерживает ML-KEM (Module-Lattice Key Encapsulation Mechanism, FIPS 203 — постквантовый обмен ключами) и гибриды с ним с версии 3.5. В 4.0 добавили ещё один гибридный обмен — curveSM2MLKEM768: китайский SM2 (<a href="https://datatracker.ietf.org/doc/rfc8998/">RFC 8998</a>) плюс ML-KEM-768 в качестве постквантовой части. Комбинация адресная — она нужна прежде всего для рынка КНР, где SM2 обязателен по национальному стандарту. Плюс новый алгоритм цифровой подписи ML-DSA-MU — вариант <a href="https://tproger.ru/news/openssh-10-3-zakryvaet-shell-injection-i-nachinaet-postkvantovuyu">ML-DSA</a> с внешним префиксом (prehash) для больших сообщений.</p><p>Для остального мира в релизе также появился <a href="https://csrc.nist.gov/pubs/sp/800/185/final">cSHAKE</a> (SP 800-185 — customizable SHAKE, версия SHAKE с доменным разделением). cSHAKE используется как строительный блок в новых стандартах NIST — именно на нём построен KMAC, а также часть постквантовых подписей. Плюс KDF для SNMP и SRTP — узкие штуки, но их в OpenSSL долго не было.</p><h3>FFDHE в TLS 1.2 и прочие мелочи</h3><p>FFDHE (finite-field Diffie-Hellman) по <a href="https://datatracker.ietf.org/doc/html/rfc7919">RFC 7919</a> — способ согласовывать группы для классического DH из фиксированного списка, а не из того, что сервер пришлёт. В TLS 1.3 это сделали сразу, в TLS 1.2 OpenSSL годами поддерживал только «пришли мне параметры». 4.0 закрыл этот пробел.</p><ul><li>FIPS self tests теперь можно откладывать до реального использования — флаг -defer_tests в openssl fipsinstall.</li><li>На Windows можно выбирать статическую или динамическую линковку VC Runtime.</li><li>Нижние границы параметров PKCS5_PBKDF2_HMAC теперь проверяются при работе в FIPS-провайдере.</li><li>Проверка AKID добавлена при установленном X509_V_FLAG_X509_STRICT.</li><li>CRL-верификация получила несколько дополнительных проверок корректности.</li></ul><h2>Как мигрировать на OpenSSL 4.0</h2><ol><li>Не обновляйтесь в лоб. Сначала прогоните вашу сборку с 3.5 и флагами -Wdeprecated-declarations и OPENSSL_NO_DEPRECATED_3_0, чтобы увидеть, где висит engine-API или структурный доступ к ASN1_STRING.</li><li>Составьте карту зависимостей: какие ваши библиотеки линкуются с OpenSSL и какие из них делают что-то нестандартное. Особое внимание — ко всему, где в коде встречается ENGINE_*.</li><li>Если используете ГОСТ — ставьте параллельно gostprov на 3.x, проверьте, что покрываются все ваши примитивы, и только после этого двигайтесь к 4.0.</li><li>Проверьте, как ваше приложение освобождает ресурсы OpenSSL. Если вы полагались на atexit()-финализацию или ранний OPENSSL_cleanup() в середине работы — добавьте явный вызов в точку, где очистка действительно нужна.</li><li>Пересоберите статические пакеты. OpenSSL 4.0 несовместим по ABI с 3.x — пакетные менеджеры дистрибутивов ближайшие месяцы будут подтягивать зависимости.</li></ol><h2>Выводы</h2><p>OpenSSL 4.0 — релиз не столько про новые фичи, сколько про дочистку хвостов. За четыре с половиной года команда вывела из эксплуатации несколько слоёв устаревшего API и зафиксировала архитектуру providers как единственный способ подключать внешнюю криптографию. Цена — несовместимость по исходникам и ABI. На 15 апреля 2026 года крупные пакеты Debian, Ubuntu, RHEL и Fedora ещё линкуются с 3.x; пересборка экосистемы займёт месяцы, а для продуктов на engines (HSM-адаптеры, gost-engine, старые PKCS#11-драйверы) — ещё дольше.</p><p>Практический совет: если у вас нет конкретной нужды в ECH или SM2+ML-KEM-768, ближайший год можно спокойно сидеть на 3.5 LTS и следить за тем, как пересобираются ваши зависимости. Когда пакетные менеджеры дистрибутивов начнут подтягивать 4.0 автоматически — это и будет момент серьёзной миграции.</p><p>Полный changelog, downloadable tarballs и ключи для проверки подписи — на странице <a href="https://github.com/openssl/openssl/releases/tag/openssl-4.0.0">релиза на GitHub</a>. Сам <a href="https://github.com/openssl/openssl/blob/openssl-4.0.0/CHANGES.md">файл CHANGES.md</a> — хорошее чтение на вечер для всех, кто хоть раз линковал с OpenSSL.</p>]]></content:encoded>
    </item>
    <item>
      <title>9 нативных API браузера вместо npm-пакетов</title>
      <link>https://tproger.ru/translations/9-nativnyh-api-brauzera-vmesto-npm-paketov</link>
      <comments>https://tproger.ru/translations/9-nativnyh-api-brauzera-vmesto-npm-paketov?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/9-nativnyh-api-brauzera-vmesto-npm-paketov</guid>
      <description><![CDATA[<p>9 встроенных API браузера вместо npm-пакетов: requestIdleCallback, :focus-within, container queries, dialog, Speech API и другие — с примерами кода.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/9-nativnyh-api-brauzera-vmesto-npm-paketov">9 нативных API браузера вместо npm-пакетов</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 10 Apr 2026 07:45:04 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если вы привыкли ставить npm-пакет под каждую задачу — вот девять вещей, под которые давно существует нативный API браузера. Кода меньше, багов меньше, бандл легче. Статья польской разработчицы Sylwia Łask собрала самые показательные примеры — перевели и адаптировали для русскоязычного читателя.</p><ul><li>requestIdleCallback — запустить фоновую задачу, когда браузер простаивает</li><li>:focus-within — стилизовать родителя, внутри которого есть элемент в фокусе</li><li>navigator.onLine + события offline/online — детектировать пропажу интернета</li><li>requestAnimationFrame — плавная анимация без рывков</li><li>Container queries — адаптив относительно размеров контейнера, а не viewport</li><li>crypto.getRandomValues — криптографически стойкие случайные ID без коллизий</li><li>&lt;dialog&gt; — нативный модал с доступностью из коробки</li><li>Web Speech API — распознавание речи без библиотек (только Chromium)</li><li>@supports — CSS feature detection без костылей</li></ul><h2>1. «Запустим это потом» → requestIdleCallback</h2><p>Хотите собирать аналитику, предзагружать данные или генерировать что-то в фоне, не конкурируя с рендером 200 компонентов? requestIdleCallback запускает ваш код в те моменты, когда браузер простаивает. На первый взгляд это кажется узкоспециальной фичей, но на практике кейсов много: сбор аналитики о поведении пользователя, несрочная фоновая обработка картинок, предварительная подготовка данных, которые пригодятся позже.</p><p>Поддержка: современные браузеры. В Safari исторически отсутствовал, так что fallback на setTimeout всё ещё полезен.</p><h2>2. «Почему мой input не подсвечивается?» → :focus-within</h2><p>Стилизовать элемент с фокусом — просто. А как стилизовать родителя, внутри которого какой-то элемент получил фокус, — задача, которую обычно решают сорока строками JavaScript со слушателями focus и blur. Всё это не нужно: :focus-within делает то же самое одной CSS-строкой.</p><p>Поддержка: везде, где это хоть сколько-нибудь важно.</p><h2>3. «Покажем офлайн-режим» → navigator.onLine</h2><p>Вечная боль любого PWA — что делать, когда у пользователя пропал интернет (он уехал в лес или зашёл в лифт). Можно писать сложные if-ы — а можно просто слушать события offline и online. На offline складываем данные в IndexedDB, на online отправляем на сервер.</p><p>Поддержка: широкая. Одна оговорка: «онлайн» не равно «ваш бэкенд доступен». Это проверка уровня сетевого соединения, а не доступности конкретного сервиса.</p><h2>4. «Плавная анимация, но проклятая» → requestAnimationFrame</h2><p>Хотите, чтобы анимация не дёргалась на слабых ноутбуках, а батарея садилась медленнее? Привычка «60 fps = setInterval каждые 16 мс» — плохая идея, и вот почему. Классика, которую все видели:</p><p>Интуитивно понятно, что это плохая идея. Лагает. К счастью, есть requestAnimationFrame — он синхронизирован с циклом перерисовки браузера, поэтому анимация действительно плавная.</p><p>Поддержка: везде.</p><h2>5. «Карточка должна адаптироваться, но только здесь» → container queries</h2><p>Одну и ту же карточку можно положить в узкий сайдбар, в основную ленту или в лайтбокс — и чтобы она корректно подстраивалась под каждое место без знания о том, на каком она экране. Раньше media queries были привязаны к размеру viewport, то есть «ко всей странице». Container queries позволяют применять стили в зависимости от размера конкретного контейнера. Компонент становится самодостаточным: куда положили — под то и подстроился.</p><p>Поддержка: современные браузеры. Если целитесь в старые — добавьте fallback через обычные media queries.</p><h2>6. «Случайный ID, что может пойти не так?» → crypto.getRandomValues</h2><p>Именно так рождаются баги:</p><p>Выглядит как «достаточно случайная» криптография с AliExpress — и работает, пока не перестаёт. Во-первых, всё зависит от реализации движка, мы не знаем, что происходит под капотом. Во-вторых, определённые паттерны вполне возможны, а при большом количестве ID вы фактически напрашиваетесь на коллизии.</p><p>К счастью, есть нативное решение. Не серебряная пуля, но crypto.getRandomValues заметно лучше: больше энтропии, нет странных паттернов, вероятность коллизий резко снижается. Браузер просто делает это правильно. А если вам нужен не произвольный набор байтов, а именно UUID, в современных браузерах есть ещё короче: crypto.randomUUID() выдаёт готовый UUID v4 одной строкой — тоже криптографически стойко и без ручной возни с байтами.</p><p>Поддержка: широкая.</p><h2>7. «Нам нужен модал» → dialog</h2><p>Больше не нужно ставить 12-килобайтную библиотеку ради модального окна, которое так любят пользователи. Нативный &lt;dialog&gt; даёт клавиатурную навигацию, фокус-трап и корректную работу со скринридерами прямо из коробки — всё то, что в самописных модалах обычно забывают или делают криво.</p><p>Поддержка: современные браузеры.</p><h2>8. «Голосовой ввод был бы крутой фичей» → Web Speech API</h2><p>Собирались ставить transformers.js, потому что понадобилось распознавание речи? У браузера для этого уже есть Web Speech API. Chromium-браузеры поддерживают его напрямую, Safari — через префиксную версию webkitSpeechRecognition (код ниже как раз это учитывает), в Firefox поддержки нет. Для демо и ассистивных фич — отлично, в проде лучше иметь запасной план на случай Firefox.</p><p>Поддержка: Chromium и Safari (через webkit-префикс), в Firefox до сих пор нет.</p><h2>9. «Не сломает ли это CSS?» → @supports</h2><p>Хотите выкатить backdrop-filter или :has() и при этом не сломать вёрстку в браузере, где фича ещё не поддерживается? Оборачиваем в @supports — и спокойны: браузер, который знает фичу, получит красивую версию, остальные — дефолтный fallback.</p><p>Поддержка: очень хорошая.</p><h2>Когда всё-таки нужна библиотека</h2><p>Библиотеки — это отлично, и иногда они действительно необходимы. Но иногда вы ставите зависимость на то, что браузер решил годы назад. Перед npm install полезно спросить себя (или поискать в MDN): «А браузер не умнее меня в этом вопросе?» Иногда ответ — да. И это нормально.</p><p>Источник: <a href="https://dev.to/sylwia-lask/9-things-youre-overengineering-the-browser-already-solved-them-o99">Sylwia Łask — 9 things you're overengineering: the browser already solved them</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>USB для разработчиков: как написать драйвер из пользовательского пространства</title>
      <link>https://tproger.ru/translations/usb-dlya-razrabotchikov-kak-napisat-drajver-iz-polzovatelskogo</link>
      <comments>https://tproger.ru/translations/usb-dlya-razrabotchikov-kak-napisat-drajver-iz-polzovatelskogo?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Евгений Стребков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/translations/usb-dlya-razrabotchikov-kak-napisat-drajver-iz-polzovatelskogo</guid>
      <description><![CDATA[<p>Написать USB-драйвер не сложнее, чем приложение с сокетами — без кода ядра. Endpoint как порты, 4 типа передачи, libusb API и Fastboot-клиент за 50 строк.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/translations/usb-dlya-razrabotchikov-kak-napisat-drajver-iz-polzovatelskogo">USB для разработчиков: как написать драйвер из пользовательского пространства</a>»</p>]]></description>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Переводы]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 09 Apr 2026 10:30:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>Вам вручили USB-устройство и попросили написать для него драйвер. Звучит страшно? На самом деле это не сложнее, чем написать приложение с сокетами. Не нужно лезть в ядро — всё можно сделать из пользовательского пространства с помощью библиотеки <a href="https://libusb.info">libusb</a>.</p><p>Это перевод <a href="https://werwolv.net/posts/usb_for_sw_devs">статьи</a> WerWolv — введение в USB для разработчиков, которые не работали с железом. Концепции объясняются через аналогию с сетевым программированием, а практический пример — реализация протокола Android Fastboot.</p><ul><li>USB-драйвер можно написать целиком в userspace через libusb — без кода ядра</li><li>Endpoint в USB — аналог порта в TCP: устройство сообщает, какие «порты» открыты и какой протокол используют</li><li>4 типа передачи: Control (конфигурация), Bulk (большие данные), Interrupt (низкая задержка), Isochronous (аудио/видео)</li><li>USB — master-slave: хост всегда инициирует обмен, устройство только отвечает</li><li>Практический пример: полноценный Fastboot-клиент на C++ за ~50 строк кода</li></ul><h2>USB — это как сеть</h2><p>Ключевая мысль статьи: USB можно понимать через аналогию с сетевым программированием. Endpoint — это порт, на который устройство принимает данные. Дескриптор устройства — аналог DNS, который говорит, кто это и какие «сервисы» доступны. Вам не нужно быть инженером встраиваемых систем, чтобы работать с USB — как не нужно быть сетевым специалистом, чтобы работать с сокетами.</p><h2>Шаг 1: узнаём, что за устройство</h2><p>При подключении устройства хост запрашивает у него информацию — это называется enumeration. На Linux это можно увидеть через lsusb:</p><p>Здесь 18d1 — Vendor ID (Google), 4ee0 — Product ID (загрузчик Pixel). Это уникальные идентификаторы, по которым хост находит нужный драйвер. VID выдаётся организацией USB-IF компаниям за деньги, PID назначает сам производитель.</p><p>Более подробный вывод:</p><p>Driver=[none] означает, что ОС не загрузила драйвер — именно то, что нужно для написания своего.</p><h2>Шаг 2: общаемся через libusb</h2><p>Библиотека <a href="https://libusb.info">libusb</a> позволяет общаться с USB-устройствами из пользовательского пространства. Она предоставляет универсальный драйвер и API для отправки запросов — без написания кода ядра.</p><p>Пример: обнаружение устройства по VID:PID и получение дескриптора через Control endpoint:</p><p>Каждое USB-устройство имеет Control endpoint на адресе 0x00 — это стандартизированная «точка входа», через которую хост получает дескрипторы (кто устройство, какие интерфейсы, какие endpoint'ы). Аналогия: это как DNS-запрос перед подключением.</p><h2>Endpoint'ы: порты USB-устройства</h2><p>Endpoint'ы — аналог портов на сетевом устройстве. Устройство описывает в дескрипторе, какие endpoint'ы доступны и какой протокол каждый из них использует. Четыре типа:</p><ul><li><b>Control</b> — один на устройство, адрес 0x00. Для конфигурации и запроса информации. Решает проблему курицы и яйца: чтобы узнать endpoint'ы, нужен endpoint — и это он</li><li><b>Bulk</b> — большие объёмы данных, низкий приоритет. Используется в Mass Storage (флешки), CDC-ACM (Serial over USB), RNDIS (Ethernet over USB)</li><li><b>Interrupt</b> — маленькие данные, минимальная задержка. Клавиатуры и мыши опрашиваются 1000+ раз в секунду через HID. Название обманчивое: реальных прерываний нет, хост просто очень часто опрашивает</li><li><b>Isochronous</b> — потоковые данные с гарантией тайминга. Аудио и видео, где задержка означает заикание</li></ul><p><b>IN и OUT:</b> USB — master-slave протокол, устройство никогда не говорит первым. IN = хост просит данные «к себе», OUT = хост отправляет данные «от себя». Направление кодируется в старшем бите адреса endpoint'а.</p><h2>Практика: Fastboot-клиент за 50 строк</h2><p>Протокол Fastboot (<a href="https://android.googlesource.com/platform/system/core/+/master/fastboot/README.md">документация</a>) предельно прост: хост отправляет строковую команду, устройство отвечает 4-символьным статусом + данные:</p><p>Реализация через libusb — отправляем команду на OUT Bulk endpoint, читаем ответ с IN Bulk endpoint:</p><p>Это всё. Два вызова libusb — и мы общаемся с загрузчиком Android без единой строки кода ядра.</p><p>Полный текст с исходным кодом: <a href="https://werwolv.net/posts/usb_for_sw_devs">USB for Software Developers</a>, WerWolv.</p>]]></content:encoded>
    </item>
    <item>
      <title>Почему ваш канал связи — не ваш. История о том, как паранойя заставила меня написать свой мессенджер с нуля.</title>
      <link>https://tproger.ru/articles/pochemu-vaw-kanal-svyazi---ne-vaw--istoriya-o-tom--kak-paranojya-zas</link>
      <comments>https://tproger.ru/articles/pochemu-vaw-kanal-svyazi---ne-vaw--istoriya-o-tom--kak-paranojya-zas?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[igrym]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/pochemu-vaw-kanal-svyazi---ne-vaw--istoriya-o-tom--kak-paranojya-zas</guid>
      <description><![CDATA[<p>Вернул UIN-ы из нулевых и завернул всё в PWA: как я писал свой мессенджер, балансируя между ностальгией и Highload</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/pochemu-vaw-kanal-svyazi---ne-vaw--istoriya-o-tom--kak-paranojya-zas">Почему ваш канал связи — не ваш. История о том, как паранойя заставила меня написать свой мессенджер с нуля.</a>»</p>]]></description>
      <category><![CDATA[Интернет]]></category>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[Безопасность]]></category>
      <category><![CDATA[iOS]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Мессенджер]]></category>
      <category><![CDATA[Приложение]]></category>
      <category><![CDATA[Песочница]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 04 Apr 2026 14:35:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>В какой-то момент я понял неприятную вещь: если твой канал связи живет по чужому настроению, политической погоде, сбою в чужом облаке или очередной внезапной любви регулятора к кнопке «запретить» — это не твой канал связи. Это аренда с правом внезапного выселения.</p><p>Мне эта модель быстро наскучила.</p><p>Поэтому я сделал то, что обычно делают люди с нездоровой смесью инженерной паранойи, скуки и профессиональной деформации: психанул и начал писать свой мессенджер.</p><p>Сразу зафиксируем рамки, чтобы не плодить фантомные ожидания:</p><p>- это не убийца Telegram;</p><p>- это не презентация для инвестора с KPI и growth loops;</p><p>- это не проповедь о том, как всем теперь жить.</p><p>Это мой личный цифровой бункер, моя песочница, мой учебный полигон и мой инженерный аттракцион. Я строю это прежде всего для себя: как резервный канал связи, как способ не зависеть от чужих решений и как честный highload-эксперимент, в котором можно не рассуждать про real-time в теории, а ловить его за горло руками.</p><p>И вот здесь началось смешное.</p><p>Я рассчитывал на бодрую гаражную поделку. Но эта штука оказалась заметно живее, упрямее и интереснее, чем я ожидал. Поэтому я и притащил ее на TProger. Не за аплодисментами. За самым ценным, что здесь умеют делать лучше многих: находить слабое место раньше, чем автор успевает самодовольно сказать «ну вроде едет».</p><h2>Что это вообще такое</h2><p>На текущем этапе это PWA-мессенджер.</p><p>Да, PWA. Да, осознанно. Да, я знаю весь стандартный набор комментариев про ограничения платформы, кривые пуши, фоновые ограничения и то, что</p><p>«настоящие пацаны пишут только натив». Можете не разогреваться, я это всё уже сам себе рассказал.</p><p>Почему все равно PWA:</p><p>- мне нужен был короткий путь от идеи до живого клиента;</p><p>- мне нужен был быстрый цикл выката без ритуальных танцев с</p><p>магазинами приложений;</p><p>- мне нужен был клиент, который можно быстро ломать, чинить,</p><p>пересобирать и снова кидать в бой;</p><p>- мне нужно было что заработает на разных платформах;</p><p>- мне нравится, что PWA живет в браузерной песочнице, а не лезет в телефон как хозяин квартиры.</p><p>У PWA есть реальные потолки:</p><p>- нет такой свободы по платформенным API, как у нативного клиента;</p><p>- фон, пуши и некоторые сценарии мобильной жизни работают хуже, чем</p><p>хотелось бы;</p><p>- нет нормальных VoIP-пушей (звонки работают только когда приложение</p><p>открыто), нет нормальной интеграции со списком вызовов телефона;</p><p>- по голой производительности натив его обгоняет.</p><p>И, да, Service Workers иногда ведут себя как подростки в пубертате, а iOS местами режет фоновую жизнь PWA так, будто лично обиделась на идею веб-клиента. Я в курсе. Выживаем с тем, что есть.</p><p>Но для моей задачи PWA дал главное: скорость эволюции. А в экспериментальном проекте это иногда важнее, чем стерильная идеология.</p><p>И да, работает эта штука подозрительно хорошо. Лучше, чем я ожидал, если честно.</p><h2>Зачем вообще писать еще один мессенджер, когда мир и так ими забит</h2><p>Потому что «и так забит» — плохой аргумент, когда существующие варианты в любой момент могут начать вести себя как полуживые.</p><p>Потому что я люблю контролировать инфраструктуру, а не молиться на чужую.</p><p>Потому что читать статьи про очереди, ретраи, доставку, порядок сообщений и борьбу с race condition — это теория. А написать свое, увидеть, где оно течет, и потом руками это затыкать — уже ремесло.</p><p>Потому что мне скучно.</p><p>Да, это тоже важная часть правды. На обычной работе мозг периодически начинает зевать от предсказуемости. А когда ты в одиночку пытаешься собрать живой real-time-сервис, где есть сессии, доставка сообщений, поиск, синхронизация состояния, очереди и weird cases мобильной сети —</p><p>то зевота быстро заканчивается.</p><p>То есть да: это учебный проект. Но из тех учебных проектов, которые в какой-то момент говорят: «всё, детский сад закончился, теперь давай как взрослые».</p><p>Где начинаются не разговоры про highload, а настоящая инженерная жизнь</p><p>Пока не собираешь такое сам, кажется, что мессенджер — это просто чатик.</p><p>Ну текстик, ну websocket, ну кнопка «отправить», господи. А потом начинается взрослая часть спектакля.</p><h3>1. Сообщение должно не просто уйти, а дойти правильно</h3><p>Самая скучная и самая дорогая ошибка — считать, что «отправил» значит</p><p>«доставил».</p><p>Нет. В реальной жизни между клиентом, сетью, сервером и хранилищем полно мест, где всё может стать интересно:</p><p>- клиент послал пакет, но сеть моргнула;</p><p>- сервер принял, но клиент не получил подтверждение;</p><p>- клиент решил, что ничего не дошло, и отправил повторно;</p><p>- внезапно у тебя уже не просто доставка, а идемпотентность,</p><p>дедупликация, подтверждения, ретраи и очень неприятные разборки с</p><p>дублями.</p><p>И это только один кусок.</p><h3>2. Порядок сообщений — штука гораздо более капризная, чем кажется</h3><p>Пользователь хочет простой магии: чтобы сообщения были в нужном порядке, статусы не врали, а история не прыгала, как пьяный курсор.</p><p>Инженерная реальность куда веселее:</p><p>- локальный optimistic update на offline-first клиенте хочет быть</p><p>быстрым;</p><p>- серверная истина хочет быть правильной;</p><p>- база хочет жить в своей временной линии;</p><p>- несколько устройств одного пользователя могут в это время смотреть на</p><p>мир разными глазами.</p><p>Как только начинаешь совмещать низкую задержку с внятной консистентностью, выясняется, что ты не «чатик пишешь», а торгуешься с физикой и распределенными состояниями.</p><h3>3. Race condition — это когда баг уже произошел, но ты еще не знаешь, где именно тебя унизили</h3><p>Race conditions — мой любимый жанр инженерного фольклора. Это когда всё прекрасно, пока ты смотришь. И ломается ровно в тот момент, когда отвлекся налить кофе.</p><p>Условно:</p><p>- один поток думает, что пользователь в онлайне;</p><p>- второй уже считает, что он отвалился;</p><p>- третий в это время честно пишет новое состояние;</p><p>- четвертый с невинным лицом отдает клиенту вчерашнюю правду.</p><p>А потом ты сидишь и объясняешь себе, почему в 99.7% случаев всё идеально, а в оставшихся 0.3% система внезапно начинает разговаривать голосами. А когда еще и пытаешься заставить работать реалтайм систему еще в кластере, то все сложности возводятся в квадрат.</p><h4>4. Любая «маленькая фича» очень быстро приходит за твоей архитектурой с ножом</h4><p>Захотел новую механику? Например, необычную резервацию UIN еще до регистрации? На бумаге выглядит забавно. На бэкенде начинается вечеринка:</p><p>- появляется состояние для еще не существующего пользователя;</p><p>- нужно резервировать ресурс так, чтобы его не вымели любопытные и жадные боты;</p><p>- нужно думать о TTL, освобождении, гонках, повторных запросах и кривом клиентском поведении;</p><p>- нужно следить, чтобы веселая фича не превратилась в атаку на собственную логику.</p><p>И вот так почти всё. В продуктовых презентациях фича может подаваться как «геймификация входа». В серверной реальности — «еще один слой боли, зато красиво».</p><h3>5. Поиск и история сообщений сначала кажутся простыми. Потом ты взрослеешь</h3><p>Пока данных мало, Postgres прощает тебе оптимизм. Потом история растет, индексы начинают намекать, что дружба дружбой, а latency по расписанию, и любой неаккуратный запрос внезапно становится личным конфликтом с CPU.</p><p>И тут выясняется, что в реальном мессенджере мало просто «хранить сообщения». Нужно еще:</p><p>- быстро искать;</p><p>- не ломать горячий путь доставки;</p><p>- не превращать сервер в печку под нагрузкой;</p><p>- думать наперед, где потом начнется горизонтальное масштабирование, а</p><p>где сначала будет боль, потом переписывание, потом снова боль.</p><p>Чтобы это не выглядело как очередная литература про «сложности highload», вот живой пример. Это кусок поиска по групповым сообщениям в моем бекенде: с проверкой доступа, выборкой только текстовых сообщений и сортировкой по релевантности.</p><p>Под этот запрос у меня лежит не молитва, а вполне конкретная опора: partial GIN index по выражению`(content-&gt;&gt;'text') gin_trgm_ops`.Иначе такая красота очень быстро превращает сервер в отопление стойки за счет тупого перебора JSONB.</p><p>А вот так тот же самый функционал очень часто пишут новички — вроде работает, пока данных смешно мало:</p><p>Проблема тут не в эстетике. Проблема в том, что верхний вариант ищет по нужному полю, умеет нормально ранжировать результат и опирается на индекс. Нижний часто уезжает в тяжелый scan по JSONB, ищет по строковому представлению всего объекта и под нагрузкой начинает жечь CPU просто потому, что автору было лень договориться с базой по-хорошему.</p><p>На реальном объеме истории в проде разница здесь может быть уже не в процентах, а на порядок и выше. То есть это очень быстро превращается не в «чуть-чуть быстрее», а в 10x+, а дальше всё зависит от размера истории, доли текстовых сообщений, партиций и того, насколько сильно вы любите мучить PostgreSQL.</p><p>И это еще сравнительно добрый пример. В по-настоящему наивной реализации люди (да часто и нейросети в руках новичков) иногда забывают не только про индекс и ранжирование, но и про нормальную проверку членства в чате — и тогда у тебя получается не просто медленный поиск, а еще и билет в секцию «как я сам себе устроил privacy-инцидент».</p><h3>6. Очереди, ретраи и backpressure — это не украшения, а повод спать чуть спокойнее</h3><p>В сетевом сервисе нельзя жить по принципу «ну отправили и ладно». Когда клиентов много, а сеть у части из них вечно в состоянии «между EDGE и молитвой», тебе нужны механизмы, которые умеют не только гнать трафик, но и не убивать систему собственным рвением.</p><p>То есть нужны:</p><p>- очереди (Kafka, или что вы там предпочитаете);</p><p>- повторные попытки (retry-логика);</p><p>- backpressure;</p><p>- вменяемая реакция на временную деградацию (graceful degradation);</p><p>- circuit breaker чтобы какой-нибудь маленький и вроде бы некритичный сервис не мог каскадно положить бы всю инфраструктуру;</p><p>- архитектура, которая умеет признавать, что мир не идеален.</p><p>Красиво это звучит только в статьях. В коде это обычно выглядит как серия компромиссов, которые ты принимаешь с лицом человека, только что подписавшего договор с хаосом. И все это когда у тебя нет сотен высокопроизводительных серверов в кармане, которые уже лишь за счет их мощности могли бы прощать многое.</p><h2>Интерфейс я подсматривал у Telegram. И да, специально</h2><p>Я не стал устраивать дизайнерский карнавал ради уникальности. У пользователя уже есть мышечная память. Она дороже моего самолюбия.</p><p>Если человек открывает новый мессенджер, он хочет быстро разобраться и написать сообщение. Ему не нужен артхаус-квест «найди кнопку отправки, автор так видит».</p><p>Поэтому UI здесь знакомый. Не потому что я беден фантазией, а потому что я делаю инструмент связи, а не выставку интерфейсного концептуализма.</p><figure><img src="https://media.tproger.ru/user-uploads/136500/2026-03-17/d42e785c-1951-43a6-b560-bc03d1f503a2.webp" alt="" /></figure><figure><img src="https://media.tproger.ru/user-uploads/136500/2026-03-17/7f9a0d02-7637-41c9-8ca1-408153554887.webp" alt="" /></figure><h2>Моя любимая инженерная шалость: UIN-рулетка до регистрации</h2><p>Тут я, конечно, немного похулиганил.</p><p>Я сделал резервацию UIN еще до этапа регистрации. То есть можно зайти, поймать красивый номер, а уже потом решить, нужен тебе вообще этот зоопарк или нет.</p><p>С человеческой стороны это фан, ностальгия и немного ICQ-вайба.</p><p>С серверной стороны это пачка вопросов:</p><p>- как хранить состояние для «почти-пользователя»;</p><p>- как не раздать красивые номера слишком щедро;</p><p>- как не дать мимо проходящему ботнету выгрести пул;</p><p>- как освобождать резервы и не плодить мусор;</p><p>- как не застрелить логическую целостность ради красивой игрушки.</p><p>С практической точки зрения миру, возможно, и не нужна эта фича. С инженерной — она просто слишком вкусная, чтобы я прошел мимо.</p><h2>Про безопасность — без дешевой магии и без сказок для инвестора</h2><p>Нет, я не изобретал свою криптографию. Я вообще считаю, что желание «сейчас быстренько придумаю свой защищенный протокол» должно автоматически активировать тревожную сирену. Да, создать защищенный протокол возможно, но это сложнее и дольше чем кажется из-за необходимости учета множества edge-cases; и в реальности сделанные на коленке протоколы чаще ненадежны, и, что еще хуже, об их уязвимостях могут знать лишь немногие пронырливые и порой не самые добросовестные люди.</p><p>Поэтому мой подход скучный, взрослый и не очень годится для красивых презентаций:</p><p>- транспорт закрыт современным TLS 1.3 (который на текущий момент, март 2026, взломать прямым криптографическим методом практически невозможно);</p><p>- клиент живет как PWA в браузерной песочнице, какая уже сама по себе имеет ряд уровней защиты;</p><p>- поверх этого я стараюсь не творить откровенной дичи;</p><p>Но важная оговорка, и она принципиальна: проект развивается быстро, агрессивно и временами как лаборатория под кофеином. Некоторые части еще могут отваливаться на ходу. Какие-то углы я уже вижу. Какие-то, уверен, еще нет.</p><p>Поэтому, несмотря на базово вменяемый современный уровень безопасности приложения, я не рекомендую сейчас доверять системе особо чувствительные данные.</p><p>Если вам нужна зрелая крепость для деликатной переписки — берите зрелые решения, которым вы уже доверяете.</p><p>Если вам нужен живой инженерный эксперимент, резервный канал связи и объект для вдумчивого краш-теста — вот он.</p><h2>Почему я вообще тащу это именно на TProger</h2><p>Потому что TProger — это место, где тексту мало быть наглым. Здесь за дерзость прощают только одно: если под ней есть мясо.</p><p>А у меня как раз тот случай, когда мне интереснее не «собрать лайки», а получить нормальную техническую реакцию:</p><p>- где архитектура выглядит спорно;</p><p>- где логика доставки сообщений может начать чудить;</p><p>- где PWA упрется в реальные ограничения платформы;</p><p>- где резервация UIN создает лишнюю поверхность атаки;</p><p>- где под нагрузкой начнет хрустеть то, что в одиночных тестах ведет себя прилично;</p><p>- где в протоколе, порядке событий, ретраях или кешировании я недооценил крайний случай.</p><p>Мне не нужен хор в духе «вау, круто».</p><p>Мне нужен ваш внутренний вредный сеньор. Тот самый тип, который открывает статью, хмыкает, а потом начинает мысленно разбирать чужую систему на части.</p><p>Вот ему я и пишу.</p><h2>Что я от вас хочу</h2><p>По сути — честной драки, но умной.</p><p>- Хотите проверить, как это переживает плохую сеть — отлично.</p><p>- Хотите посмотреть, как выглядит поведение в edge-cases — вообще прекрасно.</p><p>- Хотите понять, насколько легко читается логика протокола — давайте.</p><p>- Хотите найти баг в порядке сообщений, в кеше, в подтверждениях, в резервации UIN, в клиентском поведении — тем более.</p><p>Только давайте без детского жанра «я что-то молча сломал и ушел сиять в закат». Если найдете слабое место, баг, странность, дыру, подозрительный сценарий или красивый способ заставить систему вести себя не так, как я планировал, — пишите.</p><p>Мне это полезнее, чем аплодисменты.</p><p>И да: я не заявляю, что построил новый и единственно верный мессенджер.</p><p>Я заявляю другое. Я собрал свой рабочий велосипед, уже довольно злой и живой, и мне интересно, где именно TProger попробует вставить ему отвертку в спицы, и на какой секунде этот велосипед упадет.</p><p>Что можно делать прямо сейчас</p><p>- Если вы параноик или устали от мейнстрима и навязанных решений — держите это как запасной канал связи.</p><p>- Если вы соскучились по временам красивых UIN — приходите ловить UIN-номер.</p><p>- Если вы любите sniff, разбор трафика и сетевые игры — смотрите что идет по проводу.</p><p>- Если у вас профессиональная привычка первым делом искать edge-cases — вот, собственно, ради вас всё это и принесено.</p><p>И если что-то положите, вскроете или красиво разберете — пришлите детали. Я не обидчивый. Я, строго говоря, именно ради этого и открыл двери.</p><h2>Что дальше</h2><p>Планы без корпоративной шелухи, но вполне понятные:</p><p>- дальше допиливаю PWA-версию;</p><p>- нативные Android и iOS-клиенты — в планах, но пока не в приоритете;</p><p>- клиентскую часть, вероятно, позже открою, когда там станет меньше творческого барокко;</p><p>- идея с SDK / библиотекой для кастомных клиентов мне нравится отдельно: если люди захотят писать свои оболочки, это будет уже совсем красивый уровень игры.</p><p>Исходники сейчас закрыты. Не потому что я жадничаю или прячу священный секретный соус, а потому что местами там еще такой авторский лофт из боевых решений, экспериментов, временных костылей и честной инженерной импровизации, что сначала я предпочту сам это немного причесать.</p><h2>Итог</h2><p>На сегодня это экспериментальный PWA-мессенджер, который родился из упрямства, паранойи, скуки и любви к инженерным задачам, от которых нормальные люди обычно стараются держаться подальше.</p><p>Я делал его в первую очередь для себя. Но он уже дорос до стадии, когда его интересно не только строить, но и показывать наружу.</p><p>Если будете пробовать — лучше сразу добавить его на домашний экран (PWA так устанавливается). Так приложению жить будет заметно удобнее: платформа позволит заработать пуш-уведомлениям, появится нормальное кеширование, а оффлайн-режим перестанет быть декоративной надписью.</p><p>Если хотите просто еще один канал связи — пожалуйста.</p><p>Если хотите посмотреть и проверить, насколько крепок мой цифровой эксперимент, — тем более пожалуйста.</p><p>Если хотите проверить заодно и собственные навыки на живой системе, которая не притворяется идеальной, — вот, собственно, и весь смысл этой публикации.</p><p>Добро пожаловать.</p><p>Посмотрим, кто кого утомит первым: вы — мой сервер, я — ваши попытки его удивить, или реальность — нас обоих.</p><p><b>PS:</b></p><p>Меня там можно найти по нику IGRYM или по UIN 10001. Также есть внутренняя группа для первых пользователей (Early Birds, доступна на экране списка чатов через «+» вверху экрана)</p><p>Ссылки:</p><p>- Приложение: https://beta.plumb-app.ru/</p><p>- Телеграм-канал с новостями проекта: https://t.me/plumb_channel</p><p>- Телеграм-группа обсуждения: https://t.me/plumb_group</p>]]></content:encoded>
    </item>
    <item>
      <title>LocalStack стал платным — MiniStack заменяет его бесплатно: 33 AWS-сервиса, реальный Postgres и 2 секунды на старт</title>
      <link>https://tproger.ru/news/localstack-stal-platnym---ministack-zamenyaet-ego-besplatno--33-a</link>
      <comments>https://tproger.ru/news/localstack-stal-platnym---ministack-zamenyaet-ego-besplatno--33-a?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Алексей Михайлишин]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/localstack-stal-platnym---ministack-zamenyaet-ego-besplatno--33-a</guid>
      <description><![CDATA[<p>MiniStack эмулирует 33 AWS-сервиса на одном порте с реальным Postgres, Redis и Docker. Запуск за 2 секунды, 30 МБ RAM, MIT-лицензия. Полная замена платного LocalStack.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/localstack-stal-platnym---ministack-zamenyaet-ego-besplatno--33-a">LocalStack стал платным — MiniStack заменяет его бесплатно: 33 AWS-сервиса, реальный Postgres и 2 секунды на старт</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 01 Apr 2026 07:15:20 GMT</pubDate>
      <content:encoded><![CDATA[<p><a href="https://localstack.cloud/">LocalStack</a> долгое время был стандартом для локальной эмуляции AWS-сервисов — бесплатный, удобный, с поддержкой S3, SQS, DynamoDB и десятков других API. Но в начале 2026 года базовые сервисы переехали за пейволл: даже S3 и Lambda теперь требуют платной подписки от $35/мес.</p><p>Разработчик <b>Nahuel Nucera</b> решил эту проблему: <a href="https://github.com/Nahuel990/ministack">MiniStack</a> — полностью бесплатная замена LocalStack с открытым исходным кодом, которая эмулирует 33 AWS-сервиса на одном порте. И, в отличие от LocalStack, запускает <b>настоящие</b> базы данных и контейнеры вместо мок-заглушек.</p><p><b>MiniStack</b> — бесплатная open-source замена LocalStack (MIT-лицензия)</p><p>33 AWS-сервиса на одном порте — S3, SQS, DynamoDB, Lambda, IAM, RDS, ElastiCache, ECS и другие</p><p>Реальная инфраструктура: RDS поднимает настоящий Postgres, ElastiCache — настоящий Redis, ECS — Docker-контейнеры</p><p>Запуск за 2 секунды, 30 МБ RAM в простое (vs 30 секунд и 500 МБ у LocalStack)</p><p>Drop-in совместимость с boto3, AWS CLI, Terraform, CDK, Pulumi</p><h2>Почему LocalStack стал платным</h2><p>LocalStack сменил лицензию с Apache 2.0 на <b>Business Source License</b> (BSL) и перенёс ключевые сервисы — S3, SQS, Lambda, IAM, Cognito, EC2 — в платный тир. Бесплатная версия <a href="https://localstack.cloud/pricing/">LocalStack Community</a> фактически перестала покрывать базовые сценарии локальной разработки.</p><p>Для коммерческих команд LocalStack Pro стоит от $35/мес на разработчика. Для опенсорс-проектов и индивидуальных разработчиков это создало вакуум — и MiniStack его заполнил.</p><h2>Что умеет MiniStack</h2><p>MiniStack — это один Python ASGI-сервер, который эмулирует AWS API на порте 4566. Ваши существующие boto3-клиенты, Terraform-провайдеры, CDK-стеки и AWS CLI работают без изменений — достаточно указать endpoint.</p><h3>33 поддерживаемых сервиса</h3><ul><li><b>Хранилище:</b> S3 (с версионированием, Object Lock, CORS, lifecycle), EBS, EFS</li><li><b>Очереди и события:</b> SQS (FIFO + DLQ), SNS (fanout в SQS и Lambda), EventBridge, Kinesis, Firehose</li><li><b>Базы данных:</b> DynamoDB (TTL, транзакции), RDS (реальный Postgres/MySQL), ElastiCache (реальный Redis), Athena (реальный SQL через DuckDB)</li><li><b>Вычисления:</b> Lambda (реальное исполнение Python, warm pool), ECS (реальные Docker-контейнеры), Step Functions, EMR</li><li><b>Сеть и безопасность:</b> EC2 (instances, VPC, subnets, security groups), ALB/ELBv2, Route53, Cognito, IAM, STS</li><li><b>Конфигурация:</b> SSM Parameter Store, Secrets Manager, CloudFormation, Glue Catalog</li></ul><h3>Реальная инфраструктура, а не заглушки</h3><p>Главное отличие MiniStack — он поднимает <b>настоящие</b> сервисы там, где это важнее всего:</p><ul><li><b>RDS</b> — вызов CreateDBInstance с engine=postgres запускает реальный PostgreSQL-контейнер и возвращает настоящий host:port</li><li><b>ElastiCache</b> — реальный Redis-контейнер, а не in-memory имитация</li><li><b>ECS</b> — реальные Docker-контейнеры</li><li><b>Athena</b> — реальный SQL через DuckDB (при наличии)</li></ul><p>Это принципиально отличается от подхода LocalStack, который во многих случаях использует стабы — ответы «всё ОК» без реального выполнения.</p><h2>Сравнение с LocalStack</h2><p>Ключевые метрики рядом:</p><ul><li><b>Запуск:</b> MiniStack ~2 сек vs LocalStack ~15–30 сек</li><li><b>RAM в простое:</b> MiniStack ~30 МБ vs LocalStack ~500 МБ</li><li><b>Docker-образ:</b> MiniStack 150 МБ vs LocalStack ~1 ГБ</li><li><b>Лицензия:</b> MiniStack MIT vs LocalStack BSL (ограниченная) / Proprietary ($35+/мес)</li><li><b>RDS, ElastiCache, ECS:</b> MiniStack — реальные контейнеры бесплатно vs LocalStack — только в Pro</li></ul><p>При этом MiniStack совместим с тем же API: endpoint-url, boto3, Terraform, CDK — всё работает без изменения кода.</p><h2>Как начать</h2><p>Три способа установки:</p><p>Проверка работы:</p><p>Для Python-проектов:</p><h2>Выводы</h2><p>MiniStack не претендует на полное покрытие всех AWS-сервисов — это задача LocalStack Pro. Но для типичной локальной разработки (S3 + SQS + DynamoDB + Lambda + IAM + RDS) он закрывает 90% потребностей при нулевой стоимости, мгновенном запуске и MIT-лицензии.</p><p>Проект активно развивается (947 звёзд на GitHub, версия 1.0.7) и уже привлёк внимание на <a href="https://news.ycombinator.com/item?id=47593285">Hacker News</a> (227+ баллов). Если вы искали замену LocalStack после перехода на платную модель — попробуйте.</p><p>Ссылки: <a href="https://github.com/Nahuel990/ministack">GitHub</a> | <a href="https://ministack.org/">Сайт</a> | <a href="https://pypi.org/project/ministack/">PyPI</a> | <a href="https://hub.docker.com/r/nahuelnucera/ministack">Docker Hub</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Как подключить ChatGPT, Claude и Gemini через один API: пошаговый гайд</title>
      <link>https://tproger.ru/articles/kak-podklyuchit-chatgpt--claude-i-gemini-cherez-odin-api--powagovy</link>
      <comments>https://tproger.ru/articles/kak-podklyuchit-chatgpt--claude-i-gemini-cherez-odin-api--powagovy?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Дима Дмитриев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-podklyuchit-chatgpt--claude-i-gemini-cherez-odin-api--powagovy</guid>
      <description><![CDATA[<p>Пошаговый гайд: подключаем ChatGPT, Claude 4.6 и Gemini через один API-роутер. Реальный код на Python и Node.js, настройка fallback и мониторинга. Без переписывания SDK под каждую модель.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-podklyuchit-chatgpt--claude-i-gemini-cherez-odin-api--powagovy">Как подключить ChatGPT, Claude и Gemini через один API: пошаговый гайд</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[OpenAI]]></category>
      <category><![CDATA[Промпты]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 01 Apr 2026 05:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Если вы уже работаете с LLM в проде, то наверняка сталкивались с этим: OpenAI лёг в три ночи, а у вас дедлайн. Или кончился бюджет на GPT, и надо срочно переключиться на Gemini. Или клиент хочет Claude, а весь CI/CD заточен под OpenAI SDK.</p><p>В итоге вы держите три разных API-ключа, три разных SDK, три разные схемы биллинга — и каждое переключение стоит нескольких часов рефакторинга.</p><p>В этой статье разберём, как решить это через один API-роутер: подключим GPT-5.4, Claude Sonnet 4.6 и Gemini 3.1 Pro через одну точку входа без переписывания кода под каждую модель. Статья для тех, кто уже работал с LLM API и хочет выстроить нормальную инфраструктуру.</p><h2>Почему три отдельных API — это боль в проде</h2><p>По факту всё просто: подключаешь OpenAI, пишешь код, всё работает. На практике, как только вы начинаете масштабироваться или хотите попробовать другую модель, появляются три проблемы.</p><h2>Разные форматы запросов и ответов</h2><p>У каждого провайдера — свой SDK и своя структура данных. Посмотрите, как выглядит один и тот же запрос для трёх разных API.</p><p>Python:</p><p>​​Три разных SDK, разные структуры ответа и способа обработки ошибок. Если вы хотите добавить в проект вторую модель — значит нужно переписывать логику вызовов и парсинг ответов с нуля.</p><h2>Vendor lock-in и зависимость от аптайма одного провайдера</h2><p>OpenAI, Anthropic и Google — три разные компании с тремя разными инфраструктурами. Если один провайдер падает, ваш продукт перестаёт отвечать. Запросы возвращают ошибку, токены не тратятся — но пользователи видят сломанный интерфейс. Без резервной модели вы просто ждёте, пока провайдер починится.</p><p>Кроме аптайма, у каждого провайдера своя операционная специфика — и она влияет на то, как вы строите интеграцию:</p><figure><img src="https://media.tproger.ru/user-uploads/99633/2026-03-31/f2616213-4f24-41c5-b096-96faf7a2a40b.webp" alt="" /></figure><p>Мы знаем, что авторизация у всех разная — значит, для каждого провайдера нужен свой способ передачи ключа. Rate limit у Anthropic в 10 раз ниже, чем у OpenAI на том же тарифе — если вы пишете балансировщик нагрузки вручную, это нужно учитывать. Биллинг у Google завязан на Google Cloud — отдельный аккаунт, счета и бухгалтерия.</p><p>Именно это и решает роутер: один API-ключ, одна схема авторизации, один дашборд.</p><h2>Что такое LLM API-роутер и как он работает</h2><p>LLM API-роутер — это прокси-слой между вашим приложением и несколькими LLM-провайдерами. Вы отправляете один запрос в едином формате, роутер определяет, какую модель использовать, и возвращает ответ в стандартизированном виде.</p><figure><img src="https://media.tproger.ru/user-uploads/99633/2026-03-31/702b92e8-fa26-4c14-b2d4-1efbeba4fe96.webp" alt="" /></figure><p>Хороший роутер умеет:</p><ul><li>Fallback: если основная модель недоступна или превышен rate limit — автоматически переключает на запасную</li><li>Load balancing: распределяет запросы между провайдерами по настраиваемым правилам</li><li>Логирование: сохраняет все запросы/ответы, latency, стоимость в одном месте</li><li>Кеширование: не тратит токены на идентичные запросы</li><li>Unified billing: видите общие расходы на LLM в одном дашборде</li></ul><p>Роутер не нужен, если у вас один провайдер, небольшой объём запросов и нет требований к отказоустойчивости. Прямое подключение к API — проще и без лишних телодвижений.</p><p>Роутер нужен в трёх случаях: продукт должен работать даже когда один провайдер падает, вы сравниваете качество разных моделей на реальных задачах, или несколько команд используют разные модели и нужна единая точка учёта расходов.</p><p>Один из таких инструментов —<a href="https://routerai.ru/"> RouterAI.ru</a>, российский сервис, который поддерживает OpenAI-совместимый формат запросов. Это значит: меняете base_url в вашем существующем коде — и получаете доступ к ChatGPT, Claude и Gemini через один API-ключ.</p><h2>Единый баланс и оплата в рублях</h2><p>Отдельное преимущество для российских команд: RouterAI держит один баланс для всех моделей сразу. Пополнили один раз — запросы идут к любому провайдеру из этого баланса. Не нужно держать отдельные счета в OpenAI, Anthropic и Google Cloud и следить, чтобы на каждом хватало средств. Оплата в рублях — без конвертации и без привязки иностранной карты.</p><h2>Подключение через один API: пошаговый гайд</h2><p>Для примеров используем Python 3.10+ и Node.js 18+, проверяйте у себя, а если заметили ошибку — обязательно напишите в комментариях, чтобы предупредить других читателей.</p><h2>Шаг 1. Регистрация и получение API-ключа</h2><p>Переходите на<a href="https://routerai.ru/"> routerai.ru</a>, регистрируетесь, в личном кабинете создаёте API-ключ. Выглядит как стандартный токен в формате rtr-....</p><p>Сохраните ключ в переменную окружения — не храните его в коде:</p><p>export ROUTERAI_API_KEY="rtr-ваш-ключ"</p><h2>Шаг 2. Базовый запрос — три модели, один формат</h2><p>RouterAI поддерживает OpenAI-совместимый формат, поэтому нужно поменять только base_url и api_key — остальной код не трогаете.</p><p>Python:</p><h2>Шаг 3. Таблица доступных моделей</h2><p>Названия model-id, которые принимает RouterAI:</p><figure><img src="https://media.tproger.ru/user-uploads/99633/2026-03-31/140bd8a7-9aff-4a55-b23a-80bda4831263.webp" alt="" /></figure><p>Актуальный список моделей — в<a href="https://routerai.ru/models"> документации RouterAI</a>. Провайдеры обновляют lineup несколько раз в год.</p><h2>Шаг 4. Настройка стриминга</h2><p>Стриминг работает так же, как в нативном OpenAI SDK:</p><h2>Шаг 5. Системный промпт и параметры генерации</h2><h2>Реальный кейс: мультимодельный бот с fallback за 30 минут</h2><p>Покажем реальный сценарий: бот, который сначала пробует GPT-5.4, при ошибке переключается на Claude Sonnet 4.6, логирует все запросы и считает стоимость.</p><p>Запускаете скрипт — он пробует GPT-5.4. Если там rate limit или ошибка — автоматически берёт Claude Sonnet 4.6. Если и там проблема — Gemini 3.1 Pro. Всё логируется с временными метками.</p><p>Для прода можно вынести MODEL_CHAIN в конфиг и менять приоритет моделей без перезапуска сервиса. RouterAI также предоставляет<a href="https://routerai.ru/"> дашборд</a> с агрегированной статистикой по всем запросам: какая модель использовалась, сколько токенов потрачено, как менялась latency по времени.</p><h2>Подводные камни при работе с роутером</h2><p>Прежде чем переводить прод на роутер, стоит знать о нескольких нюансах.</p><h2>Разные контекстные окна — нельзя просто взять и переключить</h2><p>GPT-5.4, Claude Sonnet 4.6 и Gemini 3.1 Pro — все трое держат по 1M токенов, но DeepSeek V3.2 ограничен 164K, а Grok 4 — 256K. Если fallback-цепочка включает эти модели, длинный контекст просто обрежется или вернётся ошибка. Проверяйте длину промпта перед переключением.</p><h2>Разное поведение моделей на одинаковые промпты</h2><p>Claude Sonnet 4.6 строже следует системному промпту, GPT-5.4 гибче интерпретирует инструкции, Gemini 3.1 Pro хорошо работает с мультимодальными задачами и таблицами. Если у вас сложный системный промпт — при переключении модели ответ может заметно отличаться по стилю и формату. Это нормально, но стоит учитывать при тестировании.</p><h2>Роутер добавляет накладные расходы</h2><p>Любой прокси-слой — это дополнительный расход. На практике это 20–80ms в зависимости от географии. Если ваш продукт чувствителен к latency (например, голосовой интерфейс), протестируйте задержки на реальной нагрузке до деплоя.</p><h2>Ценообразование: роутер не всегда дороже</h2><p>Роутер добавляет наценку к базовой стоимости токенов — это факт. Но итоговая цена зависит от модели. На китайских моделях вроде DeepSeek V3.2 RouterAI предлагает цены крупных клиентов со скидками — и выходит дешевле, чем если подключаться к тем же моделям напрямую по стандартному тарифу. На флагманских моделях OpenAI и Anthropic разница будет в пользу прямого подключения при больших объёмах. Считайте по конкретным моделям и своему объёму запросов — универсального ответа нет.</p><h2>Роутер умножает rate limits, а не делит их</h2><p>Это одно из главных преимуществ, которое неочевидно с первого взгляда. RouterAI подключается к каждому провайдеру через несколько точек одновременно — и тот же Claude Sonnet 4.6 может уйти в Anthropic напрямую, через Google Cloud или через Amazon Bedrock. Суммарный rate limit получается значительно выше, чем при прямом подключении на стандартном тарифе.</p><h2>В итоге</h2><p>Мы подключили GPT-5.4, Claude Sonnet 4.6 и Gemini 3.1 Pro через единый API в OpenAI-совместимом формате. Ключевой момент: смена base_url и api_key в существующем коде — и вы получаете доступ к трём провайдерам без переписывания SDK.</p><p>Роутер оправдан, когда:</p><ul><li>нужна отказоустойчивость и автоматический fallback</li><li>вы сравниваете качество разных моделей на реальных задачах</li><li>хотите управлять расходами из одного места</li></ul><p>Попробовать RouterAI.ru можно бесплатно — на сайте есть тестовый тариф. Документация с актуальным списком моделей и примерами интеграций — на<a href="https://routerai.ru/"> routerai.ru</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Что такое REST API простыми словами: принципы, методы и примеры</title>
      <link>https://tproger.ru/articles/chto-takoe-rest-api-prostymi-slovami--principy--metody-i-primery</link>
      <comments>https://tproger.ru/articles/chto-takoe-rest-api-prostymi-slovami--principy--metody-i-primery?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Алексей Михайлишин]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/chto-takoe-rest-api-prostymi-slovami--principy--metody-i-primery</guid>
      <description><![CDATA[<p>REST API — архитектурный стиль для взаимодействия клиента и сервера через HTTP. Разбираем 6 принципов REST, методы GET, POST, PUT, DELETE и CRUD на примерах.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/chto-takoe-rest-api-prostymi-slovami--principy--metody-i-primery">Что такое REST API простыми словами: принципы, методы и примеры</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 28 Mar 2026 15:28:57 GMT</pubDate>
      <content:encoded><![CDATA[<p>Вы наверняка сталкивались с REST API, даже если не знали об этом. Каждый раз, когда мобильное приложение загружает ленту новостей, а сайт показывает прогноз погоды — за кулисами работает именно REST API. Разберёмся, как устроена эта технология и почему она стала стандартом веб-разработки.</p><p><b>REST API</b> (Representational State Transfer Application Programming Interface) — это архитектурный стиль взаимодействия между клиентом и сервером через протокол HTTP. Клиент отправляет запрос на определённый URL, а сервер возвращает данные — чаще всего в формате JSON. REST не является протоколом или стандартом: это набор архитектурных принципов, которым следует разработчик при проектировании API.</p><p>— REST API — это архитектурный стиль, а не протокол. Он основан на 6 принципах, предложенных Роем Филдингом в 2000 году</p><p>— Для работы с ресурсами используются HTTP-методы: GET (чтение), POST (создание), PUT (обновление), DELETE (удаление)</p><p>— Каждый ресурс имеет уникальный URL — эндпоинт, к которому обращается клиент</p><p>— REST проще SOAP и гибче GraphQL — именно поэтому более 80% публичных API используют REST</p><p>— JSON не обязателен — REST может возвращать XML, HTML или даже обычный текст</p><h2>Что означает REST — 6 принципов архитектуры</h2><p>Термин REST ввёл Рой Филдинг в своей докторской диссертации в 2000 году. Он описал 6 архитектурных ограничений, которым должна соответствовать система, чтобы считаться RESTful.</p><ol><li><b>Клиент-сервер</b> — клиент и сервер разделены. Клиент отвечает за интерфейс, сервер — за хранение данных и бизнес-логику. Это позволяет развивать их независимо</li><li><b>Отсутствие состояния (Stateless)</b> — каждый запрос содержит всю информацию, необходимую для его обработки. Сервер не хранит контекст между запросами</li><li><b>Кэширование</b> — ответы сервера могут быть помечены как кэшируемые. Это снижает нагрузку и ускоряет работу клиента</li><li><b>Единообразный интерфейс</b> — все ресурсы доступны через стандартные HTTP-методы и имеют предсказуемые URL. Это главное отличие REST от других подходов</li><li><b>Многослойная архитектура</b> — между клиентом и сервером могут находиться промежуточные слои: балансировщики, прокси, кэш-серверы. Клиент не знает, общается ли он напрямую с сервером</li><li><b>Код по запросу (необязательно)</b> — сервер может передавать клиенту исполняемый код, например JavaScript. Этот принцип — единственный необязательный из шести</li></ol><h2>HTTP-методы — GET, POST, PUT, DELETE</h2><p>REST API использует стандартные HTTP-методы для операций над ресурсами. Каждый метод соответствует определённому действию — это называется <b>CRUD</b> (Create, Read, Update, Delete).</p><h3>GET — получение данных</h3><p>Запрашивает ресурс с сервера. Не изменяет данные — только читает.</p><p>Ответ сервера:</p><h3>POST — создание ресурса</h3><p>Создаёт новый ресурс на сервере. Данные передаются в теле запроса.</p><h3>PUT — обновление ресурса</h3><p>Полностью заменяет ресурс новыми данными. Если нужно обновить одно поле — используют PATCH.</p><h3>DELETE — удаление ресурса</h3><p>Удаляет ресурс с сервера.</p><p>Сервер обычно возвращает статус 204 No Content — данные удалены, тело ответа пустое.</p><h2>Как выглядит REST API на практике — пример CRUD</h2><p>Представим, что мы проектируем API для управления задачами (to-do list). Вот как будет выглядеть набор эндпоинтов:</p><p>Обратите внимание на структуру URL. Ресурс — это существительное во множественном числе (/tasks), а действие определяется HTTP-методом, а не URL. Именно поэтому /api/deleteTask — это плохой REST, а DELETE /api/tasks/1 — хороший.</p><p>Пример запроса на создание задачи и ответа сервера:</p><p>Сервер вернул статус 201 Created и добавил поля id и createdAt, которые генерируются автоматически.</p><h2>REST vs SOAP vs GraphQL</h2><p>REST — не единственный способ построить API. Сравним его с двумя другими популярными подходами.</p><p><b>SOAP</b> (Simple Object Access Protocol) — протокол, разработанный Microsoft в 1998 году. Использует XML для запросов и ответов, требует строгую схему (WSDL). SOAP популярен в корпоративных системах и банках, где важна формальная спецификация и встроенная безопасность (WS-Security). Но он значительно тяжелее REST: XML-конверты, обязательные заголовки, сложная настройка.</p><p><b>GraphQL</b> — язык запросов от Facebook* (2015). Клиент сам описывает, какие данные ему нужны, в одном запросе. Это решает проблему over-fetching (когда REST возвращает лишние поля) и under-fetching (когда нужно несколько запросов). Но GraphQL сложнее в реализации и отладке, а кэширование требует дополнительных усилий.</p><p><i>* Meta признана экстремистской и запрещена в России</i></p><ul><li><b>REST</b> — простой, стандартный, подходит для большинства задач. Лучший выбор, если API публичное или команда небольшая</li><li><b>SOAP</b> — для корпоративных интеграций с жёсткими требованиями к безопасности и контрактам</li><li><b>GraphQL</b> — для сложных клиентов, которым нужна гибкость в выборке данных (мобильные приложения, SPA)</li></ul><h2>Заключение</h2><p>REST API — это фундамент современной веб-разработки. Его сила — в простоте: стандартные HTTP-методы, понятные URL, предсказуемые ответы. Именно поэтому REST используют такие компании, как Google, GitHub, Stripe и тысячи других.</p><p>Если вы только начинаете работу с API — попробуйте отправить GET-запрос к любому публичному API (например, <a href="https://api.github.com/users/octocat">GitHub API</a>) через curl или Postman. Это лучший способ понять, как всё работает на практике.</p><p>Чтобы глубже разобраться во взаимодействии клиента и сервера, рекомендуем нашу статью <a href="https://tproger.ru/explain/frontend-backend-interaction">Frontend и Backend: как они взаимодействуют</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Бесплатные API для LLM: полный список провайдеров с постоянным free-тарифом</title>
      <link>https://tproger.ru/articles/besplatnye-api-dlya-llm--polnyj-spisok-provajderov-s-postoyannym-f</link>
      <comments>https://tproger.ru/articles/besplatnye-api-dlya-llm--polnyj-spisok-provajderov-s-postoyannym-f?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Алексей Михайлишин]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/besplatnye-api-dlya-llm--polnyj-spisok-provajderov-s-postoyannym-f</guid>
      <description><![CDATA[<p>Google Gemini, Mistral, Groq, Cerebras, OpenRouter и другие: полный список провайдеров с бесплатным доступом к API языковых моделей.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/besplatnye-api-dlya-llm--polnyj-spisok-provajderov-s-postoyannym-f">Бесплатные API для LLM: полный список провайдеров с постоянным free-тарифом</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Новости]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 27 Mar 2026 15:40:57 GMT</pubDate>
      <content:encoded><![CDATA[<p>Собрали актуальный список провайдеров, которые дают <b>бесплатный доступ</b> к API языковых моделей на постоянной основе. Никаких пробных периодов, временных кредитов или промоакций — только постоянные free-тарифы. Все эндпоинты совместимы с OpenAI SDK.</p><p><b>RPM</b> = запросов в минуту, <b>RPD</b> = запросов в день. Список быстро меняется — актуальную версию смотрите на <a href="https://www.reddit.com/r/LLM/comments/1s3d30h/awesome_free_llm_apis/">Reddit</a>.</p><h2>Провайдеры с собственными моделями</h2><ul><li><a href="https://ai.google.dev/"><b>Google Gemini</b></a> — Gemini 2.5 Pro, Flash, Flash-Lite + ещё 4 модели. <i>10 RPM, 20 RPD</i></li><li><a href="https://cohere.com/"><b>Cohere</b></a> — Command A, Command R+, Aya Expanse 32B + ещё 9. <i>20 RPM, 1K запр./мес</i></li><li><a href="https://mistral.ai/"><b>Mistral AI</b></a> — Mistral Large 3, Small 3.1, Ministral 8B + ещё 3. <i>1 запр./с, 1B ток./мес</i></li><li><a href="https://z.ai/"><b>Zhipu AI</b></a> — GLM-4.7-Flash, GLM-4.5-Flash, GLM-4.6V-Flash. <i>Лимиты не документированы</i></li></ul><h2>Инференс-платформы</h2><ul><li><a href="https://github.com/marketplace/models"><b>GitHub Models</b></a> — GPT-4o, Llama 3.3 70B, DeepSeek-R1 + др. <i>10–15 RPM, 50–150 RPD</i></li><li><a href="https://build.nvidia.com/"><b>NVIDIA NIM</b></a> — Llama 3.3 70B, Mistral Large, Qwen3 235B + др. <i>40 RPM</i></li><li><a href="https://console.groq.com/"><b>Groq</b></a> — Llama 3.3 70B, Llama 4 Scout, Kimi K2 + ещё 17. <i>30 RPM, 14 400 RPD</i></li><li><a href="https://cerebras.ai/"><b>Cerebras</b></a> — Llama 3.3 70B, Qwen3 235B, GPT-OSS-120B + ещё 3. <i>30 RPM, 14 400 RPD</i></li><li><a href="https://developers.cloudflare.com/workers-ai/"><b>Cloudflare Workers AI</b></a> — Llama 3.3 70B, Qwen QwQ 32B + ещё 47. <i>10K нейронов/день</i></li><li><a href="https://llm7.io/"><b>LLM7.io</b></a> — DeepSeek R1, Flash-Lite, Qwen2.5 Coder + ещё 27. <i>30 RPM (120 с токеном)</i></li><li><a href="https://kluster.ai/"><b>Kluster AI</b></a> — DeepSeek-R1, Llama 4 Maverick, Qwen3-235B + 2. <i>Лимиты не документированы</i></li><li><a href="https://openrouter.ai/"><b>OpenRouter</b></a> — DeepSeek R1, Llama 3.3 70B, GPT-OSS-120B + ещё 29. <i>20 RPM, 50 RPD</i></li><li><a href="https://huggingface.co/"><b>Hugging Face</b></a> — Llama 3.3 70B, Qwen2.5 72B, Mistral 7B + много др. <i>$0,10/мес в кредитах</i></li></ul><h2>На что обратить внимание</h2><ul><li>Самый щедрый по лимитам — <b>Mistral AI</b>: 1 миллиард токенов в месяц бесплатно, включая Mistral Large 3</li><li>Самый быстрый — <b>Groq</b> и <b>Cerebras</b>: оба дают 14 400 запросов/день на специализированном железе</li><li>Самый разнообразный — <b>Cloudflare Workers AI</b>: 50+ моделей, но лимит в нейронах, а не запросах</li><li>Для прода эти лимиты маловаты, но для прототипов, учебы и пет-проектов — более чем достаточно</li></ul><p>Источник: <a href="https://www.reddit.com/r/LLM/comments/1s3d30h/awesome_free_llm_apis/">r/LLM — Awesome Free LLM APIs</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Headless WordPress: архитектура с Next.js, GraphQL и Cloudflare</title>
      <link>https://tproger.ru/articles/headless-wordpress--arhitektura-s-next-js--graphql-i-cloudflare</link>
      <comments>https://tproger.ru/articles/headless-wordpress--arhitektura-s-next-js--graphql-i-cloudflare?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Александр Пехота]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/headless-wordpress--arhitektura-s-next-js--graphql-i-cloudflare</guid>
      <description><![CDATA[<p>Разбираем headless WordPress на практике: Next.js, Cloudflare Workers, GraphQL и архитектура быстрых и масштабируемых сайтов.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/headless-wordpress--arhitektura-s-next-js--graphql-i-cloudflare">Headless WordPress: архитектура с Next.js, GraphQL и Cloudflare</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[Оптимизация]]></category>
      <category><![CDATA[PHP]]></category>
      <category><![CDATA[WordPress]]></category>
      <category><![CDATA[React]]></category>
      <category><![CDATA[Cloudflare]]></category>
      <category><![CDATA[CMS]]></category>
      <category><![CDATA[CDN]]></category>
      <category><![CDATA[CI/CD]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 26 Mar 2026 11:29:45 GMT</pubDate>
      <content:encoded><![CDATA[<h2>Почему WordPress?</h2><p>WordPress часто не любят backend-разработчики, и у каждого на это есть свои причины. Кому-то не нравится функциональный стиль разработки, кто-то критикует form-builder и экосистему плагинов. У других WordPress как CMS и PHP как язык программирования до сих пор ассоциируются со стереотипами 10–15-летней давности - будто они устарели и уступают современным технологиям.</p><p>При этом реальность такова, что и PHP, и WordPress - отличные и современные инструменты, которые очень хорошо выполняют свои задачи. Опустим PHP - статья не об этом. Что же можно сказать про WordPress как про продукт и как CMS?</p><p>WordPress по‑прежнему остаётся самой популярной системой управления контентом. Согласно данным команды WordPress, платформа обслуживает более 43% всех веб-сайтов и занимает долю в 61% на рынке CMS. Также статистика показывает, что WordPress используется примерно на 59% сайтов, где известна CMS (это около 42% всего веба).</p><p>Данные были взяты из официального блога WordPress и сайта w3techs.com:</p><ul><li><a href="https://wordpress.com/blog/2025/04/17/wordpress-market-share/" rel="nofollow">https://wordpress.com/blog/2025/04/17/wordpress-market-share/ </a></li><li><a href="https://w3techs.com/technologies/overview/content_management" rel="nofollow">https://w3techs.com/technologies/overview/content_management</a></li><li><a href="https://w3techs.com/technologies/details/cm-wordpress" rel="nofollow">https://w3techs.com/technologies/details/cm-wordpress</a></li></ul><p>При этом, традиционный WordPress объединяет CMS, шаблоны на PHP и монолитные темы. Такая связка усложняет разработку с использованием современных JS фреймворков, а также затрудняет независимое масштабирование фронтенда и бэкенда, и оптимизацию производительности и безопасности. Жёсткая связка страниц, устаревшие PHP‑функции и не самый удобный девелоперский опыт часто заставляют команды искать альтернативы.</p><p>Headless WordPress решает эти проблемы: CMS становится админ-панелью для управления контентом, а отдельный фронтенд отвечает за UI. Такое разделение обязанностей даёт несколько преимуществ: четкое разделение ответственности, независимое масштабирование интерфейса и CMS, упрощенную локальную разработку и CI/CD. CMS превращается в API‑ориентированное хранилище, а современные фреймворки вроде Next.js берут на себя маршрутизацию и рендеринг.</p><h2>Headless WordPress с использованием WPGraphQL</h2><p>Чтобы использовать WordPress как headless‑CMS, нужен API. Также есть интересный пост про headless wordpress в их <a href="https://wordpress.com/blog/2025/03/20/headless-wordpress/" rel="nofollow">официальном блоге</a>.</p><p>В WordPress из коробки есть REST API, но для frontend и mobile приложений часто удобнее использовать GraphQL. <a href="https://wordpress.org/plugins/wp-graphql/" rel="nofollow">WPGraphQL</a> - это open source плагин, который добавляет GraphQL API в WordPress. Используя WPGraphQL, мы получаем:</p><ul><li>Гибкие запросы к таким сущностям, как посты, страницы, произвольным типам постов, таксономиям и пользователям.</li><li>Систему расширений которая позволяет расширять функционал GraphQL бекенда и таким образом поддерживать популярные плагины, тем самым позволяя возвращать дополнительные поля которые не относятся к стандартным полям Wordpress.</li><li>GraphQL API, который даёт очень удобный формат для интеграции фронтенд фреймворков таких как Next.js, Astro и SvelteKit.</li><li>Оптимизацию производительности, поскольку клиент запрашивает только нужные поля и данные делая один запрос вместо группы REST запросов + отдельный фронтенд забирает на себя часть запросов.</li></ul><p>В дополнение к доступному функционалу WPGraphQL можно добавлять дополнительные плагины-расширения, такие как <a href="https://wordpress.org/plugins/add-wpgraphql-seo/" rel="nofollow">WPGraphQL Yoast SEO</a> и <a href="https://woographql.com/" rel="nofollow">WooGraphQL</a> (WPGraphQL для WooCommerce). Таким образом добавив несколько плагинов в базовую инсталляцию CMS можно из коробки получить полностью функциональный GraphQL бекенд, который может покрыть запросы для блога, сео функционал, онлайн-магазин и тд.</p><p>Важно отметить, что изначальная идея использовать WPGraphQL пришла из статьи в блоге <a href="https://vercel.com/kb/guide/wordpress-with-vercel" rel="nofollow">Vercel</a>.</p><figure><img src="https://media.tproger.ru/user-uploads/136948/2026-03-25/838bc085-bfe5-4888-a326-6dcc00b0aaf5.webp" alt="Сравнение традиционного WordPress и headless WordPress: монолитная CMS с PHP темами против архитектуры с WPGraphQL API и Next.js фронтендом" /><figcaption>Традиционный WordPress vs Headless WordPress: разделение CMS и frontend через API (WPGraphQL + Next.js)</figcaption></figure><h2>Фронтенд на Next.js</h2><p><a href="https://nextjs.org/" rel="nofollow"> Next.js</a> - production-ready React-фреймворк, который разрабатывается компанией Vercel. Многие используют его по умолчанию для разных headless‑проектов. Наш пример headless-wordpress не исключение. Фреймворк предлагает удобную <a href="https://nextjs.org/docs/pages/building-your-application/routing" rel="nofollow">маршрутизацию</a> на базе файловой системы, где любой файл в папке pages автоматически становится маршрутом и поддерживает несколько стратегий рендеринга:</p><ul><li>Server‑side rendering (SSR) позволяет генерировать HTML при каждом запросе.</li><li>Статическая генерация (включая [Incremental Static Regeneration])</li><li>React Server Components, стратегия которая дает гибкость в балансировании производительности и кэширования.</li></ul><p>Это делает Next.js хорошей платформой для работы с GraphQL API и рендеринга страниц React‑компонентами. Если у вас нет опыта с <a href="http://nex.js">Next.js</a> и React, то это не повод не попробовать набросать POC в свободное время. Современные <a href="http://next.js">Next.js</a> и React templates + хороший AI agent помогут адаптировать UI под GraphQL для вас.</p><h2>Почему Cloudflare?</h2><p>Vercel очень часто является платформой по умолчанию для Next.js‑приложений. Более того Next.js адаптирован для запуска из коробки на серверах Vercel. При этом нужно добавить, что идея этой статьи не в том чтобы как-то компрометировать Vercel. Что же нужно знать про Cloudflare чтобы обратить внимание на этот сервис с точки зрения альтернативы для хостинга Next.js?</p><p>Согласно <a href="https://w3techs.com/technologies/details/cn-cloudflare" rel="nofollow">статистике</a>, реверс-прокси сервисы Cloudflare используются примерно на 21,9% всех сайтов в интернете, а это более 82% сайтов, где используется прокси‑сервисы в принципе. Такая распространённость говорит о масштабе, надежности и глобальном охвате сервиса. Но Cloudflare - это не только reverse-proxy. Компания разрабатывает целую группу облачных сервисов, включая такие сервисы, как Cloudflare Pages - альтернатива Github Pages, Workers - Serverless functions (по аналогии с AWS Lambda), Контейнеры, Очереди, AI сервисы, R2 Object Storage, и другие. В дополнение ко всему, компания предоставляет такие сервисы, как защита сайта (site-protection), VPN и капча (human-detection captcha). Такое разнообразие сервисов делает сервис очень распространенным.</p><h2>Лимиты бесплатного тарифа Cloudflare</h2><p>Одним из самых интересных аргументов в пользу Cloudflare можно считать их бесплатный тариф. Защита от DDoS, Universal SSL и глобальную CDN доступны бесплатно. Также бесплатный тариф включает большинство из вышеперечисленных облачных сервисов. Например, Cloudflare Workers, который можно использовать для хостинга Next.js-проектов, бесплатно даёт 100,000 запросов в день. Или R2 object storage - альтернатива S3 по умолчанию дает 10GB пространства, которое можно использовать для хранения статики или других данных. Этого более чем достаточно чтобы поэкспериментировать на выходных с новым стеком и вполне достаточно для того, чтобы бесплатно хостить ваш проект до тех пор пока у вас не пойдет серьезный трафик. Ниже приведена таблица с некоторыми из Cloudflare сервисов и что включено в бесплатный тариф.</p><figure><img src="https://media.tproger.ru/user-uploads/136948/2026-03-25/826d92c6-cecd-4d70-a2ee-78733a324a70.webp" alt="Таблица сервисов Cloudflare (Workers, KV, D1, R2 и др.) с лимитами бесплатного тарифа и их назначением" /><figcaption>Cloudflare free tier: сервисы и лимиты, достаточные для запуска headless WordPress + Next.js проекта. Взято с https://dev.to/ioniacob/which-cloudflare-services-are-free-2025-free-tier-guide-53jl.</figcaption></figure><h2>Запуск Serverless функций на edge-серверах</h2><p>Cloudflare Workers позволяют запускать серверлесс‑код по всей сети Cloudflare. Ниже приведено изображение показывающее как работает Edge CDN, когда например статика продублирована на все доступные сервера и таким образом пользователь получает ресурсы с самого близлежащего сервера.</p><figure><img src="https://media.tproger.ru/user-uploads/136948/2026-03-25/6c12d101-f282-4d1a-8d7a-b4119fabdfda.webp" alt="Схема работы CDN: пользователи обращаются к ближайшим edge-серверам, которые кешируют контент и уменьшают нагрузку на origin-сервер" /><figcaption>Как работает CDN: пользователь получает контент с ближайшего edge-сервера, снижая задержку и нагрузку на origin. Источник: https://www.cloudflare.com/learning/cdn/what-is-a-cdn/</figcaption></figure><p>Эта картинка хороша тем, что аналогично CDN статике на этих же серверах можно запускать и Workers (Lambda) функции, тем самым ускоряя вашу инфраструктуру еще больше.</p><p>Одной из интересных особенностей Workers-функций является отсутствие cold-starts. Любой cloud provider обычно подымает docker container или виртуализированное окружение в момент первого запуска программы, а это всегда задержка. Минусом Workers-функций является тот факт что их Runtime API требует чтобы код мог использовать их Web platform APIs. А это в свою очередь ограничивает выбор языка программирования: Javascript, Typescript и WebAssembly. Но благодаря такому подходу Workers используют изолированную модель запуска  и могут быть прогреты еще до момента запуска кода этого воркера. Прогрев начинается еще на этапе TLS-соединения между клиентом и серверами Cloudflare. Полный текст статьи можно почитать в их <a href="https://blog.cloudflare.com/eliminating-cold-starts-with-cloudflare-workers/" rel="nofollow">блоге</a>.</p><figure><img src="https://media.tproger.ru/user-uploads/136948/2026-03-25/4bcd2a0a-5161-46f5-984c-87f4097411dc.webp" alt="Схема работы Cloudflare Workers: прогрев (warmup) и загрузка воркера происходят во время TLS handshake до выполнения HTTP-запроса" /><figcaption>Как Cloudflare Workers устраняют cold-start: прогрев воркера происходит ещё на этапе TLS-соединения.</figcaption></figure><p>Воркеры выполняются на edge-серверах, которые находятся ближе всего к пользователям, тем самым уменьшая задержку и разгружая origin‑сервер (в нашем случае WordPress backend). По аналогии с другими cloud-провайдерами, код внутри Workers Runtime может использовать другие сервисы Cloudflare, такие как:</p><ul><li><a href="https://developers.cloudflare.com/workers/runtime-apis/cache/" rel="nofollow">Cache API</a> - позволяет читать и записывать данные в глобальный edge‑кэш через caches.default, что удобно для кэширования GraphQL‑ответов или страниц Next.js.</li><li><a href="https://developers.cloudflare.com/kv/" rel="nofollow">Workers KV</a> - распределенное key‑value‑хранилище для конфигурации и небольших наборов данных; можно хранить и получать данные глобально с низкой задержкой.</li><li><a href="https://developers.cloudflare.com/workers/configuration/cron-triggers/" rel="nofollow">Cron Triggers</a> - можно сопоставить cron‑выражение с обработчиком scheduled(), чтобы запускать периодические задачи, например, уборку кэша или обновление данных. Триггеры выполняются на малоиспользуемых машинах, максимизируя эффективность.</li></ul><p>Наличие доступа к дополнительным сервисам, таким как базы данных (D1), объектное хранилище (R2), очереди и AI даёт свободу строить более сложные и гибкие архитектуры, что очень полезно в дальнейшем на больших масштабах.</p><h2>OpenNext: мост между Next.js и Cloudflare</h2><p>Самостоятельный деплой Next.js на разные платформы непрост, поскольку среда исполнения Vercel отличается от других. Можно поднять Next.js на Node‑сервере, но его работа отличается от edge‑режима Vercel. OpenNext - это проект с открытым исходным кодом, который адаптирует Next.js для разных серверлесс‑платформ. Важно сказать что у Next.js нет нативного способа само разворачивания на других платформах, кроме Vercel; существующие отдельные адаптеры разрознены и сложны в поддержке. <a href="https://opennext.js.org/" rel="nofollow">OpenNext</a> объединяет усилия в одном адаптере, переводя выход сборки Next.js в формат, совместимый с основными облачными платформами. Проект поддерживают сообщество SST (AWS), команда Cloudflare и Netlify. Соответственно, с помощью OpenNext можно развернуть Next.js на Cloudflare Workers, сохраняя SSR, статическую генерацию и API‑маршруты.</p><p>Cloudflare‑адаптер устанавливается через @opennextjs/cloudflare. Далее следует установить<a href="https://developers.cloudflare.com/workers/wrangler/"> Wrangler</a>, настроить wrangler.toml с вашим Account ID и создать open-next.config.ts для управления кэшем и ассетами. Адаптер собирает приложение Next.js под среду Cloudflare, создает edge‑воркер и конфигурирует кэш для статики и ISR‑страниц (например, используя R2). После публикации Git‑интеграция Cloudflare автоматически разворачивает приложение при каждом пуше в GitHub или GitLab, а для pull‑request создает превью.</p><figure><img src="https://media.tproger.ru/user-uploads/136948/2026-03-25/ffd3d8f8-9e94-4ee2-b1b8-7b7d075a9bbd.webp" alt="Логотипы OpenNext, Cloudflare, AWS Amplify и Netlify, показывающие поддержку деплоя Next.js на разные cloud-платформы" /><figcaption>OpenNext как единый адаптер для деплоя Next.js приложений на разные платформы: Cloudflare, AWS и Netlify</figcaption></figure><h2>Кэширование и уровни производительности</h2><p>Архитектура headless WordPress + Next.js + Cloudflare обычно включает несколько уровней кэша:</p><ol><li>Кэш браузера - стандартный HTTP‑кэш на стороне клиента.</li><li>Кэш edge‑рантайма - Cache API Cloudflare Workers сохраняет HTML‑страницы или GraphQL‑ответы рядом с пользователем; при попадании в кэш контент отдаётся мгновенно, а промахи идут к воркеру или origin.</li><li>Кэш ISR Next.js - технология Incremental Static Regeneration сохраняет отрендеренные страницы на сервере и обновляет их по запросу, снижая нагрузку на WordPress API.</li><li>Кэш GraphQL - API WPGraphQL может реализовывать кэширование по времени или тегам (например, через WPGraphQL Smart Cache), чтобы управлять сроком жизни ответов.</li></ol><p>Эта многоуровневая иерархия кэша обеспечивает, что большинство запросов вообще не доходят до вашего WordPress‑сервера, повышая производительность и снижая нагрузку.</p><p>Пример конечной архитектуры показан на изображении ниже.</p><figure><img src="https://media.tproger.ru/user-uploads/136948/2026-03-25/37141150-e160-423b-a8cd-3784117e6499.webp" alt="" /><figcaption>Архитектура headless WordPress + Next.js на Cloudflare: edge-рендеринг, многоуровневый кэш и взаимодействие с WPGraphQL</figcaption></figure><h2>Автоматизация периодических задач</h2><p>Headless‑сайтам часто требуются периодические действия - например, обновление кэша ISR или синхронизация данных. Cron Triggers Cloudflare позволяют планировать запуск воркера по cron‑выражению. Обработчик scheduled() срабатывает по расписанию и подходит для обслуживания и получения сторонних данных. Триггеры выполняются на малоиспользуемых машинах по всему миру и легко управляются через Wrangler или панель Cloudflare.</p><h2>Модернизация PHP‑стека с Roots toolkit</h2><p>Хотя headless WordPress переносит рендеринг на JavaScript, CMS всё ещё нужно поддерживать. В качестве бонуса хочется порекомендовать экосистему <a href="https://roots.io/" rel="nofollow">Roots</a>, которая предлагает современный инструментарий для разработки на WordPress:</p><figure><img src="https://media.tproger.ru/user-uploads/136948/2026-03-25/27e070e5-39c8-425b-8142-b0b2ce0af69d.webp" alt="Скриншот сайта Roots с описанием инструментов для разработки WordPress: Bedrock, Sage, Trellis и Acorn" /><figcaption>Roots — современный инструментарй для разработки WordPress с использованием Composer, Blade и автоматизированного деплоя. Источник: Roots - https://roots.io/</figcaption></figure><ul><li><a href="https://roots.io/bedrock/" rel="nofollow">Bedrock</a> - шаблон WordPress, которая устанавливает ядро, плагины и темы через Composer. Таким образом Bedrock дает современную для PHP проектов структуру проекта, улучшает структуру папок, использует концепты Двенадцать факторов для конфигурации приложения с помощью .env‑файлы и тд. Более того, управление зависимостями через Composer повышает надежность и позволяет делать деплой приложения на разные сервера без страха что-то забыть или упустить.</li><li><a href="https://roots.io/sage/" rel="nofollow">Sage</a> - стартовая тема WordPress, использующая Blade от Laravel для шаблонов и интегрирующая Tailwind CSS. Sage автоматически генерирует theme.json из конфигурации Tailwind, поддерживает live preview блокового редактора с Vite и позволяет создавать компоненты на Blade. Это помогает фронтенд‑разработчикам отойти от устаревших подходов для разработки тем Wordpress с нуля.</li><li><a href="https://roots.io/trellis/" rel="nofollow">Trellis</a> - DevOps‑инструмент на базе Ansible, который поднимает серверы и автоматизирует деплой. Trellis предоставляет LEMP‑стек (Ubuntu 24.04, Nginx, PHP 8.3, MariaDB), выполняет деплой без downtimes и из коробки поддерживает SSL‑сертификаты. CLI помогает создавать и настраивать серверы, а также разворачивать проекты с атомарными релизами и откатами.</li><li><a href="https://roots.io/acorn/" rel="nofollow">Acorn</a> - интеграция, позволяющая использовать функционал Laravel в WordPress. С Acorn становятся доступны такие инструменты как Blade‑шаблоны, миграции, роутинг, кэширование и Artisan‑подобный CLI внутри WordPress. Это позволяет разработчикам строить плагины и фичи WordPress с использованием современных PHP‑подходов и современного фреймворка .</li></ul><p>Эти инструменты показывают, что экосистема WordPress продолжает развиваться и хорошо сочетается с современными подходами. Иными словами, WordPress - отличное решение, если знать, как его правильно готовить.</p><h2>Собираем всё вместе</h2><p>Архитектура приложения headless WordPress + Next.js + Cloudflare выглядит приблизительно так:</p><ol><li>WordPress (headless) - работает на традиционном сервере или в контейнере. Редакторы управляют контентом в админке. WPGraphQL и его расширения предоставляют GraphQL‑endpoint с данными, SEO и другой информацией, например данными о магазине.</li><li>Next.js фронтенд - React‑приложение, которое получает данные через GraphQL, рендерит страницы на сервере (SSR) или статически (ISR/SSG) и обрабатывает маршрутизацию и взаимодействие с клиентом. Код хранится в Git и автоматически разворачивается благодаря Git‑интеграции Cloudflare.</li><li>Cloudflare Workers - размещают приложение Next.js на edge через OpenNext. Workers исключают cold-starts и работают по аналогии с CDN как можно ближе к пользователю. Они также выполняют кэширование, обрабатывают API‑маршруты и запускают cron‑задачи.</li><li>Кэш на edge и в браузере - несколько уровней кэша гарантируют быструю отдачу статики и отрендеренных страниц. KV, R2 или D1 могут хранить дополнительные данные вроде сессий или объектов.</li></ol><h2>Заключение</h2><p>Headless‑архитектура объединяет универсальность WordPress и гибкость современных JavaScript‑фреймворков. Экспонируя контент через WPGraphQL и потребляя его в Next.js, можно получить больше контроля над рендерингом и тем самым улучшить производительность. Размещение фронтенда на Cloudflare Workers через OpenNext позволяет приблизить фронтенд код к пользователям, устраняет cold-starts, позволяет использовать free-tier и продвинутые уровни кэширования. Инструменты вроде Bedrock, Sage, Trellis и Acorn модернизируют PHP/Wordpress‑сторону и делают CMS такой же удобной в работе, как и современный Next.js/React-фронтенд. Вместе эти технологии создают мощный стек для создания быстрых, масштабируемых и безопасных сайтов, будь то хакатон, pet‑проект или серьёзный продакшн.</p>]]></content:encoded>
    </item>
    <item>
      <title>Вышла Nano Banana 2 — новое поколение ИИ-генератора картинок от Google</title>
      <link>https://tproger.ru/news/vywla-nano-banana-2---novoe-pokolenie-ii-generatora-kartinok-ot-</link>
      <comments>https://tproger.ru/news/vywla-nano-banana-2---novoe-pokolenie-ii-generatora-kartinok-ot-?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/vywla-nano-banana-2---novoe-pokolenie-ii-generatora-kartinok-ot-</guid>
      <description><![CDATA[<p>Google выпустила Nano Banana 2 (Gemini 3.1 Flash Image): быстрее генерация до 4K, дефолт в Gemini и водяной знак SynthID</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/vywla-nano-banana-2---novoe-pokolenie-ii-generatora-kartinok-ot-">Вышла Nano Banana 2 — новое поколение ИИ-генератора картинок от Google</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Google]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 26 Feb 2026 15:25:11 GMT</pubDate>
      <content:encoded><![CDATA[<p>Google <a href="https://blog.google/innovation-and-ai/technology/ai/nano-banana-2/">представила</a> Nano Banana 2 — обновленную версию своего популярного генератора изображений.</p><p>Технически модель называется Gemini 3.1 Flash Image и теперь станет моделью по умолчанию в приложении Gemini.</p><h2>Быстрее и реалистичнее</h2><p>Nano Banana 2 создает изображения быстрее, чем предыдущая версия, сохраняя при этом качество уровня Pro. Поддерживается разрешение от 512p до 4K и разные соотношения сторон.</p><p>Google заявляет о:</p><ul><li>более реалистичном освещении;</li><li>богатых текстурах;</li><li>четкой детализации;</li><li>поддержке сложных и «многоуровневых» промптов.</li></ul><p>Модель способна сохранять консистентность до пяти персонажей и до 14 объектов в рамках одного рабочего процесса. Это важно для сторителлинга и серийных изображений.</p><figure><img src="https://media.tproger.ru/user-uploads/111041/2026-02-26/542958c4-bf70-4523-add2-c60b4cb1e2ff.webp" alt="" /></figure><h2>Везде по умолчанию</h2><p>Nano Banana 2 станет дефолтной моделью генерации изображений:</p><ul><li>в приложении Gemini (режимы Fast, Thinking и Pro);</li><li>в редакторе видео Flow;</li><li>в Google Search через Google Lens;</li><li>в AI Mode в 141 стране.</li></ul><p>Подписчики Google AI Pro и Ultra смогут по-прежнему вручную выбирать Nano Banana Pro для специализированных задач.</p><h2>Водяные знаки и API</h2><p>Все изображения будут снабжены водяным знаком SynthID — фирменной системой маркировки ИИ-контента от Google. Также поддерживаются стандарты C2PA Content Credentials.</p><p>Для разработчиков модель доступна через Gemini API, Vertex API, Gemini CLI и AI Studio.</p>]]></content:encoded>
    </item>
    <item>
      <title>Заглянуть под капот ИИ-агентов: новый инструмент раскрывает «магию» Claude Code</title>
      <link>https://tproger.ru/news/zaglyanut-pod-kapot-ii-agentov--novyj-instrument-raskryvaet--mag</link>
      <comments>https://tproger.ru/news/zaglyanut-pod-kapot-ii-agentov--novyj-instrument-raskryvaet--mag?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Неопознанный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/zaglyanut-pod-kapot-ii-agentov--novyj-instrument-raskryvaet--mag</guid>
      <description><![CDATA[<p>Появился Coding Agent Explorer: инструмент раскрывает, как Claude Code читает файлы, вызывает инструменты и тратит токены при разработке</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/zaglyanut-pod-kapot-ii-agentov--novyj-instrument-raskryvaet--mag">Заглянуть под капот ИИ-агентов: новый инструмент раскрывает «магию» Claude Code</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Искусственный интеллект]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Промпты]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 19 Feb 2026 11:05:51 GMT</pubDate>
      <content:encoded><![CDATA[<p>ИИ-агенты любят создавать ощущение магии. Например, вы даете задачу — «добавь авторизацию через JWT». Затем минуту смотрите на мигающий курсор, после чего внезапно появляются изменения в семи файлах, новые тесты и коммит. Что происходило все это время — остается за кадром.</p><p>Шведский разработчик Торе Нестениус решил <a href="https://nestenius.se/ai/introducing-the-coding-agent-explorer-net/">сорвать</a> занавес. Он <a href="https://github.com/tndata/CodingAgentExplorer" rel="nofollow">выпустил</a> Coding Agent Explorer — открытый прокси-сервер, который в реальном времени показывает все общение между агентом и API Anthropic.</p><p>Сейчас поддерживается только Claude Code, но уже в таком виде инструмент дает неожиданно глубокое понимание того, как работает агентная разработка.</p><h2>Что именно он показывает</h2><p>Explorer перехватывает HTTP-запросы и визуализирует:</p><ul><li>системные промпты (часто намного длиннее, чем кажется);</li><li>последовательность вызовов инструментов (Read, Grep, Write, Bash);</li><li>шаги «размышления» агента;</li><li>распределение задач между моделями (например, Haiku для рутинных операций и Sonnet/Opus для сложной логики);</li><li>статистику токенов, включая кэш (cache_creation_tokens и cache_read_tokens).</li></ul><p>По сути, инструмент можно воспринимать как «рентген для агентной разработки». Видно, какие файлы агент читает, как ищет паттерны в коде, почему он внезапно запускает тесты и сколько это стоит в токенах.</p><p>В интерфейсе два режима. HTTP Inspector — сухая таблица со всеми JSON-телами, временем ответа и расходом токенов. Conversation View — более «человеческий» режим, где процесс выглядит как диалог: шаги планирования, проверки гипотез, исправления ошибок.</p><figure><img src="https://media.tproger.ru/user-uploads/111041/2026-02-19/a137b978-5b64-416e-a3a5-d4302b1937b7.webp" alt="" /></figure><h2>Зачем это нужно</h2><p>Изначально инструмент задумывался как учебный — автор использует его на воркшопах по агентной разработке. Но практическая ценность оказалась шире.</p><p>Когда агент «зависает», теперь можно увидеть, что он на самом деле делает: перебирает файлы, пересобирает контекст или тратит половину лимита токенов на анализ README.</p><p>А уже это помогает оптимизировать промпты и понимать реальную стоимость задач. В итоге ИИ перестает быть черным ящиком.</p><h2>Безопасность и ограничения</h2><p>Explorer работает только локально (localhost). API-ключи автоматически маскируются в интерфейсе.</p><p>Данные не сохраняются — все хранится в памяти и ограничено примерно тысячей запросов. Никаких внешних сервисов и баз данных.</p>]]></content:encoded>
    </item>
    <item>
      <title>7 готовых промптов для автоматизации через OpenClaw</title>
      <link>https://tproger.ru/articles/7-gotovyh-promptov-dlya-avtomatizacii-cherez-openclaw</link>
      <comments>https://tproger.ru/articles/7-gotovyh-promptov-dlya-avtomatizacii-cherez-openclaw?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Дима Дмитриев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/7-gotovyh-promptov-dlya-avtomatizacii-cherez-openclaw</guid>
      <description><![CDATA[<p>7 готовых промптов для OpenClaw: автоматизация почты, документов, мониторинга конкурентов, безопасности и умного дома без нод и сценариев.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/7-gotovyh-promptov-dlya-avtomatizacii-cherez-openclaw">7 готовых промптов для автоматизации через OpenClaw</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[OpenAI]]></category>
      <category><![CDATA[Автоматизирование]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 17 Feb 2026 08:45:02 GMT</pubDate>
      <content:encoded><![CDATA[<p>OpenClaw (ранее Clawdbot и Moltbot) — open-source AI-агент, который живёт в вашем мессенджере. В отличие от визуальных конструкторов вроде n8n или Zapier, здесь не нужно собирать ноды и настраивать связи вручную. Вы описываете задачу текстом, агент сам пишет код, создаёт скиллы и настраивает cron-расписания.</p><p>Статья предполагает, что OpenClaw у вас уже развёрнут. Если нет — <a href="https://routerai.ru/pages/openclaw-web-telegram-routerai-claude-gpt-5-deepseek-mistral">вот инструкция от RouterAI по установке</a>.</p><h2>Как использовать</h2><ul><li>Копируете промпт</li><li>Отправляете в OpenClaw</li><li>Отвечаете на уточняющие вопросы агента</li><li>Получаете работающую автоматизацию</li></ul><h2>1. Обработка входящих документов из чатов (счета, акты, КП)</h2><p>Документы из Telegram автоматически классифицируются, переименовываются по шаблону и раскладываются по папкам с уведомлением ответственных.</p><h2>Как это работает</h2><p>OpenClaw отслеживает входящие сообщения с вложениями. При получении PDF или изображения — запускает OCR при необходимости, извлекает ключевые данные (номер, дата, контрагент, сумма), переименовывает файл и сохраняет в нужную директорию.</p><h2>Промпт</h2><h2>Что подготовить</h2><ul><li>Канал/чат для входящих документов</li><li>Канал бухгалтерии для уведомлений</li><li>Путь к директории для хранения файлов</li></ul><h2>Итог</h2><p>Начните с одного канала. Посмотрите, насколько точно агент классифицирует документы, и скорректируйте шаблон переименования под свои нужды.</p><h2>2. Мониторинг и исследование конкурентов</h2><p>Ежедневный отчёт об активности конкурентов: новые продукты, изменения цен, вакансии, упоминания в прессе.</p><h2>Как это работает</h2><p>OpenClaw по cron-расписанию обходит список источников (RSS, сайты, новостные порталы), сравнивает с предыдущим отчётом и присылает только реальные изменения.</p><h2>Промпт</h2><h2>Что подготовить</h2><ul><li>Список конкурентов (названия, URL сайтов, RSS если известны)</li><li>Отрасль и ключевые слова для новостного поиска</li><li>Канал доставки отчёта</li></ul><h2>Итог</h2><p>Начните с 2–3 конкурентов и RSS-лент — это самый надёжный источник. Скрапинг публичных страниц может ломаться при изменении вёрстки, так что проверяйте отчёты в первую неделю.</p><h2>3. Утренний дайджест по расписанию</h2><p>Сводка за 2 минуты вместо получаса ручной проверки почты, чатов и новостей.</p><h2>Как это работает</h2><p>По расписанию OpenClaw собирает данные из подключённых источников (почта, календарь, мессенджеры, новости) и присылает одно сообщение с приоритетами.</p><h2>Промпт</h2><h2>Что подготовить</h2><ul><li>Какие источники подключены (почта, календарь, мессенджеры)</li><li>Список важных отправителей/чатов</li><li>Тематика новостей</li><li>Канал доставки</li></ul><h2>Итог</h2><p>Первую неделю следите за качеством — скорее всего, придётся подправить список важных отправителей и тематику новостей. Если используете вместе с кейсом 4 (Email-triage), разграничьте зоны ответственности: дайджест — обзор за день, triage — обработка каждого письма в реальном времени.</p><h2>4. Email-triage: Inbox Zero с умной обработкой</h2><p>Автоматическая сортировка входящей почты: важные письма — в приоритет, рассылки — в архив, типовые запросы — черновик ответа.</p><h2>Как это работает</h2><p>OpenClaw проверяет почту каждые 15 минут, классифицирует письма и выполняет действия: уведомляет, архивирует, готовит черновики или помечает для ручной обработки.</p><h2>Промпт</h2><h2>Что подготовить</h2><ul><li>Почтовый ящик (Яндекс Почта, Mail.ru, Gmail, Outlook или IMAP)</li><li>Список VIP-отправителей</li><li>Примеры типовых запросов для обучения классификации</li><li>Канал для уведомлений</li></ul><h2>Итог</h2><p>Начните с автоархивации рассылок — это безопасно и сразу разгружает инбокс. Черновики ответов подключайте, когда убедитесь в качестве классификации. Папку «На проверку» первое время проверяйте ежедневно. Если используете вместе с кейсом 3 (утренний дайджест), почтовую часть дайджеста можно упростить до сводки по категориям из triage.</p><h2>5. Управление умным домом/офисом через чат</h2><p>Управление устройствами через сообщения: включить свет, выключить обогреватель, запустить сценарий — без отдельного приложения для каждого вендора.</p><h2>Как это работает</h2><p>OpenClaw подключается к Home Assistant (или другой системе) через API и выполняет команды из чата. Простые действия — сразу, сценарии — по расписанию.</p><h2>Промпт</h2><h2>Что подготовить</h2><ul><li>Какая система умного дома (Home Assistant, Яндекс, Mi Home или другая)</li><li>URL и API-токен для подключения</li><li>Список устройств и их названия</li><li>Какие сценарии по расписанию нужны</li></ul><h2>Итог</h2><p>Начните со света и температуры — это самые безопасные команды для обкатки. Убедитесь, что агент правильно сопоставляет названия устройств, прежде чем подключать сценарии по расписанию.</p><h2>6. Помощник для защиты прав потребителя</h2><p>Подготовка претензий, жалоб и запросов на возврат: подбор статей закона, генерация документов, контроль сроков.</p><h2>Как это работает</h2><p>Вы описываете проблему, агент определяет тип спора, подбирает применимые нормы, генерирует текст документа и ставит напоминание о дедлайне ответа.</p><h2>Промпт</h2><h2>Что подготовить</h2><ul><li>ФИО, адрес и контакты для шапки документа</li><li>Документы по спору (чеки, договор, переписка с продавцом)</li><li>Описание проблемы: что купили, когда, что пошло не так</li></ul><h2>Итог</h2><p>Для стандартной претензии по ЗоЗПП — работает хорошо. Для чего-то серьёзнее (суд, крупные суммы) — обратитесь к юристу. LLM может ошибиться в трактовке закона.</p><h2>7. Проактивный мониторинг безопасности</h2><p>Ежедневная проверка зависимостей проектов на известные уязвимости с уведомлениями по критичности.</p><h2>Как это работает</h2><p>OpenClaw по расписанию парсит файлы зависимостей, сверяет версии пакетов с базой CVE и присылает отчёт с приоритизацией по CVSS.</p><h2>Промпт</h2><h2>Что подготовить</h2><ul><li>Пути к репозиториям/директориям для мониторинга</li><li>Канал для уведомлений</li><li>Есть ли пакеты, которые нужно исключить из проверки</li></ul><h2>Итог</h2><p>Хорошая первая линия обороны, но не замена полноценному аудиту. Для критичных систем используйте Snyk, Trivy или Dependabot параллельно.</p><h2>Ещё идеи</h2><p>Что делают другие пользователи:</p><ul><li>Парсинг веб-страниц и сохранение саммари в базу знаний</li><li>Поиск товаров на маркетплейсах по списку покупок и добавление дешёвых вариантов в корзину</li><li>Сбор статистики из рекламных кабинетов и отправка сводки команде</li><li>Переименование файлов в папке по содержимому или дате</li><li>Мониторинг новостных сайтов по теме AI с публикацией саммари в Telegram-канал команды</li><li>Проверка битых ссылок на сайте и отчёт по 404-м</li><li>Поиск кандидатов на hh.ru по критериям и выгрузка в таблицу</li><li>Мониторинг цен на авиабилеты с уведомлением при снижении</li><li>Анализ серверных логов за сутки и выделение критических ошибок</li><li>Перевод файлов локализации (JSON) на новые языки с сохранением структуры</li><li>Сбор финансовых показателей конкурентов из открытых источников в Excel</li></ul><h2>Рекомендации</h2><p><b>Начните с малого.</b> Выберите 2–3 кейса и доведите до ума, прежде чем автоматизировать всё подряд.</p><p><b>Итерируйте.</b> Первая версия промпта редко бывает идеальной. Корректируйте по результатам.</p><p><b>Следите за агентом.</b> Первое время проверяйте, что автоматизация делает то, что вы ожидаете.</p><p><b>Не забывайте о безопасности.</b> HTTPS, минимальные права доступа, секреты — в защищённом хранилище. Агент с доступом к вашим системам и API-ключам может натворить дел при ошибке в настройке.</p><h2>Заключение</h2><p>Возможности OpenClaw + <a href="https://routerai.ru/">RouterAI</a> не ограничиваются этими семью сценариями — вы можете описать агенту любую задачу или попросить его создать нужную автоматизацию с нуля.</p>]]></content:encoded>
    </item>
    <item>
      <title>Android 17 Beta 1 вышла с новыми API камеры и изменениями интерфейса</title>
      <link>https://tproger.ru/news/android-17-beta-1-vywla-s-novymi-api-kamery-i-izmeneniyami-interf</link>
      <comments>https://tproger.ru/news/android-17-beta-1-vywla-s-novymi-api-kamery-i-izmeneniyami-interf?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/android-17-beta-1-vywla-s-novymi-api-kamery-i-izmeneniyami-interf</guid>
      <description><![CDATA[<p>Android 17 Beta 1 вышла для Pixel: новые API камеры, обязательная адаптивность интерфейсов и постепенные изменения дизайна</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/android-17-beta-1-vywla-s-novymi-api-kamery-i-izmeneniyami-interf">Android 17 Beta 1 вышла с новыми API камеры и изменениями интерфейса</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Google]]></category>
      <category><![CDATA[Бета]]></category>
      <category><![CDATA[Дизайн]]></category>
      <category><![CDATA[Дизайн интерфейсов и UX]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 13 Feb 2026 17:20:07 GMT</pubDate>
      <content:encoded><![CDATA[<p>Google <a href="https://www.androidauthority.com/android-17-beta-1-delayed-rollout-3640969/">запустила</a> первую бета-версию Android 17 для устройств Pixel.</p><p>Релиз немного задержался — компания в последний момент отложила старт тестирования, пообещав, что обновление выйдет «скоро». В итоге пауза продлилась всего несколько дней.</p><p>Бета уже распространяется «по воздуху» для участников Android Beta Program. Владельцы актуальных Pixel получат обновление автоматически.</p><h2>Обязательная адаптивность и доработанная камера</h2><p>Одно из ключевых изменений — обязательная поддержка адаптивных интерфейсов для приложений, ориентированных на Android 17.</p><p>Разработчикам придется корректно обрабатывать разные размеры экранов и форм-факторы, включая складные устройства и планшеты. Формально это не то чтобы революция. Но теперь за игнорирование адаптивности можно будет заплатить совместимостью.</p><p>Вторая важная новинка — обновленные API камеры. Они должны устранить рывки и пропуски кадров при переключении режимов съемки. Это как раз та категория проблем, которую достаточно сложно показать на презентации, но которая напрямую влияет на пользовательский опыт.</p><p>Также в системе появились визуальные правки интерфейса. Google продолжает постепенно дорабатывать дизайн, не меняя радикально общую концепцию.</p><figure><img src="https://media.tproger.ru/user-uploads/111041/2026-02-13/c690325a-75d9-41e1-aa65-c96b3d7425e6.webp" alt="" /></figure><h2>Как установить и когда ждать релиз</h2><p>Участники программы тестирования получат Android 17 Beta 1 автоматически. Тем, кто не хочет устанавливать бета-версию, нужно выйти из программы и дождаться стабильной сборки.</p><p>Финальный релиз Android 17 ожидается во II квартале 2026 года. Судя по первой бете, Google делает ставку не на громкие функции, а на стабильность, производительность и требования к качеству приложений.</p><p>Для экосистемы это может оказаться важнее любой эффектной анимации.</p>]]></content:encoded>
    </item>
  </channel>
</rss>