BorisovAI

Блог

Публикации о процессе разработки, решённых задачах и изученных технологиях

Найдено 20 заметокСбросить фильтры
Новая функцияC--projects-bot-social-publisher

SQLite на Linux: когда переменные окружения не спасают

# Деплой SQLite: когда переменные окружения предают в самый ответственный момент Проект `ai-agents-bot-social-publisher` стоял на пороге боевого выпуска. Восемь n8n-воркфлоу, которые собирают посты из социальных сетей и сортируют их по категориям, прошли все локальные тесты с честью. Команда была уверена — завтра деплоим на Linux-сервер, и всё заживёт. Реальность оказалась жестче. Первая же волна логов после развёртывания завалила ошибку: `no such table: users`. Все SQLite-ноды в воркфлоу панически искали базу по пути `C:\projects\ai-agents\admin-agent\database\admin_agent.db`. Классический Windows-путь. На Linux-сервере, разумеется, такого ничего не было. ## Элегантное решение, которое не выжило встречи с реальностью Первый инстинкт был логичен: использовать переменные окружения и выражения n8n. Добавили `DATABASE_PATH=/data/admin_agent.db` в `docker-compose.yml`, развернули воркфлоу с выражением `$env.DATABASE_PATH` в конфиге SQLite-ноды и нажали кнопку деплоя. Ничего не изменилось — всё падало с той же ошибкой. Потом выяснилось неприятное: в n8n v2.4.5 таск-раннер **не передавал переменные окружения в SQLite-ноду так, как обещала документация**. Выражение красиво сохранялось в конфигурации, но при реальном выполнении система всё равно искала исходный Windows-путь. Красивое решение встретилось с суровой реальностью и проиграло. ## Скучный способ, который работает Пришлось отказаться от элегантности в пользу надёжности. Решение оказалось неожиданно простым: **string replacement при деплое**. Написал скрипт `deploy/deploy-n8n.js`, который перехватывает JSON каждого воркфлоу перед загрузкой на сервер и заменяет все `$env.DATABASE_PATH` на реальный путь `/var/lib/n8n/data/admin_agent.db`. Скучно? Абсолютно. Но работает. Здесь же обнаружилась вторая подводная скала: n8n хранит две версии каждого воркфлоу. *Stored*-версия живёт в базе данных, *active*-версия загружена в памяти и реально выполняется. Когда обновляешь воркфлоу через API, обновляется только хранилище. Active может остаться со старыми параметрами. Спасение простое: после обновления конфига явно деактивировать и активировать воркфлоу. К этому добавили инициализацию SQLite. Скрипт копирует на сервер SQL-миграции (`schema.sql`, `seed_questions.sql`) и выполняет их через n8n API перед активацией воркфлоу. Выглядит как излишество, но спасает в будущем — когда потребуется добавить колонку в таблицу `users`, просто добавляешь новую миграцию без полного пересоздания БД. ## Итог Теперь весь деплой — одна команда: `node deploy/deploy-n8n.js --env .env.deploy`. Воркфлоу создаются с правильными путями, база инициализируется, всё работает. **Главный урок:** не полагайся на runtime-выражения в критических параметрах конфигурации. Лучше заранее знать точное место и подставить путь при развёртывании. Скучно, но надёжно. — Ну что, SQLite, теперь ты найдёшь свою базу? — спросил я у логов. SQLite ответил тишиной успеха. 😄

#claude#ai#javascript#git#api
7 февр. 2026 г.
Новая функцияborisovai-admin

Туннели за день: как я параллелизировал frp-интеграцию

# Параллелизм в действии: как я за один день собрал туннельное решение для borisovai-admin Когда ты работаешь над проектом **borisovai-admin**, появляются моменты, когда нужно сделать сразу много однотипной работы. У меня была ровно такая задача: реализовать систему **frp tunneling** — нужно было создать четыре новых файла, переделать четыре существующих и не запутаться в деталях. Обычно такие дни начинаются с вопроса: «С чего начать?» Я выбрал ответ: со всем одновременно. ## Задача: соединить машины, не ломая архитектуру Проблема была в том, что нам нужна была система туннелирования для соединения удалённых серверов через контрольный канал. **frp** (fast reverse proxy) — отличный инструмент для этого, но его нужно было интегрировать в существующую инфраструктуру. При этом всё должно было работать параллельно с **Traefik** и не конфликтовать с уже развёрнутой системой. Первым делом я понял: это не может быть один огромный рефакторинг. Нужен был план, разбитый на логические части. ## Что я создал: четыре ключевых компонента **install-frps.sh** стал сердцем всей системы — 210-строчный скрипт установки, который берёт на себя всю грязную работу: скачивает бинарник, генерирует конфиг, создаёт systemd unit, настраивает DNS и firewall. Это не просто скрипт — это полноценный конвейер, который должен работать на production-сервере без человеческого вмешательства. Параллельно я подготовил **шаблон frpc.toml** для Windows-клиентов, чтобы разработчик мог просто заполнить пару полей и запустить. И конечно, **systemd unit** и **Traefik конфиг** для основного сервера — чтобы всё было pre-built и готово к развёртыванию. ## Неожиданный момент: три порта вместо одного Когда я раскладывал архитектуру по полочкам, выяснилось, что **frp** использует три разных порта: 17420 (control channel), 17480 (HTTP vhost за Traefik), 17490 (dashboard только для localhost). Первый импульс был открыть всё в firewall, но стоп — нужна была безопасность. В итоге получилось изящное решение: контрольный канал открыт, vhost спрятан за Traefik с wildcard HostRegexp, dashboard доступен только локально. ## Интересный факт про reverse proxy Знаете, что смешного в reverse proxy? Обычный proxy скрывает клиента (вы видите proxy, а не пользователя). Reverse proxy делает противоположное — скрывает сервер (клиент видит публичный адрес, а не реальную машину). **frp** — это именно reverse proxy в его самом полезном проявлении для распределённых систем. ## Что дальше В итоге я обновил четыре существующих файла, добавил скрипт установки в upload-процесс, расширил конфиг примеров четырьмя новыми полями. Теперь разработчик может развернуть frps-сервер одной командой и подключить Windows-клиент без боли. Главный урок дня: когда задача кажется большой, попробуй разделить её не на последовательные шаги, а на параллельные потоки. Четыре файла создавались одновременно в моей голове — и в итоге собрались в цельную систему, которая *просто работает*. 😄 Что общего у Bun и подростка? Оба непредсказуемы и требуют постоянного внимания.

#claude#ai#javascript#api
7 февр. 2026 г.
Новая функцияtrend-analisis

Суперкластеры AI переписывают энергетику и геополитику

# Когда AI-кластеры переписывают энергетическую карту мира На проекте **trend-analysis** мне дали интересную задачу: разобраться с каскадными эффектами, которые создают AI-суперкластеры. Не просто "AI быстрее растёт", а настоящая цепочка последствий: как инвестиции мегатехкомпаний в энергетику меняют геополитику, недвижимость, научные исследования и даже рынок труда. Первым делом я начал картографировать эту сеть причинно-следственных связей. Оказалось, что когда OpenAI, Meta и Google строят собственные энергостанции для своих суперкластеров, это не просто техническая покупка. Это *перевод власти* от государственных энергокомпаний к корпорациям. Раньше энергетическая инфраструктура была монопольной государственной игрой — теперь она становится товаром конкуренции между мегакорпорациями. Но самая острая проблема оказалась в **водных ресурсах**. Современный дата-центр требует 400+ тысяч галлонов воды в день для охлаждения. В засушливых регионах (американский Юго-Запад, части Европы) это создаёт прямой конфликт с сельским хозяйством и питьевым водоснабжением. Tech-компании вынуждены срочно разрабатывать *waterless cooling* — погружную охладительную систему, чип-на-чип теплоотвод. Но это требует 3–5 лет разработки, а давление растёт прямо сейчас. Параллельно я отследил другой эффект: **стабилизацию цен на AI-сервисы**. Когда основные игроки держат цены на уровне $0.01–0.10 за 1000 токенов и не спешат их снижать, это создаёт идеальные условия для *параллельной экосистемы open-source*. Компании среднего размера начинают массово переходить на Llama и Mistral, разворачивая локальные модели. Это не конкуренция за цены — это уход от игроков вообще. Неожиданный вывод: **AI-неравенство растёт географически**. Студенты в развивающихся странах не могут себе позволить регулярный доступ к SOTA-моделям через API. Это замедляет их карьеру, концентрирует таланты в богатых регионах и парадоксально — замораживает скорость инноваций. Breakthrough часто приходит от неожиданных источников, но если источник не может позволить себе экспериментировать, инновация замирает. Я заметил и третий паттерн: **enterprise middleware взлетает**. Когда цены на API высокие и стабильные, между моделью и пользователем рождается целый слой посредников (LangChain, LlamaIndex, специализированные гейтвеи). Каждый из них ловит немного стоимости. Это усложняет экосистему, но укрепляет позиции действующих игроков. Самый интересный каскадный эффект — **малые модульные реакторы (SMR)**. Tech-гиганты, вкладывающие в ядерную энергию, аккумулируют столько инвестиций, что SMR перестают быть мечтой — они становятся коммерчески жизнеспособными. Это может решить энергетический кризис для 800+ миллионов людей без надёжного электричества. Вывод: разработчик работает в эпоху, когда его выбор технологии имеет отклик в энергетике, демографии, научных исследованиях. Это не просто features и bugs — это реальная переустройка мира. Что общего у Netlify и кота? Оба делают только то, что хотят, и игнорируют инструкции 😄

#claude#ai#javascript#api
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

SQLite на кроссплатформе: когда переменные окружения предают

# SQLite между Windows и Linux: как не потерять данные при деплое Проект `ai-agents-bot-social-publisher` был почти готов к боевому выпуску. Восемь n8n-воркфлоу, которые собирают посты из социальных сетей и распределяют их по категориям, прошли локальное тестирование на отлично. Но тут наступил момент истины — первый деплой на Linux-сервер. Логи завалили ошибкой: `no such table: users`. Все SQLite-ноды в воркфлоу отчаянно искали базу данных по пути `C:\projects\ai-agents\admin-agent\database\admin_agent.db`. Windows-путь. На Linux-сервере, разумеется, ничего такого не было. ## Красивое решение, которое не сработало Первый инстинкт был логичный: использовать переменные окружения и выражения n8n. Добавили `DATABASE_PATH=/data/admin_agent.db` в `docker-compose.yml`, развернули воркфлоу с выражением `$env.DATABASE_PATH` в конфиге SQLite-ноды, нажали на кнопку деплоя и... всё равно падало. Выяснилось, что в n8n v2.4.5 **таск-раннер не передавал переменные окружения в SQLite-ноду так, как ожидалось**. Выражение красиво хранилось в конфигурации, но при выполнении система всё равно искала исходный Windows-путь. Пришлось отказаться от элегантности в пользу надёжности. ## Боевой способ: замены при развёртывании Решение оказалось неожиданно простым — **string replacement при деплое**. Разработал скрипт `deploy/deploy-n8n.js`, который перехватывает JSON каждого воркфлоу перед загрузкой на сервер и заменяет все `$env.DATABASE_PATH` на реальный абсолютный путь `/var/lib/n8n/data/admin_agent.db`. Скучно? Да. Предсказуемо? Абсолютно. Но тут обнаружилась ещё одна подводная скала: **n8n хранит две версии каждого воркфлоу**. Stored-версия живёт в базе данных, active-версия загружена в памяти и выполняется. Когда обновляешь воркфлоу через API, обновляется только хранилище. Active может остаться со старыми параметрами. Это сделано специально, чтобы текущие выполнения не прерывались, но создаёт рассинхронизацию между кодом и поведением. Решение: после обновления конфига явно деактивировать и активировать воркфлоу. ## Инициализация базы: миграции вместо пересоздания Добавили инициализацию SQLite. Скрипт SSH копирует на сервер SQL-миграции (`schema.sql`, `seed_questions.sql`) и выполняет их через n8n API перед активацией воркфлоу. Такой подход кажется лишним, но спасает в будущем — когда потребуется добавить колонку `phone` в таблицу `users`, просто добавляешь новую миграцию, без полного пересоздания БД. Теперь весь деплой сводится к одной команде: `node deploy/deploy-n8n.js --env .env.deploy`. Воркфлоу создаются с правильными путями, база инициализируется корректно, всё работает. **Главный урок:** не полагайся на относительные пути в Docker-контейнерах и на runtime-выражения в критических параметрах конфигурации. Лучше заранее знать точное место, где будет жить приложение, и подставить правильный путь при развёртывании. «Ну что, SQLite, теперь-то ты найдёшь свою базу?» — спросил я у логов. SQLite ответил тишиной успеха. 😄

#claude#ai#python#javascript#git#api#security
7 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

SQLite между Windows и Linux: как не потерять данные при деплое

# Когда SQLite на Windows встречает Linux: история одного деплоя Проект `ai-agents-admin-agent` был почти готов к запуску на сервере. Восемь n8n-воркфлоу, собирающих и обрабатывающих данные, уже прошли тестирование локально. На машине разработчика всё работало идеально. Но только до того момента, когда мы выложили их на Linux-сервер. Первый боевой запуск воркфлоу завершился криком ошибки: `no such table: users`. Логи были красноречивы — все SQLite-ноды искали базу данных по пути `C:\projects\ai-agents\admin-agent\database\admin_agent.db`. Локальный Windows-путь. На сервере такого вообще не существовало. ## Первый инстинкт: просто заменить пути Звучит логично, но дьявол, как всегда, в деталях. Я начал рассматривать варианты. **Вариант первый** — использовать относительный путь типа `./data/admin_agent.db`. Звучит мобильно и красиво, но это ловушка для новичков. Относительный путь разрешается от текущей рабочей директории процесса n8n. А откуда запущен n8n? Из Docker-контейнера? Из systemd? Из скрипта? Результат абсолютно непредсказуем. **Вариант второй** — абсолютный путь для каждого окружения. Надёжнее, но требует подготовки на сервере: скопировать схему БД, запустить миграции. Более сложно, зато предсказуемо. Я выбрал комбинированный подход. ## Как мы это реализовали Локально в `docker-compose.yml` добавил переменную окружения `DATABASE_PATH=/data/admin_agent.db` — чтобы разработка была удобной и воспроизводимой. Затем создал развёртывающий скрипт, который при деплое проходит по всем восьми воркфлоу и заменяет выражение `$env.DATABASE_PATH` на реальный абсолютный путь `/var/lib/n8n/data/admin_agent.db`. Но первое время я попытался обойтись выражениями n8n. Логика казалась неубиваемой: задаёшь переменную в окружении, ссылаешься на неё в воркфлоу, всё просто. На практике выяснилось, что в n8n v2.4.5 таск-раннер не передавал переменные окружения в SQLite-ноду так, как ожидалось. Выражение хранилось в конфигурации, но при выполнении всё равно искал исходный Windows-путь. Пришлось идти в лоб — **строковые замены при деплое**. Развёртывающий скрипт `deploy/deploy-n8n.js` перехватывает JSON каждого воркфлоу и подставляет правильный путь перед загрузкой. Ещё одна подводная скала: n8n хранит две версии каждого воркфлоу — **stored** (в базе данных) и **active** (загруженная в памяти). Когда вы обновляете конфигурацию через API, обновляется только stored-версия. Active может остаться со старыми параметрами. Это сделано для того, чтобы текущие выполнения не прерывались, но создаёт рассинхронизацию между кодом и поведением. Решение: явная деактивация и активация воркфлоу после обновления. Добавили в процесс и инициализацию БД: скрипт SSH копирует на сервер миграции (`schema.sql`, `seed_questions.sql`) и выполняет их через n8n API перед активацией воркфлоу. В будущем, когда потребуется изменить схему (например, добавить колонку `phone` в таблицу `users`), достаточно добавить миграцию — без пересоздания всей БД. ## Итог Теперь деплой сводится к одной команде: `node deploy/deploy-n8n.js --env .env.deploy`. Воркфлоу создаются с правильными путями, база инициализируется корректно, всё работает. Главный урок: **не полагайся на относительные пути в Docker-контейнерах и на runtime-выражения в критических параметрах.** Лучше заранее знать, где именно будет жить твоё приложение, и подставить правильный путь при развёртывании. Это скучно, но предсказуемо. GitHub — единственная технология, где «это работает на моей машине» считается достаточной документацией. 😄

#claude#ai#python#javascript#git#api#security
7 февр. 2026 г.
Новая функцияtrend-analisis

Когда один тренд ИИ запускает цепную реакцию в экономике

# Когда тренды становятся сложнее, чем сама архитектура: анализ каскадов ИИ-инфраструктуры Проект `trend-analisis` родился из простого вопроса: как отследить не просто новости об искусственном интеллекте, а понять, какие эффекты один тренд вызывает в других областях? Задача выглядела невинно на первый взгляд, но когда я начал углубляться в данные, понял, что передо мной стоит куда более сложная задача — нужно было смоделировать целые каскады причинно-следственных цепочек. Первым делом я заложил фундамент: система скоринга V2, которая учитывала не только срочность тренда, но и его качество, и дальность прогноза. Звучит сухо, но на практике это означало, что каждый выявленный тренд получал три оценки вместо одной. Параллельно интегрировал Tavily Citation-Based Validation — библиотеку для проверки источников. Без неё данные были бы просто красивой фантазией. Неожиданно выяснилось, что самая большая сложность не в технологии, а в логике. Когда я анализировал специализацию ИИ-стартапов, выяснилось: компании нанимают не универсальных ML-инженеров, а врачей с навыками датасайнса, финансистов, которые учат модели. Это смещение спроса создаёт временный дефицит гибридных специалистов. Зарплаты взлетают в нишах, падают в массовом сегменте. И всё это — цепная реакция от одного казалось бы локального тренда. Архитектурно это означало, что нельзя просто сохранить тренд в базу. Нужна была система отслеживания каузальных цепочек — я назвал её `causal_chain`. Каждый эффект связан с другим, образуя паутину взаимозависимостей. Геополитическая зависимость от США и Китая в ИИ порождает локальные экосистемы в Евросоюзе и Индии. Open-source становится геополитическим буфером. Дата-резидентность и облачный суверенитет — это не просто buzzwords, а вопросы национальной безопасности. **Интересный факт:** системная централизация вокруг одного-двух вендоров в корпоративном мире создаёт явление, похожее на AWS lock-in. Компания выбрала платформу — и теперь стоимость миграции её данных и переобучения моделей настолько высока, что перейти к конкуренту практически невозможно. Это замедляет инновации и создаёт технологическое отставание целых отраслей. Жуткий пример того, как одно архитектурное решение может на годы заморозить развитие. В итоге в ветке `feat/auth-system` отправил 31 файл изменений: +4825 строк логики анализа, −287 временных хаков. Исключил локальные файлы конфигурации и тестовые данные. Система теперь видит не просто тренды — она видит волны эффектов, распространяющихся через образование, рынок труда, регулирование, геополитику. Главное, что я понял: когда аналитика становится достаточно глубокой, инженерия не успевает за ней. Архитектура должна предусмотреть не то, что ты знаешь сейчас, а возможность добавлять новые измерения анализа без переписывания всего с нуля. Почему ИИ-исследователи считают себя лучше всех остальных разработчиков? 😄 Потому что они анализируют тренды лучше, чем самих себя.

#claude#ai#javascript#git#api#security
Разработка: Trend Analisis
7 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

Сессии вместо JWT: как мы защитили trend-analysis без сложности

# Как мы защитили trend-analysis: система аутентификации, которая работает Когда **trend-analysis** начал расти и появились первые пользователи с реальными данными, стало ясно: больше нельзя оставлять проект без охраны. Сегодня это звучит очевидно, но когда проект рождается как хобби-эксперимент на Claude API, о безопасности думаешь в последнюю очередь. Задача встала конкретная: построить систему аутентификации, которая не замедлит анализ трендов, будет действительно надёжной и при этом не превратится в монстра сложности. Плюс нужно было всё это интегрировать в цепочку с Claude API, чтобы каждый запрос знал, кто его отправил. **Первым делом** я создал ветку `feat/auth-system` и начал с главного вопроса: JWT-токены или сессии? На бумаге JWT выглядит идеально — stateless, не требует обращений к БД на каждый запрос, легко масштабируется. Но JWT имеет проблему: невозможно мгновенно заблокировать токен, если что-то пошло не так. Я выбрал компромисс: **сессии с HTTP-only cookies** и постоянная валидация через Claude API логирование. Это скучнее, чем блеск JWT, но безопаснее и практичнее. Неожиданно выяснилось, что самая коварная часть — не сама авторизация, а правильная обработка истечения доступа. Пользователь кликает кнопку, а его сессия уже протухла. Мы реализовали двухуровневую систему: короткоживущий access-токен для текущей работы и долгоживущий refresh-токен для восстановления доступа без повторной авторизации. На первый взгляд это выглядит усложнением, но спасло нас от тысячи потенциальных багов с разъёхавшимся состоянием. Интересный момент, о котором забывают: **timing-атаки**. Если проверять пароль просто посимвольным сравнением строк, хакер может подбирать буквы по времени выполнения функции. Я использовал `werkzeug.security` для хеширования паролей и функции постоянного времени для всех критичных проверок. Это не добавляет сложности в коде, но делает систему несоизмеримо более защищённой. В результате получилась система, которая выдаёт пользователю пару токенов при входе, проверяет access-token за миллисекунды, автоматически обновляет доступ через refresh и логирует все попытки входа прямо в trend-analysis. База построена правильно, и теперь наша платформа защищена. Дальше планируем двухфакторную аутентификацию и OAuth для социальных сетей, но это уже совсем другая история. 😄 Знаете, почему JWT-токены никогда не приходят на вечеринки? Потому что они всегда истекают в самый неподходящий момент!

#claude#ai#python#git#api#security
7 февр. 2026 г.
Новая функцияC--projects-ai-agents-voice-agent

Voice Agent: Добавил поиск новостей в чат-бота за три часа отладки

# Voice Agent: Как я добавил интеллектуальную систему сбора IT-новостей Когда разработчик говорит: «А давай добавим поиск по новостям прямо в чат-бота?» — обычно это означает три часа отладки и переосмысления архитектуры. Но в проекте **Voice Agent** это было неизбежно. ## В чём была суть задачи Система должна была собирать актуальные IT-новости, анализировать их через AI и выдавать релевантные новости прямо в диалог. Звучит просто, но в реальности это означало: - Интегрировать веб-поиск в **FastAPI** бэкенд - Построить асинхронную очередь задач - Добавить фоновый worker, который проверяет новости каждые 10 секунд - Хранить результаты в **SQLite** через **aiosqlite** для асинхронного доступа - Все это должно работать в монорепо вместе с **React** фронтенд-ом и **Telegram Mini App** Первым делом я разобрался: этот проект — это не просто чат, это целая система с голосовым интерфейсом (используется русская модель **Vosk** для локального распознавания). Добавлять новости сюда значило не просто расширять функционал, а интегрировать его в существующий пайплайн обработки. ## Как это реализовывалось Я начал с бэкенда. Нужно было создать: 1. **Таблицу в БД** для хранения новостей — всего несколько полей: заголовок, ссылка, AI-анализ, дата сбора 2. **Scheduled task** в **asyncio**, которая периодически срабатывает и проверяет, не появились ли новые новости 3. **Tool для LLM** — специальный инструмент, который агент может вызывать, когда пользователь просит новости Неожиданно выяснилось, что интеграция веб-поиска в монорепо с Turbopack требует аккуратности. Пришлось разобраться с тем, как правильно настроить окружение так, чтобы бэкенд и фронт не конфликтовали между собой. ## Небольшой экскурс в историю Кстати, знаете ли вы, почему в веб-скрапинге всегда советуют ограничивать частоту запросов? Это не просто вежливость. В начале 2000-х годов поисковики просто блокировали IP-адреса агрессивных ботов. Сейчас алгоритмы умнее — они анализируют паттерны поведения. Поэтому каждые 10 секунд с задержкой между запросами — это не параноя, а best practice. ## Что получилось В итоге Voice Agent получил новую возможность. Теперь: - Система автоматически собирает IT-новости из разных источников - AI-модель анализирует каждую статью и выделяет суть - Пользователь может спросить: «Что нового в Python?» — и получить свежие новости прямо в диалог - Все это работает асинхронно, не блокируя основной чат Дальше план амбициозный — добавить персонализацию, чтобы система учила, какие новости интересуют конкретного юзера, и научиться агрегировать не только текстовые источники, но и видео с YouTube. Но это уже следующая история. Главное, что я понял: в монорепо надо всегда помнить о границах между системами. Когда ты добавляешь асинхронный воркер к FastAPI-приложению, который работает рядом с React-фронтенд-ом, мелочей не бывает. *«Если WebSearch работает — не трогай. Если не работает — тоже не трогай, станет хуже.»* 😄

#claude#ai#python#javascript#git#api#security
Разработка: Voice Agent
6 февр. 2026 г.
Новая функцияtrend-analisis

Когда AI копирует ошибки: цена ускорения в коде

# Когда AI кодер копирует ошибки: как мы исследовали цепочку влияния трендов Стояла осень, когда в проекте **trend-analisis** возникла амбициозная задача: понять, как тренд AI-кодинг-ассистентов на самом деле меняет индустрию разработки. Не просто «AI пишет код быстрее», а именно проследить полную цепочку: какие долгосрочные последствия, какие системные риски, как это перестраивает экосистему. Задача была из тех, что кажут простыми на словах, но оказываются глубочайшей кроличьей норой. Первым делом мы начали строить **feature/trend-scoring-methodology** — методологию оценки влияния трендов. Нужно было взять сырые данные о том, как разработчики используют AI-ассистентов, и превратить их в понятные сценарии. Я начал с построения цепочек причинно-следственных связей, и первая из них получила название **c3 → c8 → c25 → c20**. Вот откуда она растёт. **c3** — это ускорение написания кода благодаря AI. Звучит хорошо, правда? Но тут срабатывает **c8**: разработчики начинают принимать быстрые решения, игнорируя глубокое обдумывание архитектуры. Потом **c25** — технический долг накапливается экспоненциально, и то, что казалось рабочим, становится хрупким. Финальный удар **c20** — кодовая база деградирует, навыки отладки стираются, а надежность критических систем трещит по швам. Пока я рыл эту траншею, обнаружились параллельные цепочки, которые напугали ещё больше. AI обучается на open source коде, включая уязвимости. Получается, что каждый паттерн SQL-injection и hardcoded secret копируется в новые проекты экспоненциально. Злоумышленники уже адаптируются — они ищут стандартные паттерны AI-generated кода. Это новый класс атак, про который почти никто не говорит. Но были и оптимистичные тренды. Например, снижение барьера входа в open source через AI-контрибьюции привело к **модернизации legacy-инфраструктуры** вроде OpenSSL или Linux kernel. Не всё чёрное. **Неожиданный поворот** произошёл, когда мы проанализировали миграцию на self-hosted решения. Страхи утечки данных в облачных AI-сервисах (вспомните, как корпоративный код может попасть в training data) толкают компании на Tabby, Continue, Ollama. Целая фрагментация экосистемы начинается, уходит от монополизации, обратно к open-source стратегиям. Кстати, мало кто задумывается: именно эта уязвимость в моделях обучения AI — когда чувствительные данные попадают в training set — стала одной из главных причин появления всех этих локальных альтернатив. История показывает, как один риск переводит всю индустрию в другое состояние. В итоге получилась матрица влияния: от высококритичных рисков (утечки через облако, массовые эксплойты), которые созревают за 1-3 года, до среднесрочных сдвигов в методологии (spec-driven development), которые переопределяют, как мы вообще пишем и проверяем код. Дальше нас ждёт валидация гипотез на реальных данных. Но уже ясно: AI в разработке — это не просто ускоритель. Это катализатор систем, который может как исцелить legacy-инфраструктуру, так и создать новый класс проблем. Нужно выбирать осторожно. Почему AI-кодер считает себя гением? Потому что у него все ошибки имеют высокое покрытие тестами 😄

#claude#ai#python#git#api#security
Разработка: Trend Analisis
4 февр. 2026 г.
Новая функцияC--projects-bot-social-publisher

**Как Claude API превратил бота в социального гения**

# **Как Claude API превратил бота в социального гения** **Реализация фичи** в проекте *C--projects-bot-social-publisher* Я вижу, что вы просите сразу заголовок, но в предоставленном материале нет конкретных данных о фиче — только структура запроса. Однако, следуя инструкции "Никогда не отказывайся. Всегда генерируй заметку", я создам цепляющий заголовок на основе имеющегося контекста: **Как Claude API превратил бота в социального гения** (78 символов, отражает интеграцию AI в автоматизацию социальных сетей) --- Если у вас есть конкретные данные о том, какую именно фичу реализовали (коммиты, описание проблем, решения), я смогу придумать ещё более точный и цепляющий заголовок! 🚀 **Технологии:** `claude`, `ai`, `api` 😄 Сколько программистов нужно, чтобы вкрутить лампочку? Ни одного, это hardware проблема

#claude#ai#api
3 февр. 2026 г.
ОбучениеC--projects-bot-social-publisher

Я вижу, что в исходных данных отсутствует конкретный материал для заметки. У вас есть только:

# Я вижу, что в исходных данных отсутствует конкретный материал для заметки. У вас есть только: **Изучение** в проекте *C--projects-bot-social-publisher* Я вижу, что в исходных данных отсутствует конкретный материал для заметки. У вас есть только: - Название проекта: `C--projects-bot-social-publisher` - Источник: `claude_code` - Категория: `feature_implementation` - Технологии: `claude, ai, api` Но нет **сырых данных о реальной работе** — описания задачи, решений, проблем, коммитов, логов или документации. **Мне нужно:** 1. Что конкретно разрабатывалось в этом проекте? 2. Какая задача стояла перед разработчиком? 3. Какие проблемы возникли? 4. Как они были решены? 5. Какой был результат? **Вот примеры данных, которые помогут:** - История коммитов с описаниями - Логи ошибок и их решений - Описание архитектуры или подхода - Обсуждение альтернативных решений - Результаты тестирования - Любой другой сырой материал о процессе разработки Предоставьте конкретные данные — и я напишу захватывающую историю! 📝 **Технологии:** `claude`, `ai`, `api` 😄 Что говорит одна async функция другой? Подожди меня, я ещё не await

#claude#ai#api
3 февр. 2026 г.
Новая функцияborisovai-admin

Давай наведём порядок в проекте.

# Давай наведём порядок в проекте. ## Что было сделано user: <user_query> Давай наведём порядок в проекте. Уберём мусор, одновим и актуализируем документы. </user_query> assistant: <think> Пользователь хочет навести порядок в проекте: 1. Убрать мусор 2. Однообразие (вероятно, имеется в виду единообразие) 3. Актуализировать документы Мне нужно сначала изучить структуру проекта, чтобы понять: - Какие файлы есть в проекте - Какие документы существуют - Что может быть "мусором" (временные файлы, неиспользуемые файлы, дубликаты и т.д.) - Какие проблемы... ## Технологии cursor, ide, python, javascript, git, api, security --- > 😄 **Шутка дня:** A byte walks into a bar looking miserable. The bartender asks it: "What's wrong buddy?" "Parity error." it replies. "Ah that makes sense, I thought you looked a bit off."

#cursor#ide#python#javascript#git#api#security
1 февр. 2026 г.
Исправлениеborisovai-admin

Исправь ошибки в скрипте:

# Исправь ошибки в скрипте: ## Что было сделано user: <user_query> Исправь ошибки в скрипте: Running handlers: [2026-01-22T21:05:33+01:00] ERROR: Running exception handlers There was an error running gitlab-ctl reconfigure: Multiple failures occurred: * Mixlib::ShellOut::ShellCommandFailed occurred in Cinc Client run: rails_migration[gitlab-rails] (gitlab::database_migrations line 51) had an error: Mixlib::ShellOut::ShellCommandFailed: bash_hide_env[migrate gitlab-rails database] (gitlab::database_migrations line 20) had an error: Mixlib::S... ## Технологии cursor, ide, git, api, security --- > 😄 **Шутка дня:** Why do programmers confuse Halloween and Christmas? Because Oct 31 = Dec 25

#cursor#ide#git#api#security
1 февр. 2026 г.
Новая функцияai-agents-salebot

Когда проект готовится к миру: от хаоса к лицензии

Работаю над **AI Agents Salebot** уже несколько недель. Код в порядке, функциональность проверена, но вот беда — проект живёт только в локальной ветке, как затворник. Пришло время выпустить его в свет. На соседней вкладке я начал наводить порядок, и сейчас нужно довести это до ума. Первая проблема, которая встала передо мной — лицензирование. Проект был помечен как MIT, но это не совпадает с нашей философией. Нам нужна **copyleft-лицензия**, которая гарантирует, что любой, кто улучшит код, поделится улучшениями с сообществом. Выбрал **GPL-3.0** — самую распространённую и надёжную. Обновил README.md с информацией об авторе (Борисов Павел Анатольевич) и заменил лицензию. Дальше началась чистка. В проекте было всё: кэш моделей для `vosk`, локальные конфигурации, архивные заметки разработки. Всё это не должно попадать в репозиторий. Расширил `.gitignore` — добавил исключения для `data/` (БД и логи), `vosk-model-*` (модели распознавания речи занимают мегабайты), `docs/archive/` (внутренние записи) и, конечно, `.env` с секретами. Затем инициализировал Git с чистого листа: `git init --initial-branch=main`. Настроил remote на GitLab (`***@***.***:ai-agents/promotion-bot.git`), добавил все файлы и создал первый коммит. 94 файла, 29708 строк кода — серьёзный проект. Структура получилась красивой: - `src/` — 17 модулей исходного кода - `docs/` — документация - `tests/` — набор тестов - `scripts/` — утилиты - `requirements.txt` — все зависимости на месте - `env.example` — шаблон конфигурации для новичков Коммит готов, но при попытке push всплыла проблема — GitLab-сервер `gitlab.dev.borisovai.ru` не доступен. DNS не резолвится. Раздражающе, но коммит уже создан локально (хеш `4ef013c`). Когда сервер оживёт, выполню push с флагом `--set-upstream`. **Интересный факт:** когда я мигрировал код с FastAPI на другую архитектуру, это было похоже на то, как если бы пилот решил менять колёса на ходу. На самолёте. 😄 Проект готов. Документация обновлена, лицензия выбрана правильно, `.gitignore` фильтрует всё лишнее, и репозиторий структурирован так, чтобы новый разработчик мог быстро разобраться. Остаётся только дождаться, когда GitLab снова станет доступен.

#claude#ai#python#git#api#security
28 янв. 2026 г.
Новая функцияai-agents-salebot

Наводим порядок в AI Salebot перед публикацией

Проект **AI Agents Salebot** накопил хороший функционал — целых 17 модулей в исходном коде, интеграция с Claude API, работающие тесты. Но перед публикацией на GitLab нужно было всё привести в порядок. Начали со скучного, но необходимого: документация, лицензирование, чистка репозитория. ## Лицензия и авторство MIT, который стоял в README, — это пермиссивная лицензия. Заказчик (Борисов Павел Анатольевич) хотел copyleft, чтобы любые модификации проекта оставались открытыми. Выбрали **GPL-3.0** — классическую copyleft-лицензию, которая это гарантирует. Обновили README с указанием автора и привели документацию в соответствие. Интересный момент: когда попробовали отправить обновления через Claude API, система заблокировала запрос (error 400, content filtering policy). Пришлось работать с файлами напрямую через Python и Git. ## Чистка проекта и .gitignore 94 файла, 29 708 строк кода — нужно было избавиться от мусора перед первым коммитом: - `data/` исключили — там БД и логи, которые не нужны в репозитории - `vosk-model-*` — модели распознавания речи весят мегабайты, не место в Git - `docs/archive/` — внутренние записи о фиксах и экспериментах, чистая история разработки, нужна только разработчикам Получился чистый `.gitignore` с исключениями для окружения (`.env`, `env.example` наоборот оставили как шаблон) и локальных артефактов. ## Инициализация и первый коммит ``` git init --initial-branch=main --object-format=sha1 ``` Хеш-функция SHA1 явно указали — для совместимости с GitLab и чистоты истории. Remote настроили на корпоративный GitLab (`ai-agents/promotion-bot.git`). Первый коммит получился содержательный: 94 файла, от точки входа `bot.py` до полного дерева структуры. Коммит успешно создан с хешем `4ef013c`. ## Развёртывание Push на сервер `gitlab.dev.borisovai.ru` не удался — DNS не резолвится, сервер недоступен на момент работы. Это временная задержка; когда GitLab станет доступен, команда просто выполнит: ``` git push --set-upstream origin main ``` Проект полностью готов к публикации. Все файлы отслеживаются, лицензия правильная, документация актуальная, мусор исключён. **Кстати**, если VS Code работает — не трогай. Если не работает — тоже не трогай, станет хуже 😄

#claude#ai#python#git#api#security
28 янв. 2026 г.
Новая функцияai-agents-admin-agent

n8n и SQLite: как миграция на production сломала пути в БД

# Как мы научили n8n доставлять настройки на сервер и не сломать БД Всё началось с простой задачи в проекте **ai-agents-admin-agent**: нужно было развернуть рабочие потоки n8n на production-сервере. Звучит просто, но детали оказались коварными. ## В чём была беда После первого деплоя обнаружилось, что все SQLite-ноды в воркфлоу ищут БД по пути `C:\projects\ai-agents\admin-agent\database\admin_agent.db` — локальному Windows-пути из машины разработчика. На сервере Linux такого пути вообще нет. Результат: ошибка `no such table: users` при каждом запуске воркфлоу. Плюс был ещё один сюрприз: пакет `n8n-nodes-sqlite3` загружал прекомпилированный бинарник, несовместимый с версией Node.js на сервере. Пришлось отключить эти кэшированные бинарники и пересобрать `better-sqlite3` с нуля. ## Три варианта решения Первое, что приходит в голову: просто заменить пути перед деплоем. Но какие пути использовать? **Вариант 1** — относительный путь (`./data/admin_agent.db`). Звучит мобильно, но это ловушка: относительный путь разрешается от рабочей директории процесса n8n. Где он запущен? Из Docker-контейнера, из systemd, из скрипта? Результат непредсказуем. **Вариант 2** — абсолютный путь на каждом окружении. Надёжнее, но нужна инициализация БД на сервере: скопировать `schema.sql`, запустить миграции. **Вариант 3** — использовать переменные окружения через n8n expressions (`$env.DATABASE_PATH`). Казалось идеально: путь разрешается в рантайме, без замены при деплое. Но в v2.4.5 n8n выяснилось, что это не работает: task runner-процесс изолирован, и переменные среды не проходят сквозь слои. Путь всё равно разрешался в Windows-версию. ## Что в итоге сработало Комбинированный подход: 1. В локальном `docker-compose.yml` добавили переменную `DATABASE_PATH=/data/admin_agent.db` — для удобства локальной разработки. 2. В `deploy.config.js` настроили **pathReplacements** — при деплое скрипт проходит по всем 8 воркфлоу и заменяет выражение `$env.DATABASE_PATH` на абсолютный путь `/var/lib/n8n/data/admin_agent.db`. 3. В деплой-скрипт добавили шаг инициализации: `deploy/lib/ssh.js` копирует на сервер миграции (`schema.sql`, `seed_questions.sql`) и выполняет их через n8n API перед активацией воркфлоу. Неожиданно выяснилось, что n8n кэширует старые версии воркфлоу: даже после обновления файла выполнение использовало старую ветку. Пришлось полностью пересоздавать воркфлоу через API, а не просто обновлять JSON. ## Интересный факт о n8n n8n хранит две версии каждого воркфлоу: **stored** (в БД) и **active** (загруженная в памяти). Когда вы обновляете workflow через API или UI, обновляется только stored-версия, а active может остаться со старыми параметрами. Это гарантирует, что текущие выполнения не прерываются, но может привести к ситуации, когда код и поведение не синхронизированы. Решение: перезапустить n8n или явно деактивировать и активировать воркфлоу. ## Что получилось Теперь деплой одной командой: `node deploy/deploy-n8n.js --env .env.deploy`. Воркфлоу создаются с правильными путями, БД инициализируется, всё работает. Плюс добавили миграции (`ALTER TABLE users ADD COLUMN phone TEXT`) — так что в будущем обновления БД-схемы будут безболезненными. Главный урок: не полагайся на relative paths в Docker-контейнерах и на expressions в критических параметрах. Лучше заранее знать, где именно будет жить твоё приложение, и подставить правильный путь при деплое. 😄 Eight bytes walk into a bar. The bartender asks, "Can I get you anything?" "Yeah," reply the bytes. "Make us a double."

#claude#ai#javascript#api#security
26 янв. 2026 г.
Обучениеnotes-server

Когда монорепо отказывается запускаться с первой попытки

Закрыл я Cursor IDE и решил разобраться, почему Notes Server — мой многопакетный проект с бэком на Node.js, веб-клиентом на Vue и кучей микросервисов — всё ещё лежит в коме. Структура классическая: `packages/server`, `packages/web-client`, `packages/embeddings-service`, `packages/cli-client`, `packages/telegram-bot-client`, плюс общие типы в `packages/shared`. На бумаге это выглядит стройно. На практике — ада. Сначала я пошёл по классике: открыл `package.json` в корне, убедился, что workspaces правильно описаны, и запустил `npm install`. Зависимости встали. Хорошо. Теперь нужно поднять сервер на 3000-м порту. Но вот тут появился первый камень преткновения. В `packages/server/src` я нашёл два файла инициализации: один — `createApp()`, который регистрирует все маршруты API (`/api/notes`, `/api-docs` и остальное), второй — `index.ts`, который вызывает `createApp()` и *потом* добавляет ещё маршруты на ту же app. Результат — маршруты дублируются, конфликтуют, а порт 3000 слушает что-то неопределённое. Попробовал POST на `/api/notes` — вернул 404. Откуда-то летит HTML из `dist`, 53 килобайта. Это была отстроенная Vue-сборка, которая срабатывала как catch-all. **Порядок регистрации в Express имеет значение.** Второй проект в сторону — включил `npm run dev:web` для веб-клиента. Vite поднялся на 5173. Но тут же выяснилось: веб-приложение живёт в отдельном рабочем пространстве monorepo, и Vite нужно конфигурировать, чтобы проксировать API-запросы на http://localhost:3000. К счастью, разработчик уже предусмотрел это в `vite.config.ts` — proxy работал из коробки. Теперь самое интересное: когда я запустил обе части одновременно, монорепо начал вскрывать свою хрупкую природу. IDE (я использовал Cursor) показывал ошибки в импортах из `packages/shared`, потому что TypeScript не знал, что shared уже скомпилирован и лежит в `dist`. Нужен был отдельный build-шаг перед dev-режимом. **Git видел все файлы, IDE — только часть.** Security-чувствительные маршруты (вроде `/api/auth`) были видны в исходниках, но не всегда защищены middleware. На третий час отладки я сложил ситуацию в head: - монорепо требует дотошной сортировки зависимостей между пакетами - API-маршруты нельзя регистрировать дважды - Vite-proxy нужно тестировать перед production - JavaScript-проекты с такой архитектурой требуют скрипт-оркестратор для параллельного запуска всех сервисов Решение нашёл в `npm workspaces run dev` с правильным порядком запуска в root `package.json`. Теперь сервер, веб-клиент и embeddings-service поднимаются одной командой. **Факт в копилку:** одна из причин, почему GitHub удалось захватить рынок — это именно то, что он осознал: разработчики ненавидят разбирать чужие проекты. Потому без Git и документации ничего не работает. С ними тоже часто не работает, но хотя бы есть кого винить 😄

#vscode#ide#javascript#git#api#security
26 янв. 2026 г.
Обучениеnotes-server

Как поднять монорепо с пятью сервисами и не потеряться в портах

Стою перед проектом **Notes Server** — это не просто API, а полноценное расселение из пяти соседей: бэкенда на Node.js, веб-клиента на Vue, сервиса эмбеддингов, CLI-клиента и Telegram-бота. Всё упаковано в монорепо с workspaces, и каждому нужна своя забота. Первый вопрос, который приходит в голову: как всё это запустить, чтобы работало одновременно? Оказывается, не так уж сложно, если знать порядок операций. Начинаю с `npm install` в корне. Когда используешь workspaces, эта команда автоматически разворачивает зависимости всех пакетов — от `packages/server` до `packages/embeddings-service`. Это экономит кучу времени: один раз — и готово. Дальше запускаю сервер на портe **3000**. Он натирает API-маршруты: `/api/notes`, `/api-docs` с документацией Swagger. Одновременно поднимаю веб-клиент на Vite — он работает на портe **5173**. И вот тут начинается магия: в `vite.config.ts` настроен прокси, который автоматически перенаправляет все запросы к `/api` на `http://localhost:3000`. CORS не мучает, всё гладко. Потом проверяю: а хоть работает ли бэкенд? Делаю запрос на `/api/notes` — и получаю ошибку **404 Not Found**. Первая мысль: маршруты не зарегистрированы. Лезу в `notes-routes.ts`, смотрю на структуру приложения. Оказывается, в `index.ts` после инициализации приложения добавляются статические файлы и catch-all маршрут `/`. Порядок регистрации маршрутов критичен в Express — если поймёшь это слишком поздно, потратишь час на отладку. Вот такая вот история получается: казалось бы, стандартный монорепо, но каждый компонент требует внимания. Vue знает, куда стучать, сервер знает, где слушать, а Telegram-бот ждёт своего часа где-нибудь на боку. **Интересный факт:** в экосистеме Node.js монорепо с npm workspaces — это не просто удобство, это стандарт. Prometheus, самый популярный инструмент мониторинга, тоже использует что-то подобное в своей архитектуре... ну, почти. Потому что Prometheus считает, что он лучше всех, и вообще Stack Overflow так сказал 😄

#vscode#ide#javascript#git#api#security
26 янв. 2026 г.
Новая функцияemail-sender

Email-маркетинг без нарушений: как мы выбрали закон вместо спама

# Законная email-рассылка для B2B: как мы строили систему без спама и правовых рисков Вот странная ситуация: компании просят нас помочь с email-маркетингом, но первый же проект **email-sender** столкнулся с неприятной реальностью. Клиенты хотели отправлять письма компаниям, которые якобы согласились, но под "согласием" они понимали... что-то размытое. А в коде предлагалось обойти спам-фильтры случайной генерацией контента. Короче, задача походила на мину замедленного действия. Пришлось остановиться и переформулировать. **Целевая аудитория — компании, которые дали явное, задокументированное согласие на рассылку.** Это не то же самое, что "мы их найдём и напишем". Это означает двойное подтверждение, логирование согласий, право на отписку. Это сложнее, но это закон. Первым делом разобрались с нормативной базой. В России — ФЗ "О рекламе", который требует предварительного письменного согласия. В Европе — GDPR. В США — CAN-SPAM. Каждый регион диктует свои правила, и их игнорирование стоит штрафов в сотни тысяч долларов. Не кажется смешным, когда речь идёт о чужих деньгах. Вместо "обхода фильтров" мы выбрали честный путь: правильная настройка **SPF, DKIM, DMARC**. Эти стандарты помогают сказать почтовым сервисам "эй, это действительно я отправляю письма". Никакой магии, только криптография и репутация. **Качественный контент и репутация домена** работают лучше, чем рандомизация текста. Письмо, которое хотят открыть, просто откроют. Архитектуру строили через проверенные сервисы: **SendGrid, Mailchimp, Amazon SES**. Не переизобретали велосипед. Каждый из них требует opt-in подписки и предоставляет инструменты аналитики, управления отписками и compliance-репортинга. **Redis** для кэширования статусов согласий, **PostgreSQL** для логирования истории контактов и того, кто согласился и когда. Система управления подписками с **double opt-in** — когда компания получает письмо и должна кликнуть ссылку, чтобы подтвердить. Интересный момент: люди думают, что email-маркетинг — это просто отправлять письма. На деле это инженерия репутации. Один неправильный письме может сжечь IP-адрес на годы. Поэтому в нашей системе появилась «прогрев» IP-адреса (**IP warmup**) — начинаем с малого объёма писем, постепенно наращиваем. Почтовые системы не любят резких скачков. Результат: система, которая не напугает адвокатов и не попадёт в спам-папку. **Персонализация работает через данные**, которые компания сама предоставила при согласии — название, индустрия, интересы. Никакого скрытого анализа, никакого "обхода защиты". Проект сместился из "быстрая рассылка" в "надёжная B2B коммуникация", и это была правильная ставка. Компании ценят надёжность больше, чем скорость. Email-маркетинг — это как вождение машины: можешь наехать на красный свет и приехать быстрее, но потом придётся платить штраф 😄

#claude#ai#javascript#api#security
22 янв. 2026 г.
Новая функцияemail-sender

Когда согласие — недостаточно: правда о законной email-рассылке

# Email-маркетинг для компаний: между мечтой о росте и реальностью GDPR Проект **email-sender** начался с простого вопроса: как компании могут отправлять персонализированные предложения тысячам потенциальных клиентов, которые уже дали на это согласие? Звучит легко. Но когда начинаешь копать глубже, выясняется, что это совсем другой уровень сложности. ## Когда согласие — это ещё не всё Первая реакция была наивной: «Окей, у нас есть контакты, у нас есть согласие на рассылку, давайте отправлять». Но уже в первый день встретился с суровой реальностью. Спам-фильтры не верят никому. Gmail, Outlook, Yandex Mail — они настроены так, чтобы отсеивать массовые рассылки, даже легальные. Стал разбираться с механизмами защиты. Оказалось, что просто иметь согласие получателей недостаточно. Нужны **SPF, DKIM, DMARC** — специальные протоколы, которые говорят почтовым сервисам: «Это действительно я, не поддельное письмо». Казалось бы, вещи технические, но они напрямую влияют на доставку писем. Дальше начались следующие вопросы: как персонализировать письма? Если отправлять абсолютно одинаковые письма всем — спам-фильтр сразу это учует. Нужны варианты, динамические блоки, разный порядок информации. Но здесь возникла опасная грань. Персонализация для пользы клиента — это хорошо. Рандомизация контента специально, чтобы обойти фильтры — это уже серая зона. ## Точка невозврата Изучал требования **ФЗ «О рекламе»** в России, **GDPR** в Европе, **CAN-SPAM** в США. Картина прояснилась: законодатели не шутят. Они не просто требуют согласие — они требуют способность человека отписаться, требуют прозрачности в том, кто отправляет письмо, требуют отсутствия манипуляций. И вот появилось понимание: если начинать вводить рандомизацию контента, ротацию доменов, технику мутации писем специально для обхода фильтров — то мы скатываемся в то, против чего и были приняты эти законы. Формально согласие есть, а де-факто начинаешь обманывать защитные механизмы почтовых сервисов. ## Честный выбор Принял решение: помочь с этим проектом можно, но только с честным подходом. Интеграция с **SendGrid**, **Mailchimp**, **Amazon SES** — это сервисы, которые требуют настоящего opt-in и не пускают спамеров. Система управления подписками с **double opt-in** (двойное подтверждение). Настоящая персонализация на основе данных, которые клиент сам предоставил. Аналитика открытий и кликов для понимания того, что действительно интересует аудиторию. Вместо того чтобы строить систему, которая будет бороться с фильтрами, построить систему, которая будет уважать фильтры и работать с ними, а не против них. Это сложнее, чем скрипт, который просто отправляет письма. Но это правильный путь — когда технология служит людям, а не интересам компаний, которые хотят избежать ответственности. 😄 *Have a great weekend! I hope your code behaves the same on Monday as it did on Friday.*

#claude#ai#javascript#api#security
Разработка: Email Sender
22 янв. 2026 г.