На работе возникла задача проверить, безопасен ли код, который пишут наши программисты. Спойлер: нет. И почти сразу появилась «гениальная идея»: давайте внедрим SonarQube, прогоним код через линтер — и всё узнаем.
К сожалению, один линтер не сделает код безопасным. Безопасность приложения — это не одна галочка в CI/CD, а несколько уровней контроля: код, зависимости, Docker-образы, конфигурации, секреты, права доступа и поведение приложения после деплоя.
На уровне кода нужны SAST-инструменты и линтеры. Они помогают находить потенциальные уязвимости ещё до сборки и выката: небезопасную работу с входными данными, SQL-инъекции, XSS, ошибки авторизации и другие проблемные места. Здесь могут пригодиться SonarQube, GitLab SAST, Semgrep.
Отдельно нужно проверять зависимости. Даже если собственный код написан аккуратно, уязвимость может приехать через стороннюю библиотеку. Для этого подходят GitLab Dependency Scanning, OWASP Dependency-Check, Snyk, потому что безопасность ломается не только там, где писал ты сам.
Secret Detection нужен, чтобы не утащить в репозиторий токены, пароли, приватные ключи, API-ключи и другие секреты. Это отдельная боль: один случайно закоммиченный
Container scanning нужен, чтобы не тащить в production уязвимые базовые образы и системные пакеты. Здесь можно использовать GitLab Container Scanning, Trivy, Grype, Clair, Snyk Container. Отдельная история — DAST: он проверяет уже работающее приложение как «чёрный ящик» и показывает проблемы, которые проявляются только в запущенной системе.
Есть ещё инфраструктурная безопасность: права доступа, сетевые политики, секреты, централизованная авторизация, аудит и мониторинг. Это уже не про один сканер, а про общую дисциплину эксплуатации: кто имеет доступ, где лежат секреты, какие действия логируются и как быстро можно заметить проблему после деплоя.
Вывод простой: линтер — это только первая линия обороны. Нормальная безопасность начинается там, где проверки закрывают весь путь приложения: от кода, зависимостей и секретов до контейнера, инфраструктуры и реального поведения в production. Всё остальное — приятная иллюзия контроля.
Вот хорошие видео на эту тему.
DevSecOps для самых маленьких
https://www.youtube.com/watch?v=jdSyadPFycE
С какого конца начинать безопасную разработку
https://www.youtube.com/watch?v=UHD0q8QW_rM
А теперь немного новостей. У компании Rebrain летом появился формат «Открытый микрофон»: каждый может прийти со своим докладом и выступить на аудиторию. Я подумал: а почему бы и да, у меня же есть статья «Когда связист становится разработчиком, программирование Asterisk на практике» https://vk.com/@programmer_path-kogda-svyazist-stanovitsya-razrabotchikom-programmirovanie-a
Я выполнил необходимые требования к спикеру, и мой доклад приняли. Так что 24 июня проведу вебинар на тему статьи. Можно зарегистрироваться здесь: https://rebrainme.com/webinars
Открою тайну: доклад, презентация и демонстрации ещё не готовы. Точнее готовы, но не до конца. Но за две недели я точно их доделаю, потому что инженерная магия обычно начинается сразу после слов «ну тут осталось совсем немного».
К сожалению, один линтер не сделает код безопасным. Безопасность приложения — это не одна галочка в CI/CD, а несколько уровней контроля: код, зависимости, Docker-образы, конфигурации, секреты, права доступа и поведение приложения после деплоя.
На уровне кода нужны SAST-инструменты и линтеры. Они помогают находить потенциальные уязвимости ещё до сборки и выката: небезопасную работу с входными данными, SQL-инъекции, XSS, ошибки авторизации и другие проблемные места. Здесь могут пригодиться SonarQube, GitLab SAST, Semgrep.
Отдельно нужно проверять зависимости. Даже если собственный код написан аккуратно, уязвимость может приехать через стороннюю библиотеку. Для этого подходят GitLab Dependency Scanning, OWASP Dependency-Check, Snyk, потому что безопасность ломается не только там, где писал ты сам.
Secret Detection нужен, чтобы не утащить в репозиторий токены, пароли, приватные ключи, API-ключи и другие секреты. Это отдельная боль: один случайно закоммиченный
.env или ключ доступа может стоить дороже, чем десяток замечаний от линтера. Для таких проверок можно использовать GitLab Secret Detection, Gitleaks, TruffleHog, detect-secrets, GitGuardian.Container scanning нужен, чтобы не тащить в production уязвимые базовые образы и системные пакеты. Здесь можно использовать GitLab Container Scanning, Trivy, Grype, Clair, Snyk Container. Отдельная история — DAST: он проверяет уже работающее приложение как «чёрный ящик» и показывает проблемы, которые проявляются только в запущенной системе.
Есть ещё инфраструктурная безопасность: права доступа, сетевые политики, секреты, централизованная авторизация, аудит и мониторинг. Это уже не про один сканер, а про общую дисциплину эксплуатации: кто имеет доступ, где лежат секреты, какие действия логируются и как быстро можно заметить проблему после деплоя.
Вывод простой: линтер — это только первая линия обороны. Нормальная безопасность начинается там, где проверки закрывают весь путь приложения: от кода, зависимостей и секретов до контейнера, инфраструктуры и реального поведения в production. Всё остальное — приятная иллюзия контроля.
Вот хорошие видео на эту тему.
DevSecOps для самых маленьких
https://www.youtube.com/watch?v=jdSyadPFycE
С какого конца начинать безопасную разработку
https://www.youtube.com/watch?v=UHD0q8QW_rM
А теперь немного новостей. У компании Rebrain летом появился формат «Открытый микрофон»: каждый может прийти со своим докладом и выступить на аудиторию. Я подумал: а почему бы и да, у меня же есть статья «Когда связист становится разработчиком, программирование Asterisk на практике» https://vk.com/@programmer_path-kogda-svyazist-stanovitsya-razrabotchikom-programmirovanie-a
Я выполнил необходимые требования к спикеру, и мой доклад приняли. Так что 24 июня проведу вебинар на тему статьи. Можно зарегистрироваться здесь: https://rebrainme.com/webinars
Открою тайну: доклад, презентация и демонстрации ещё не готовы. Точнее готовы, но не до конца. Но за две недели я точно их доделаю, потому что инженерная магия обычно начинается сразу после слов «ну тут осталось совсем немного».
YouTube
DevSecOps для самых маленьких. Иван Кондратьев | KazHackStan 2022
В докладе мы рассмотрим различный инструментарий, как opensource так и enterprise, который повысит качество разрабатываемого кода (продукта) в контексте информациионной безопасности.
👍3
Почти всю неделю на работе настраивал SonarQube. Задача из тех, которые сначала выглядят как «ну сейчас быстро подключим», а потом внезапно превращаются в квест с токенами, правами, GitLab и кучей мелких нюансов. Чтобы нормально связать GitLab и SonarQube, нужна туева хуча разных токенов с разными правами. Но я справился.
Сканирование нашего основного проекта занимает примерно 20–30 минут. Важно понимать: SonarQube сканирует весь проект, а не отдельные коммиты. Для проверки коммитов лучше использовать GitLab SAST, но это уже задача на следующую неделю. Один инструмент не закрывает всю безопасность, он просто подсвечивает часть проблем.
Посмотрел результаты сканирования — наш код, мягко говоря, не безопасный. Я даже не думал, что можно допускать такие банальные ошибки, но проект старый, поэтому возможно всё. Хорошая новость в том, что самые критические проблемы уже пофиксили. Плохая — теперь понятно, сколько ещё работы впереди.
По SonarQube рекомендую два видео:
«Никита Грызлов. Мастер-класс. SonarQube. В омут с головой» https://www.youtube.com/watch?v=wFwG8bKuEw4
«Святослав Кокурин из Naumen “Внедряем SonarQube без шума и пыли”» https://www.youtube.com/watch?v=LI36tWHd-Tc
SonarQube — мощная и сложная система промышленного уровня. Если смотрите в сторону DevSecOps, разобраться с ней точно стоит.
В пятницу прилетела ещё одна задача. На проде периодически падают сервисы-консьюмеры, которые обрабатывают очереди RabbitMQ. Только падают они хитро: процессы в системе есть, память и процессор потребляют, вроде бы «работают», но очереди уже не обрабатывают. Формально живые, по факту бесполезные.
Решили реализовать временный костыль. Если количество консьюмеров по очереди становится равно нулю, в Zabbix срабатывает триггер, который запускает скрипт и убивает нужный сервис на проде. Эти сервисы автоматически стартуют каждую минуту, поэтому простой минимальный. Более правильно, конечно, задать программистам вопрос: почему код зависает. Но по собственному опыту знаю: поймать плавающую ошибку, которая возникает раз в несколько дней, — отдельный вид боли.
Bash-скрипт, который убивает сервис по SSH, я написал. Главный вопрос был в другом: как проверить его работу и не устроить пожар на проде. Если специально ронять рабочие службы, меня сожгут где-нибудь между переговоркой и серверной. А Zabbix ещё и выполняет скрипты довольно молча: сработало, не сработало, где упало — разбирайся сам.
В итоге сделал фейковый Item
Получилась вполне рабочая схема: сам создал ошибку, сам её обработал, сам проверил цепочку от Zabbix до скрипта. И главное — на проде ничего ломать не пришлось. Иногда лучший тест — это не героически уронить боевую систему, а спокойно собрать безопасную имитацию проблемы.
Кстати, напоминаю: в следующую среду, 24 июня 2026 года, в 18:00 по МСК, я провожу вебинар «Когда связист становится разработчиком: программирование Asterisk на практике» https://rebrainme.com/webinars/kogda-svyazist-stanovitsya-razrabotchikom-programmirovanie-asterisk-na-praktike
Приходите, расскажу про программирование Asterisk, Dialplan, AGI, AMI, ARI и про тот момент, когда обычная телефония внезапно превращается в разработку.
Сканирование нашего основного проекта занимает примерно 20–30 минут. Важно понимать: SonarQube сканирует весь проект, а не отдельные коммиты. Для проверки коммитов лучше использовать GitLab SAST, но это уже задача на следующую неделю. Один инструмент не закрывает всю безопасность, он просто подсвечивает часть проблем.
Посмотрел результаты сканирования — наш код, мягко говоря, не безопасный. Я даже не думал, что можно допускать такие банальные ошибки, но проект старый, поэтому возможно всё. Хорошая новость в том, что самые критические проблемы уже пофиксили. Плохая — теперь понятно, сколько ещё работы впереди.
По SonarQube рекомендую два видео:
«Никита Грызлов. Мастер-класс. SonarQube. В омут с головой» https://www.youtube.com/watch?v=wFwG8bKuEw4
«Святослав Кокурин из Naumen “Внедряем SonarQube без шума и пыли”» https://www.youtube.com/watch?v=LI36tWHd-Tc
SonarQube — мощная и сложная система промышленного уровня. Если смотрите в сторону DevSecOps, разобраться с ней точно стоит.
В пятницу прилетела ещё одна задача. На проде периодически падают сервисы-консьюмеры, которые обрабатывают очереди RabbitMQ. Только падают они хитро: процессы в системе есть, память и процессор потребляют, вроде бы «работают», но очереди уже не обрабатывают. Формально живые, по факту бесполезные.
Решили реализовать временный костыль. Если количество консьюмеров по очереди становится равно нулю, в Zabbix срабатывает триггер, который запускает скрипт и убивает нужный сервис на проде. Эти сервисы автоматически стартуют каждую минуту, поэтому простой минимальный. Более правильно, конечно, задать программистам вопрос: почему код зависает. Но по собственному опыту знаю: поймать плавающую ошибку, которая возникает раз в несколько дней, — отдельный вид боли.
Bash-скрипт, который убивает сервис по SSH, я написал. Главный вопрос был в другом: как проверить его работу и не устроить пожар на проде. Если специально ронять рабочие службы, меня сожгут где-нибудь между переговоркой и серверной. А Zabbix ещё и выполняет скрипты довольно молча: сработало, не сработало, где упало — разбирайся сам.
В итоге сделал фейковый Item
test.trigger, который меняю через команду zabbix_sender -z 127.0.0.1 -s "rabbitmq" -k test.trigger -o 1. К нему привязал тестовый триггер, который запускает мой скрипт. Отладку делал через логи, потому что без логов в таких задачах быстро начинается гадание на кофейной гуще. Когда ошибка больше не нужна, возвращаю всё обратно: zabbix_sender -z 127.0.0.1 -s "rabbitmq" -k test.trigger -o 0.Получилась вполне рабочая схема: сам создал ошибку, сам её обработал, сам проверил цепочку от Zabbix до скрипта. И главное — на проде ничего ломать не пришлось. Иногда лучший тест — это не героически уронить боевую систему, а спокойно собрать безопасную имитацию проблемы.
Кстати, напоминаю: в следующую среду, 24 июня 2026 года, в 18:00 по МСК, я провожу вебинар «Когда связист становится разработчиком: программирование Asterisk на практике» https://rebrainme.com/webinars/kogda-svyazist-stanovitsya-razrabotchikom-programmirovanie-asterisk-na-praktike
Приходите, расскажу про программирование Asterisk, Dialplan, AGI, AMI, ARI и про тот момент, когда обычная телефония внезапно превращается в разработку.
YouTube
Никита Грызлов. Мастер-класс. SonarQube. В омут с головой
Поговорим про SonarQube – не только о том, что он может дать, но и о том, как его установить, быстро запустить и произвести в нем базовые настройки.
Доклад в виде статьи: https://infostart.ru/public/1661973/
Доклад в виде статьи: https://infostart.ru/public/1661973/
👍5❤1
Иногда одна демонстрация на вебинаре превращается в две недели борьбы с окружением, зависимостями и чужими настройками. А одна строка в
Провёл вебинар «Когда связист становится разработчиком: программирование Asterisk на практике» на Rebrain. И понял одну простую вещь: самое сложное в докладе — не выступление, а всё, что происходит до него.
Тему я заявлял как обзор технологий Asterisk для разработчиков. Планировал рассказать про четыре инструмента: Dialplan, AGI (Asterisk Gateway Interface), AMI (Asterisk Manager Interface) и ARI (Asterisk REST Interface).
Но реальность быстро внесла свои коррективы. Выяснилось, что ARI даже для простого примера требует слишком глубокого погружения. Тратить несколько недель только ради одной демонстрации не хотелось, поэтому пришлось отказаться.
Со всем остальным тоже оказалось не так просто. На работе эти технологии давно функционируют, и я уже не замечаю, насколько большое окружение за ними стоит. Например, для демонстрации AMI понадобился CDR. Начал поднимать всё с нуля — и сразу выяснилось, что «из коробки» оно не работает.
CDR потребовал MySQL. MySQL оказался привязан не к тому интерфейсу. Исправил. Затем выяснилось, что структура базы данных не подходит под мою версию Asterisk. Переделал. Чтобы показать простую функцию — соединить клиента с тем менеджером, с которым он разговаривал ранее, — пришлось буквально перешерстить полобраза Ubuntu.
Потом решил выложить исходники на GitHub. Часть проекта работала в Docker, поэтому пришлось ещё разбираться с GitHub Actions, чтобы автоматически публиковать Docker-образы. Огромный пласт работы, который никто во время вебинара даже не увидит.
И так было практически с каждой демонстрацией. Со стороны кажется: «показать небольшой пример». На практике — две недели настройки, поиска несовместимостей и чтения документации.
В итоге всё заработало. Но появилась другая проблема. Доклад, который я рассчитывал провести за полтора часа, уложился примерно в сорок минут.
На вебинар зарегистрировались 115 человек. Формат был «открытый микрофон»: после выступления можно заполнить анкету с обратной связью.
И тут финальный штрих.
Анкету заполнил... один человек.
Возможно, тема оказалась слишком узкой. Менеджер Rebrain уже предложила выступить ещё раз в августе. Похоже, в следующий раз придётся выбирать что-то более массовое. Узкоспециализированные темы интересны далеко не всем.
На работе тоже приключение.
Написал скрипт. Всё работает, но он пишет логи. Если ничего с ними не делать, через какое-то время они разрастутся до гигабайтов и благополучно съедят всё свободное место. Логичное решение — настроить
Я уже успел проверить файловую систему, права, каталоги и конфигурацию. Всё выглядело абсолютно нормально.
Оказалось, проблема вообще не там.
Если посмотреть настройки сервиса:
то выясняется, что
Решение оказалось элементарным:
Пять минут на исправление.
И почти неделя на поиск причины.
Если вам кажется, что какая-то задача простая, скорее всего, вы просто ещё не начали её делать.
Обе истории показывают, что в IT самая сложная часть часто скрыта за самой обычной задачей. То, что выглядит как быстрый пример или простая настройка, на деле может обернуться неделями подготовки и поиска неочевидной причины. Поэтому к любому «это же быстро» лучше сразу относиться с долей скепсиса.
systemd — в почти недельный квест.Провёл вебинар «Когда связист становится разработчиком: программирование Asterisk на практике» на Rebrain. И понял одну простую вещь: самое сложное в докладе — не выступление, а всё, что происходит до него.
Тему я заявлял как обзор технологий Asterisk для разработчиков. Планировал рассказать про четыре инструмента: Dialplan, AGI (Asterisk Gateway Interface), AMI (Asterisk Manager Interface) и ARI (Asterisk REST Interface).
Но реальность быстро внесла свои коррективы. Выяснилось, что ARI даже для простого примера требует слишком глубокого погружения. Тратить несколько недель только ради одной демонстрации не хотелось, поэтому пришлось отказаться.
Со всем остальным тоже оказалось не так просто. На работе эти технологии давно функционируют, и я уже не замечаю, насколько большое окружение за ними стоит. Например, для демонстрации AMI понадобился CDR. Начал поднимать всё с нуля — и сразу выяснилось, что «из коробки» оно не работает.
CDR потребовал MySQL. MySQL оказался привязан не к тому интерфейсу. Исправил. Затем выяснилось, что структура базы данных не подходит под мою версию Asterisk. Переделал. Чтобы показать простую функцию — соединить клиента с тем менеджером, с которым он разговаривал ранее, — пришлось буквально перешерстить полобраза Ubuntu.
Потом решил выложить исходники на GitHub. Часть проекта работала в Docker, поэтому пришлось ещё разбираться с GitHub Actions, чтобы автоматически публиковать Docker-образы. Огромный пласт работы, который никто во время вебинара даже не увидит.
И так было практически с каждой демонстрацией. Со стороны кажется: «показать небольшой пример». На практике — две недели настройки, поиска несовместимостей и чтения документации.
В итоге всё заработало. Но появилась другая проблема. Доклад, который я рассчитывал провести за полтора часа, уложился примерно в сорок минут.
На вебинар зарегистрировались 115 человек. Формат был «открытый микрофон»: после выступления можно заполнить анкету с обратной связью.
И тут финальный штрих.
Анкету заполнил... один человек.
Возможно, тема оказалась слишком узкой. Менеджер Rebrain уже предложила выступить ещё раз в августе. Похоже, в следующий раз придётся выбирать что-то более массовое. Узкоспециализированные темы интересны далеко не всем.
На работе тоже приключение.
Написал скрипт. Всё работает, но он пишет логи. Если ничего с ними не делать, через какое-то время они разрастутся до гигабайтов и благополучно съедят всё свободное место. Логичное решение — настроить
logrotate. Только вот логи почему-то не ротируются.logrotate падал с ошибкой:Файловая система доступна только для чтения
Я уже успел проверить файловую систему, права, каталоги и конфигурацию. Всё выглядело абсолютно нормально.
Оказалось, проблема вообще не там.
Если посмотреть настройки сервиса:
systemctl cat logrotate.service
ProtectSystem=full
то выясняется, что
systemd запускает logrotate в режиме, где каталоги /usr, /boot и /etc доступны только для чтения. А мой лог как раз лежал внутри /usr/local/....Решение оказалось элементарным:
systemctl edit logrotate.service
[Service]
ReadWritePaths=/usr/local/scripts
Пять минут на исправление.
И почти неделя на поиск причины.
Если вам кажется, что какая-то задача простая, скорее всего, вы просто ещё не начали её делать.
Обе истории показывают, что в IT самая сложная часть часто скрыта за самой обычной задачей. То, что выглядит как быстрый пример или простая настройка, на деле может обернуться неделями подготовки и поиска неочевидной причины. Поэтому к любому «это же быстро» лучше сразу относиться с долей скепсиса.
👍2
На работе возникла задача: посчитать количество минут переговоров отдела продаж и сервиса. Казалось бы, что может пойти не так? Ответ: всё.
Все записи разговоров у нас хранятся в одной папке, файлов там тысячи, очень много тысяч. Я написал bash-скрипт, который в 12 потоков перебирает записи, определяет длительность, вытаскивает дату и пытается понять, кто кому звонил. Первый этап прошёл относительно бодро: машина шумит, скрипт работает, файлы считаются — красота.
Дальше нужно было выделить из этого океана звонков продажи и сервис. Я вспомнил, что у нас же есть адресная книга: достаточно взять оттуда номера нужных отделов, скрестить со звонками — и готово. Наивный оптимистичный человек.
Адресная книга у нас в Bitrix24, но не просто адресная книга, а какой-то встроенный сайт в iframe, который, судя по всему, проектировали в состоянии творческого безумия: экспортировать нормально нельзя, копировать удобно нельзя, жить с этим тоже нельзя. Решил сделать скриншот.
Скриншот получился длинный, очень длинный: сотрудников много, страданий тоже. Скормил скриншот ChatGPT, она посмотрела на это произведение корпоративного UX и бодро сказала, что такое не распознаётся. Ладно.
Режем длинный JPG на куски и собираем PDF:
PDF распознал через FineReader, он превратил результат в DOCX. Но DOCX ChatGPT ест плохо, зато Markdown — уже гораздо бодрее. Конвертируем:
Телефонная книга была устроена примерно так: «Продажи»\ 101 Иванов\ 102 Петров. А мне нужно было: 101 Продажи\ 102 Продажи, то есть вместо фамилии — название отдела. Тут ChatGPT наконец-то сказала: «Вот теперь нормально, работаем» — и сделала нужное преобразование.
Дальше я скрестил распознанную телефонную книгу со списком звонков через сводную таблицу в Excel, и тут барабанная дробь: больше всех в организации звонит отдел «Прочее». Мощный отдел, сильная команда — никто их не видел, но звонят они больше всех.
Начал разбираться. Оказалось, что отделов продаж у нас не один: кто-то работает с юрлицами, кто-то с ИП, кто-то с отдельными направлениями, а в отчёте всё это нужно видеть укрупнённо. Потом выяснилось, что адресная книга не соответствует реальности: кто-то уволился, кого-то приняли, номера переехали, часть сотрудников живёт в системе как археологический слой.
Пошёл вручную актуализировать телефоны менеджеров по продажам в Bitrix24, добавил уволенных, потому что старые звонки тоже должны попадать в отчёт. Количество «Прочего» уменьшилось, но не сдалось.
Потом выяснилось, что имя телефона не всегда соответствует человеку: условно, телефон когда-то был закреплён за Ивановым, Иванов ушёл, пришёл Петров, а телефон всё ещё называется «Иванов». Петров работает, Иванов звонит — всё логично.
Затем руководитель задал очень правильный вопрос: — А где менеджеры по продажам московского офиса? Их не было вообще. Оказалось, что они работают с корпоративных SIM-карт, то есть в нашей красивой статистике по АТС их звонков просто нет. Теперь на следующей неделе буду созваниваться с оператором связи и выяснять, как настроить запись звонков с корпоративных SIM-карт.
Но и это был не финал. Оказалось, что звонки сервисных инженеров из-за особенностей нашей корпоративной системы пишутся в отдельную папку, конечно же. Снова запускаю сканер в 12 потоков, теперь уже по этой папке — маразм крепчал, еноты пели.
Потом нашёлся ещё большой пласт автоматических звонков от корпоративной системы, они тоже попадали в общую статистику и делали вид, что являются полезной человеческой активностью. В итоге только с третьей или четвёртой попытки удалось свести всё воедино.
Вывод простой: задача «просто посчитать минуты разговоров» легко превращается в археологическую экспедицию по корпоративным данным, где каждый новый слой отвечает на один вопрос и задаёт три новых. Прогулка по граблям с завязанными глазами удалась.
Все записи разговоров у нас хранятся в одной папке, файлов там тысячи, очень много тысяч. Я написал bash-скрипт, который в 12 потоков перебирает записи, определяет длительность, вытаскивает дату и пытается понять, кто кому звонил. Первый этап прошёл относительно бодро: машина шумит, скрипт работает, файлы считаются — красота.
Дальше нужно было выделить из этого океана звонков продажи и сервис. Я вспомнил, что у нас же есть адресная книга: достаточно взять оттуда номера нужных отделов, скрестить со звонками — и готово. Наивный оптимистичный человек.
Адресная книга у нас в Bitrix24, но не просто адресная книга, а какой-то встроенный сайт в iframe, который, судя по всему, проектировали в состоянии творческого безумия: экспортировать нормально нельзя, копировать удобно нельзя, жить с этим тоже нельзя. Решил сделать скриншот.
Скриншот получился длинный, очень длинный: сотрудников много, страданий тоже. Скормил скриншот ChatGPT, она посмотрела на это произведение корпоративного UX и бодро сказала, что такое не распознаётся. Ладно.
Режем длинный JPG на куски и собираем PDF:
magick input.jpg -crop x3000 +repage page_%03d.jpg
magick page_*.jpg output.pdf
PDF распознал через FineReader, он превратил результат в DOCX. Но DOCX ChatGPT ест плохо, зато Markdown — уже гораздо бодрее. Конвертируем:
pandoc /mnt/d/Телефоны.docx -t gfm -o phones.md
Телефонная книга была устроена примерно так: «Продажи»\ 101 Иванов\ 102 Петров. А мне нужно было: 101 Продажи\ 102 Продажи, то есть вместо фамилии — название отдела. Тут ChatGPT наконец-то сказала: «Вот теперь нормально, работаем» — и сделала нужное преобразование.
Дальше я скрестил распознанную телефонную книгу со списком звонков через сводную таблицу в Excel, и тут барабанная дробь: больше всех в организации звонит отдел «Прочее». Мощный отдел, сильная команда — никто их не видел, но звонят они больше всех.
Начал разбираться. Оказалось, что отделов продаж у нас не один: кто-то работает с юрлицами, кто-то с ИП, кто-то с отдельными направлениями, а в отчёте всё это нужно видеть укрупнённо. Потом выяснилось, что адресная книга не соответствует реальности: кто-то уволился, кого-то приняли, номера переехали, часть сотрудников живёт в системе как археологический слой.
Пошёл вручную актуализировать телефоны менеджеров по продажам в Bitrix24, добавил уволенных, потому что старые звонки тоже должны попадать в отчёт. Количество «Прочего» уменьшилось, но не сдалось.
Потом выяснилось, что имя телефона не всегда соответствует человеку: условно, телефон когда-то был закреплён за Ивановым, Иванов ушёл, пришёл Петров, а телефон всё ещё называется «Иванов». Петров работает, Иванов звонит — всё логично.
Затем руководитель задал очень правильный вопрос: — А где менеджеры по продажам московского офиса? Их не было вообще. Оказалось, что они работают с корпоративных SIM-карт, то есть в нашей красивой статистике по АТС их звонков просто нет. Теперь на следующей неделе буду созваниваться с оператором связи и выяснять, как настроить запись звонков с корпоративных SIM-карт.
Но и это был не финал. Оказалось, что звонки сервисных инженеров из-за особенностей нашей корпоративной системы пишутся в отдельную папку, конечно же. Снова запускаю сканер в 12 потоков, теперь уже по этой папке — маразм крепчал, еноты пели.
Потом нашёлся ещё большой пласт автоматических звонков от корпоративной системы, они тоже попадали в общую статистику и делали вид, что являются полезной человеческой активностью. В итоге только с третьей или четвёртой попытки удалось свести всё воедино.
Вывод простой: задача «просто посчитать минуты разговоров» легко превращается в археологическую экспедицию по корпоративным данным, где каждый новый слой отвечает на один вопрос и задаёт три новых. Прогулка по граблям с завязанными глазами удалась.
👍9
Кажется, компьютерное зрение — это просто: показал ИИ фотографию и получил готовый инженерный отчёт. На практике между фотографией и отчётом внезапно вырастает небольшой конвейер из трёх агентов, чистки данных, проверок и 53 страниц документации. Потому что за каждой «простой» задачей обычно скрывается целая система обязательных шагов.
На работе возникла задача: есть фотография со списком ошибок, по которым нужно найти описания и подготовить инженерный отчёт по устранению. Думаете, ИИ увидит фотографию и сразу выдаст правильный результат одним промптом? Вот чтобы да — так таки совсем даже нет. ИИ хорошо выполняет ровно одно действие, поэтому задачу пришлось разбирать на отдельные этапы.
Сначала первый агент распознаёт фотографию и возвращает одну длинную строку текста. Эту строку нужно почистить от лишних пробелов, переносов, непечатных символов и прочего мусора. Мусор на входе, мусор на выходе — магии не произошло. Только после этого результат можно передавать следующему агенту.
Второй агент выполняет классификацию и превращает строку в JSON: выделяет дату, коды ошибок и остальные данные. Иногда в поле даты внезапно появляются значения из XIX века — видимо, ИИ решил, что мы работаем с архивами времён паровых машин. Но результат снова приходится проверять и чистить, потому что
И только третий агент получает проверенные коды и пишет инженерный отчёт. Разной степени фэнтезийности, поэтому его результат тоже нельзя принимать на веру. В итоге простая задача превращается в мультиагентную систему из трёх агентов. Хорошо хоть без общей памяти, иначе приключение стало бы ещё интереснее.
Дополнительно вся система должна работать в четыре потока. На этой неделе я в основном писал документацию со всеми ошибками, исключениями и частными случаями — получилось 53 страницы. По собственному опыту знаю: программируешь обработку редкой ошибки, которая, как тебе кажется, должна происходить раз в тысячу лет. На проде она встречается пару раз в день, и возникает немой вопрос: «Как?»
Есть замечательное видео «Как AI помогает запускать стартапы: вайбкодинг, OpenClaw и ограничения для бизнеса» https://www.youtube.com/watch?v=kQAWgM_b0XI. Разработчик написал ИИ-сервис: загружаешь фотографию с телефона и получаешь готовое фото на паспорт или визу. Вроде бы банальная задача — убрать фон. Но фотография должна соответствовать уйме бюрократических требований, причём для каждой страны они разные, и простая идея снова превращается в задачу со звёздочкой.
В четверг был на встрече тюменских IT-шников, в том числе обсуждали резюме. Вспомнили старое резюме одного матёрого айтишника: текущее место работы — гардероб, хобби — женский баскетбол в качестве зрителя. С лёгкой долей абсурда, но зато запоминается. Я понял, что определённо что-то в этой жизни упустил.
В общем, ИИ действительно умеет распознавать фотографии и писать отчёты. Нужно только построить вокруг него систему из агентов, фильтров, проверок, многопоточности и документации на 53 страницы. А так — всё просто.
На работе возникла задача: есть фотография со списком ошибок, по которым нужно найти описания и подготовить инженерный отчёт по устранению. Думаете, ИИ увидит фотографию и сразу выдаст правильный результат одним промптом? Вот чтобы да — так таки совсем даже нет. ИИ хорошо выполняет ровно одно действие, поэтому задачу пришлось разбирать на отдельные этапы.
Сначала первый агент распознаёт фотографию и возвращает одну длинную строку текста. Эту строку нужно почистить от лишних пробелов, переносов, непечатных символов и прочего мусора. Мусор на входе, мусор на выходе — магии не произошло. Только после этого результат можно передавать следующему агенту.
Второй агент выполняет классификацию и превращает строку в JSON: выделяет дату, коды ошибок и остальные данные. Иногда в поле даты внезапно появляются значения из XIX века — видимо, ИИ решил, что мы работаем с архивами времён паровых машин. Но результат снова приходится проверять и чистить, потому что
0 и D, l и 1 выглядят слишком похоже. Код ошибки может казаться правильным, но при этом не существовать в принципе. Затем убираем дубли, выбираем последние ошибки и применяем остальные правила обработки.И только третий агент получает проверенные коды и пишет инженерный отчёт. Разной степени фэнтезийности, поэтому его результат тоже нельзя принимать на веру. В итоге простая задача превращается в мультиагентную систему из трёх агентов. Хорошо хоть без общей памяти, иначе приключение стало бы ещё интереснее.
Дополнительно вся система должна работать в четыре потока. На этой неделе я в основном писал документацию со всеми ошибками, исключениями и частными случаями — получилось 53 страницы. По собственному опыту знаю: программируешь обработку редкой ошибки, которая, как тебе кажется, должна происходить раз в тысячу лет. На проде она встречается пару раз в день, и возникает немой вопрос: «Как?»
Есть замечательное видео «Как AI помогает запускать стартапы: вайбкодинг, OpenClaw и ограничения для бизнеса» https://www.youtube.com/watch?v=kQAWgM_b0XI. Разработчик написал ИИ-сервис: загружаешь фотографию с телефона и получаешь готовое фото на паспорт или визу. Вроде бы банальная задача — убрать фон. Но фотография должна соответствовать уйме бюрократических требований, причём для каждой страны они разные, и простая идея снова превращается в задачу со звёздочкой.
В четверг был на встрече тюменских IT-шников, в том числе обсуждали резюме. Вспомнили старое резюме одного матёрого айтишника: текущее место работы — гардероб, хобби — женский баскетбол в качестве зрителя. С лёгкой долей абсурда, но зато запоминается. Я понял, что определённо что-то в этой жизни упустил.
В общем, ИИ действительно умеет распознавать фотографии и писать отчёты. Нужно только построить вокруг него систему из агентов, фильтров, проверок, многопоточности и документации на 53 страницы. А так — всё просто.
YouTube
Как AI помогает запускать стартапы: вайбкодинг, OpenClaw и ограничения для бизнеса / Антон Плешивцев
🔹 Присоединяйся к курсу «ИИ для разработчиков» https://ru.hexlet.io/programs/ai-for-developers?utm_source=youtube
Можно ли сегодня построить прибыльный IT-бизнес практически в одиночку? И почему одни разработчики с помощью AI уже запустили продукты и автоматизировали…
Можно ли сегодня построить прибыльный IT-бизнес практически в одиночку? И почему одни разработчики с помощью AI уже запустили продукты и автоматизировали…
👍2
Неделя получилась неожиданно насыщенной. Большую часть времени разбирался с сервисом обработки чеков: где-то боролся с ограничениями ChatGPT, где-то ловил совсем неожиданные баги в OCR, а заодно успел немного повоевать со спамерами в Telegram.
На работе продолжаю делать микросервис для обработки чеков с ошибками. В качестве LLM использую ChatGPT и Codex. В целом всё отлично, но периодически упираюсь в лимиты тарифа за $20. Оказалось, проблема далеко не только у меня. Решение нашлось простое: купить второй аккаунт и переключаться между ними через
Параллельно разбирался с безопасностью загрузки изображений. Обрабатываю фотографии чеков, и нейросеть настоятельно рекомендовала проверять файл не только по расширению, но и по сигнатуре. Решил разобраться, зачем это нужно. Оказалось, это вполне распространённая атака: под видом JPG можно прислать исполняемый файл или другой вредоносный контент. Поэтому доверять файлам из интернета только потому, что они заканчиваются на
Потом решил проверить систему на нестандартных данных. Вместо фотографии чека отправил... фотографию котика. Казалось бы, сервис должен быстро ответить: «Это не чек». Но вместо этого он ушёл в глубокие раздумья.
Начал разбираться. Сначала выяснилось, что таймаут распознавания по умолчанию — десять минут. А с тремя попытками ожидание легко превращалось в полчаса. Сократил время до минуты. Но ошибка всё равно не возвращалась.
Следующая находка оказалась интереснее. Сообщение с ошибкой уходило не в очередь результатов, а в DLQ (Dead Letter Queue — очередь сообщений, которые не удалось обработать). А ведь DLQ предназначена для незапланированных серьёзных сбоев, а не для ситуации «пользователь прислал не тот документ». Исправил маршрутизацию.
И тут появился ещё один сюрприз. OCR каким-то образом сумел извлечь из фотографии котика 42 байта текста. До сих пор не понимаю, что именно он там увидел. В итоге пришлось добавить ещё один уровень проверки: если после OCR получается бессмысленный набор символов, данные отправляются на классификатор, который уже принимает решение, похож ли результат на настоящий чек.
В итоге понял простую вещь. Если пользователь прислал ерунду, корректно сообщить ему, что это именно ерунда, зачастую сложнее, чем обработать правильный документ. Именно такие пограничные случаи обычно и отнимают больше всего времени.
Ещё одна неожиданная история произошла с Telegram-каналом. За несколько дней туда набежало больше десяти тысяч ботов. Очень много аккаунтов с арабскими и китайскими именами. Для защиты поставил Lols Anti Spam (
Ради интереса посмотрел, что именно блокировал бот. В основном это были предложения лёгкого заработка, крипта, займы и прочие «уникальные возможности». Поэтому небольшое напоминание.
Прежде чем кликнуть по очередной ссылке с обещанием быстрого богатства, задайте себе простой вопрос: почему совершенно незнакомый человек хочет сделать богаче именно вас? Скорее всего, заработать собирается он, а платить будете вы.
По моему опыту, 99,99% подобных схем — обычный обман.
И сразу отвечу на возможный вопрос. Мой канал — это просто дневник IT-инженера. Здесь нет розыгрышей, криптосхем, инвестиционных советов или предложений «заработать миллион за вечер». Только реальные рабочие задачи, технологии и инженерные находки.
Как говорил Козьма Прутков: «Бди!»
На работе продолжаю делать микросервис для обработки чеков с ошибками. В качестве LLM использую ChatGPT и Codex. В целом всё отлично, но периодически упираюсь в лимиты тарифа за $20. Оказалось, проблема далеко не только у меня. Решение нашлось простое: купить второй аккаунт и переключаться между ними через
codex-auth — https://github.com/loongphy/codex-auth. По сути, утилита просто подменяет файл auth.json с текущим токеном ChatGPT. Мелочь, а экономит нервы.Параллельно разбирался с безопасностью загрузки изображений. Обрабатываю фотографии чеков, и нейросеть настоятельно рекомендовала проверять файл не только по расширению, но и по сигнатуре. Решил разобраться, зачем это нужно. Оказалось, это вполне распространённая атака: под видом JPG можно прислать исполняемый файл или другой вредоносный контент. Поэтому доверять файлам из интернета только потому, что они заканчиваются на
.jpg, точно не стоит.Потом решил проверить систему на нестандартных данных. Вместо фотографии чека отправил... фотографию котика. Казалось бы, сервис должен быстро ответить: «Это не чек». Но вместо этого он ушёл в глубокие раздумья.
Начал разбираться. Сначала выяснилось, что таймаут распознавания по умолчанию — десять минут. А с тремя попытками ожидание легко превращалось в полчаса. Сократил время до минуты. Но ошибка всё равно не возвращалась.
Следующая находка оказалась интереснее. Сообщение с ошибкой уходило не в очередь результатов, а в DLQ (Dead Letter Queue — очередь сообщений, которые не удалось обработать). А ведь DLQ предназначена для незапланированных серьёзных сбоев, а не для ситуации «пользователь прислал не тот документ». Исправил маршрутизацию.
И тут появился ещё один сюрприз. OCR каким-то образом сумел извлечь из фотографии котика 42 байта текста. До сих пор не понимаю, что именно он там увидел. В итоге пришлось добавить ещё один уровень проверки: если после OCR получается бессмысленный набор символов, данные отправляются на классификатор, который уже принимает решение, похож ли результат на настоящий чек.
В итоге понял простую вещь. Если пользователь прислал ерунду, корректно сообщить ему, что это именно ерунда, зачастую сложнее, чем обработать правильный документ. Именно такие пограничные случаи обычно и отнимают больше всего времени.
Ещё одна неожиданная история произошла с Telegram-каналом. За несколько дней туда набежало больше десяти тысяч ботов. Очень много аккаунтов с арабскими и китайскими именами. Для защиты поставил Lols Anti Spam (
@LolsBot) и несколько дней методично чистил подписчиков. В итоге количество сократилось примерно до тысячи.Ради интереса посмотрел, что именно блокировал бот. В основном это были предложения лёгкого заработка, крипта, займы и прочие «уникальные возможности». Поэтому небольшое напоминание.
Прежде чем кликнуть по очередной ссылке с обещанием быстрого богатства, задайте себе простой вопрос: почему совершенно незнакомый человек хочет сделать богаче именно вас? Скорее всего, заработать собирается он, а платить будете вы.
По моему опыту, 99,99% подобных схем — обычный обман.
И сразу отвечу на возможный вопрос. Мой канал — это просто дневник IT-инженера. Здесь нет розыгрышей, криптосхем, инвестиционных советов или предложений «заработать миллион за вечер». Только реальные рабочие задачи, технологии и инженерные находки.
Как говорил Козьма Прутков: «Бди!»
GitHub
GitHub - Loongphy/codex-auth: A CLI tool to switch and manage Codex accounts
A CLI tool to switch and manage Codex accounts. Contribute to Loongphy/codex-auth development by creating an account on GitHub.
❤5👍5
Иногда самые интересные инженерные решения появляются не на этапе проектирования, а уже когда система почти готова — именно так у меня и получилось с микросервисом по обработке чеков.
Пока разбирался с архитектурой, наткнулся на интересную идею. После основной нейронки рекомендуют запускать ещё одну, которая проверяет результат её работы. Подход называется LLM-as-a-Judge.
Логика простая. Промпт — это не программа, а скорее набор рекомендаций. Нейронка может интерпретировать их по-своему: придумать новый код ошибки, добавить несуществующую деталь устройства или сделать ещё что-нибудь творческое. Как поётся в песне: «Фантазёр, ты меня называла».
Первые версии промпта для проверяющей модели оказались слишком суровыми. Почти на каждый ответ она выдавала что-то вроде: «Представленные рекомендации недостаточно обоснованы и не опираются на фактические данные и подтверждённые взаимосвязи». Да здравствует математическая логика. В итоге пришлось смягчить требования: теперь она отбрасывает только откровенные фантазии, а не пытается переписать весь результат. Фронтендер уже начал писать код под мой сервис. Посмотрим, как всё это покажет себя в реальной работе.
Параллельно решил попробовать Codex для написания скриптов на PowerShell. Остался приятно удивлён. Для системного администратора это очень сильный язык: работа с базами данных, почтой, сетью, журналированием, многопоточностью — всё есть из коробки. Отдельный плюс — PowerShell уже встроен в Windows вместе с IDE. Если вы администрируете Windows-серверы или просто хотите автоматизировать домашний компьютер, язык точно стоит изучить. Осваивается он достаточно быстро, а пользы приносит много.
Ещё посмотрел курс «Летняя сессия Яндекса» по AI. В основном рассказывали про экосистему Яндекса и её продукты. Если сравнивать с ChatGPT или DeepSeek, то какого-то принципиального технологического разрыва я не увидел. Зато у Яндекса хорошо выстроена именно экосистема: можно собрать полноценный проект, практически не выходя за пределы их сервисов. До Amazon Web Services по масштабу ещё далеко, но развивается очень активно. Поэтому курс могу смело рекомендовать: https://www.youtube.com/@YandexCloudPlatform/streams
Всё больше убеждаюсь, что основная работа при внедрении ИИ — это не выбор модели. Намного важнее построить вокруг неё правильный процесс: проверить входные данные, проконтролировать результат и не дать нейронке слишком увлечься собственной фантазией. Тогда она действительно начинает экономить время, а не создавать новую работу.
Пока разбирался с архитектурой, наткнулся на интересную идею. После основной нейронки рекомендуют запускать ещё одну, которая проверяет результат её работы. Подход называется LLM-as-a-Judge.
Логика простая. Промпт — это не программа, а скорее набор рекомендаций. Нейронка может интерпретировать их по-своему: придумать новый код ошибки, добавить несуществующую деталь устройства или сделать ещё что-нибудь творческое. Как поётся в песне: «Фантазёр, ты меня называла».
Первые версии промпта для проверяющей модели оказались слишком суровыми. Почти на каждый ответ она выдавала что-то вроде: «Представленные рекомендации недостаточно обоснованы и не опираются на фактические данные и подтверждённые взаимосвязи». Да здравствует математическая логика. В итоге пришлось смягчить требования: теперь она отбрасывает только откровенные фантазии, а не пытается переписать весь результат. Фронтендер уже начал писать код под мой сервис. Посмотрим, как всё это покажет себя в реальной работе.
Параллельно решил попробовать Codex для написания скриптов на PowerShell. Остался приятно удивлён. Для системного администратора это очень сильный язык: работа с базами данных, почтой, сетью, журналированием, многопоточностью — всё есть из коробки. Отдельный плюс — PowerShell уже встроен в Windows вместе с IDE. Если вы администрируете Windows-серверы или просто хотите автоматизировать домашний компьютер, язык точно стоит изучить. Осваивается он достаточно быстро, а пользы приносит много.
Ещё посмотрел курс «Летняя сессия Яндекса» по AI. В основном рассказывали про экосистему Яндекса и её продукты. Если сравнивать с ChatGPT или DeepSeek, то какого-то принципиального технологического разрыва я не увидел. Зато у Яндекса хорошо выстроена именно экосистема: можно собрать полноценный проект, практически не выходя за пределы их сервисов. До Amazon Web Services по масштабу ещё далеко, но развивается очень активно. Поэтому курс могу смело рекомендовать: https://www.youtube.com/@YandexCloudPlatform/streams
Всё больше убеждаюсь, что основная работа при внедрении ИИ — это не выбор модели. Намного важнее построить вокруг неё правильный процесс: проверить входные данные, проконтролировать результат и не дать нейронке слишком увлечься собственной фантазией. Тогда она действительно начинает экономить время, а не создавать новую работу.
YouTube
Yandex Cloud
Yandex Cloud — технологическая платформа Яндекса для создания и развития цифровых продуктов.
Номер заявления в РКН: 4962839754
Номер заявления в РКН: 4962839754
👍3❤2
Иногда кажется, что самая сложная часть корпоративной системы — написать код. А потом начинаешь выяснять, кто какую полку в Wiki должен видеть, и внезапно оказываешься где-то между Keycloak, OLAP-кубом и многомерной вселенной, в которой возможно вообще всё.
У нас есть большая корпоративная система Service Desk (SD), и захотели к ней прикрутить документацию в виде Wiki. Выбор пал на BookStack https://www.bookstackapp.com/. BookStack мне понравился своей концепцией книжного шкафа: есть шкаф, на нём полки, в полках книги, у книг главы и страницы. Всё довольно наглядно и хорошо ложится на корпоративную документацию.
Но дальше захотелось, чтобы пользователь один раз авторизовался в Service Desk и с этой же учёткой автоматически входил в BookStack. Это называется SSO — Single Sign-On, или «единый вход». Между SD и BookStack в качестве прослойки используется Keycloak https://www.keycloak.org/, который и должен реализовать всю эту историю через протокол OpenID Connect (OIDC).
Keycloak оказался системой весьма замысловатой и, мягко говоря, не самой дружелюбной. Например, пользователи и клиенты — совершенно разные сущности, как группы и роли. Самое интересное, что сущности с похожими названиями есть ещё и в BookStack, только означают они уже немного другое. В какой-то момент начинаешь подозревать, что главная задача Keycloak — не авторизовать пользователя, а проверить твою веру в человечество.
Но техническая часть оказалась не самой сложной. В голове у бизнеса пока есть только крупные мазки и общее желание: «нужно разграничить доступ». А как только начинаешь выяснять, какой пользователь, с какой ролью, из какого подразделения должен видеть конкретную полку, книгу или главу, возникает дикая таксономия во главе с OLAP-кубом. Получается многомерная вселенная прав доступа, в которой возможно практически всё.
Был даже созвон с нашим корпоративным архитектором. Посмотрели на эту неведомую зверушку, обсудили варианты, и архитектор взял паузу подумать, как всё это правильно реализовать. Поэтому SSO пока не доведён до конца. В очередной раз выяснилось, что настроить протокол проще, чем формализовать человеческое «ну вот эти должны видеть это, а эти вроде бы не должны».
Кроме того, было обучение по Cursor — ИИ постепенно внедряется в нашей фирме. Радикально нового я узнал мало: уже успел пройти путь от простых промптов до построения мультиагентных систем. Но несколько интересных приёмов всё-таки вынес, а один практически сразу пригодился в работе.
Сейчас пишу небольшой скрипт, который отправляет записи телефонных разговоров на расшифровку в Яндекс. Под Windows программа прекрасно работает, а под FreeBSD падала с ошибкой. Я дал Codex доступ на сервер только к определённой папке и показал ошибку. Codex сам подключился к FreeBSD, разобрался в окружении и нашёл причину: у утилиты
Раньше в такой ситуации я бы «обмазался» логами, запустил удалённую отладку и потратил несколько часов, причём не факт, что сразу нашёл бы причину. Здесь Codex справился примерно за полчаса. Вот такое применение ИИ мне нравится гораздо больше разговоров про то, как завтра он заменит всех программистов: дал конкретную проблему, ограничил область работы — и получил несколько сэкономленных часов.
Похоже, с ИИ всё постепенно приходит к довольно приземлённой модели. Он не отменяет сложность систем и точно не способен придумать за бизнес, кому какую полку показывать. Зато там, где раньше приходилось часами копаться в логах и различиях между Linux и FreeBSD, уже вполне способен взять часть работы на себя. И вот это действительно полезно.
У нас есть большая корпоративная система Service Desk (SD), и захотели к ней прикрутить документацию в виде Wiki. Выбор пал на BookStack https://www.bookstackapp.com/. BookStack мне понравился своей концепцией книжного шкафа: есть шкаф, на нём полки, в полках книги, у книг главы и страницы. Всё довольно наглядно и хорошо ложится на корпоративную документацию.
Но дальше захотелось, чтобы пользователь один раз авторизовался в Service Desk и с этой же учёткой автоматически входил в BookStack. Это называется SSO — Single Sign-On, или «единый вход». Между SD и BookStack в качестве прослойки используется Keycloak https://www.keycloak.org/, который и должен реализовать всю эту историю через протокол OpenID Connect (OIDC).
Keycloak оказался системой весьма замысловатой и, мягко говоря, не самой дружелюбной. Например, пользователи и клиенты — совершенно разные сущности, как группы и роли. Самое интересное, что сущности с похожими названиями есть ещё и в BookStack, только означают они уже немного другое. В какой-то момент начинаешь подозревать, что главная задача Keycloak — не авторизовать пользователя, а проверить твою веру в человечество.
Но техническая часть оказалась не самой сложной. В голове у бизнеса пока есть только крупные мазки и общее желание: «нужно разграничить доступ». А как только начинаешь выяснять, какой пользователь, с какой ролью, из какого подразделения должен видеть конкретную полку, книгу или главу, возникает дикая таксономия во главе с OLAP-кубом. Получается многомерная вселенная прав доступа, в которой возможно практически всё.
Был даже созвон с нашим корпоративным архитектором. Посмотрели на эту неведомую зверушку, обсудили варианты, и архитектор взял паузу подумать, как всё это правильно реализовать. Поэтому SSO пока не доведён до конца. В очередной раз выяснилось, что настроить протокол проще, чем формализовать человеческое «ну вот эти должны видеть это, а эти вроде бы не должны».
Кроме того, было обучение по Cursor — ИИ постепенно внедряется в нашей фирме. Радикально нового я узнал мало: уже успел пройти путь от простых промптов до построения мультиагентных систем. Но несколько интересных приёмов всё-таки вынес, а один практически сразу пригодился в работе.
Сейчас пишу небольшой скрипт, который отправляет записи телефонных разговоров на расшифровку в Яндекс. Под Windows программа прекрасно работает, а под FreeBSD падала с ошибкой. Я дал Codex доступ на сервер только к определённой папке и показал ошибку. Codex сам подключился к FreeBSD, разобрался в окружении и нашёл причину: у утилиты
flock немного отличаются ключи в Linux и FreeBSD.Раньше в такой ситуации я бы «обмазался» логами, запустил удалённую отладку и потратил несколько часов, причём не факт, что сразу нашёл бы причину. Здесь Codex справился примерно за полчаса. Вот такое применение ИИ мне нравится гораздо больше разговоров про то, как завтра он заменит всех программистов: дал конкретную проблему, ограничил область работы — и получил несколько сэкономленных часов.
Похоже, с ИИ всё постепенно приходит к довольно приземлённой модели. Он не отменяет сложность систем и точно не способен придумать за бизнес, кому какую полку показывать. Зато там, где раньше приходилось часами копаться в логах и различиях между Linux и FreeBSD, уже вполне способен взять часть работы на себя. И вот это действительно полезно.
BookStack
BookStack is a simple, open-source, self-hosted, easy-to-use platform for organising and storing information.
👍10
За неделю AI успел побыть у меня программистом и уборщиком файловой помойки. И неожиданно именно последнее оказалось одним из самых полезных применений. Иногда не нужно просить AI сделать стартап на миллион — достаточно заставить его разобрать папку, к которой сам боишься подходить годами.
Завершил мини-проект по загрузке записей звонков в Yandex SpeechSense и заодно познакомился с gRPC. До этого я в основном работал с REST, который древний как мамонт, но всё ещё живее всех живых. А Яндекс решил сделать API SpeechSense через gRPC — технологии уже десять лет, но для меня это оказался новый и довольно интересный мир.
Если сильно упрощать, в REST клиент и сервер обычно обмениваются JSON: формат понятный человеку, но довольно многословный — имена полей повторяются в каждом объекте, а данные передаются текстом. В gRPC контракты сервисов заранее описываются в
Мне gRPC понравился именно этой строгостью: контракты определены заранее, меньше пространства для самодеятельности, данные передаются компактнее. Но хоронить REST я бы точно не стал — он будет жить ещё очень и очень долго. Просто теперь у меня появился ещё один инструмент и понимание, зачем он вообще нужен. Вот хорошее видео «gRPC для новичков» https://www.youtube.com/watch?v=DGBLwNN-YM4
Ладно, программирование — это всё хорошо. А может AI решить какую-нибудь совершенно рядовую задачу прямо на моём компьютере? У меня есть папка
Смысл PARA простой: вся информация раскладывается всего по четырём папкам. Projects (Проекты) — то, над чем работаю сейчас и у чего есть конкретный результат и финишная черта. Areas (Сферы) — постоянные зоны ответственности без даты окончания: работа, финансы, обучение, Telegram-канал. Если это нужно регулярно поддерживать в актуальном состоянии — ему сюда.
Resources (Ресурсы) — статьи, документация, инструкции, книги и прочие материалы, с которыми сейчас ничего делать не нужно, но они могут пригодиться потом. Archives (Архивы) — завершённое, устаревшее и больше не требующее внимания. Получается простой фильтр: есть конкретный результат —
Я указал Codex на папку
На этом я не остановился и таким же образом упорядочил по PARA заметки в Obsidian, заодно добавив иконки. Забавно, что одним из самых полезных применений AI оказался не написанный им код, а банальная уборка файловой помойки. Подробней о PARA можно прочитать здесь «Четыре папки против хаоса: PARA — это просто» https://singularity-app.ru/blog/metod-para/
Похоже, самые полезные сценарии AI начинаются не там, где он должен сделать за тебя что-то великое. А там, где можно наконец отдать ему работу, которую ты сам откладывал годами.
Завершил мини-проект по загрузке записей звонков в Yandex SpeechSense и заодно познакомился с gRPC. До этого я в основном работал с REST, который древний как мамонт, но всё ещё живее всех живых. А Яндекс решил сделать API SpeechSense через gRPC — технологии уже десять лет, но для меня это оказался новый и довольно интересный мир.
Если сильно упрощать, в REST клиент и сервер обычно обмениваются JSON: формат понятный человеку, но довольно многословный — имена полей повторяются в каждом объекте, а данные передаются текстом. В gRPC контракты сервисов заранее описываются в
.proto-файлах, данные сериализуются через Protocol Buffers (Protobuf) и передаются поверх HTTP/2 в бинарном формате. В итоге меньше данных гоняется по сети, есть строгая типизация, а клиент и сервер заранее знают, чем именно должны обмениваться.Мне gRPC понравился именно этой строгостью: контракты определены заранее, меньше пространства для самодеятельности, данные передаются компактнее. Но хоронить REST я бы точно не стал — он будет жить ещё очень и очень долго. Просто теперь у меня появился ещё один инструмент и понимание, зачем он вообще нужен. Вот хорошее видео «gRPC для новичков» https://www.youtube.com/watch?v=DGBLwNN-YM4
Ладно, программирование — это всё хорошо. А может AI решить какую-нибудь совершенно рядовую задачу прямо на моём компьютере? У меня есть папка
Docum, которая за годы превратилась в натуральную файлопомойку. Разобрать её руками можно, но страшно даже представить, сколько времени уйдёт. И тут я вспомнил про подход PARA.Смысл PARA простой: вся информация раскладывается всего по четырём папкам. Projects (Проекты) — то, над чем работаю сейчас и у чего есть конкретный результат и финишная черта. Areas (Сферы) — постоянные зоны ответственности без даты окончания: работа, финансы, обучение, Telegram-канал. Если это нужно регулярно поддерживать в актуальном состоянии — ему сюда.
Resources (Ресурсы) — статьи, документация, инструкции, книги и прочие материалы, с которыми сейчас ничего делать не нужно, но они могут пригодиться потом. Archives (Архивы) — завершённое, устаревшее и больше не требующее внимания. Получается простой фильтр: есть конкретный результат —
Projects, постоянная ответственность — Areas, может пригодиться потом — Resources, закончилось или потеряло актуальность — Archives.Я указал Codex на папку
Docum и сказал упорядочить её по PARA. И вот здесь магия оказалась действительно полезной: он разобрал файловые завалы по содержимому и разложил всё по четырём категориям. Теперь на верхнем уровне ровно четыре папки, текущие проекты находятся быстро, а всё давно ненужное спокойно лежит в архиве и не мозолит глаза.На этом я не остановился и таким же образом упорядочил по PARA заметки в Obsidian, заодно добавив иконки. Забавно, что одним из самых полезных применений AI оказался не написанный им код, а банальная уборка файловой помойки. Подробней о PARA можно прочитать здесь «Четыре папки против хаоса: PARA — это просто» https://singularity-app.ru/blog/metod-para/
Похоже, самые полезные сценарии AI начинаются не там, где он должен сделать за тебя что-то великое. А там, где можно наконец отдать ему работу, которую ты сам откладывал годами.
YouTube
gRPC для новичков
В этом видео я расскажу вам о технологии gRPC для новичков. Рассмотрим основные отличия от REST. Также, продемонстрирую на реальном примере использование gRPC, плюсы использования protobuf. Для тех кто заинтересован потренироваться с gRPC, привел пример…
👍6
Есть ощущение, что ИИ действительно ускоряет работу — ровно до того момента, пока сам понимаешь, что он делает. Стоит потерять контроль, и вместо экономии времени можно получить очень убедительное решение совсем не той задачи.
Всю неделю внедрял Cursor в свою работу. Думал, что после WebStorm придётся долго привыкать, но переход оказался довольно безболезненным. Хотя разница между ними хорошо показывает два разных подхода: IDE, где почти всё есть из коробки, и редактор, который сначала представляет собой скелет, а потом обрастает нужными плагинами.
Cursor — это ИИ-редактор на базе Visual Studio Code, поэтому первое время непривычно было работать с Git, а сильнее всего мешало отсутствие привычной панели для npm-скриптов. В WebStorm нужный функционал обычно уже есть — остаётся его настроить. В VS Code логика другая: доставляешь плагины и собираешь редактор под себя. Поставил всё необходимое, например Better Scripts для npm-скриптов, и проблема исчезла.
Особенно понравилось решать через Cursor задачи по системному администрированию. Если продукт один, обычно и самому понятно, куда смотреть. Но когда нужно интегрировать две-три системы, поиск решения легко занимает день и больше: документация, конфиги, права, особенности каждой системы. Cursor сам заходил на сервер, искал варианты решения и реализовывал их. В таких задачах экономия времени получается вполне ощутимая.
Но волшебная палочка быстро сломалась об Yandex SpeechSense. Там достаточно сложная система управления правами и доступами, и даже с MCP автоматически настроить необходимые права не получилось. Пришлось читать документацию и выполнять настройку вручную — по старинке. Хорошее напоминание, что ИИ особенно полезен, когда сам понимаешь внутренний процесс и можешь быстро заметить, что он пошёл куда-то совсем не туда.
А уехать он может далеко. Иногда смотрю на очередное решение и диву даюсь: технически всё выглядит убедительно, только к конкретной задаче имеет весьма отдалённое отношение. В таких случаях я просто останавливаю процесс и объясняю, почему этот вариант здесь неприменим. Cursor точно даст прирост в работе, но думать за инженера пока всё-таки не научился.
Параллельно разбирался с Keycloak (https://www.keycloak.org/) — бесплатной open-source системой управления доступом и идентификацией пользователей (IAM). У нас в компании много разных систем, и очень хочется, чтобы пользователь входил во все под одной учёткой. Это и есть единый вход — SSO. В Keycloak кроме SSO есть многофакторная авторизация, вход через социальные сети, защита от перебора паролей и интеграцией через Active Directory.
Основная проблема — Keycloak сам по себе достаточно сложный. Там уйма похожих терминов и сущностей, которые поначалу легко перепутать: пользователи, клиенты, роли, группы и всё остальное. Если приложение одно и авторизация простая, тащить ради него Keycloak, скорее всего, не стоит. А вот когда приложений много и требования к авторизации становятся замороченными, уже есть смысл задуматься о централизованном решении.
Я помню, как мы отделом писали собственную авторизацию: сначала на ролях, потом на атрибутах. Даже относительно простой вариант занял где-то два-три спринта. Поэтому управление доступом только со стороны выглядит задачей уровня «ну тут логин, пароль и несколько ролей». Чем глубже начинаешь разбираться, тем быстрее выясняется, что простая авторизация почему-то заканчивается отдельной системой.
В итоге за неделю получилось два похожих вывода. Cursor хорошо ускоряет работу, пока понимаешь, что именно он делает, а Keycloak хорошо решает авторизацию, когда действительно понимаешь, зачем тебе вся эта сложность. Инструменты становятся полезными не тогда, когда делают всё сами, а когда ты понимаешь, где их использовать и где вовремя остановиться.
Всю неделю внедрял Cursor в свою работу. Думал, что после WebStorm придётся долго привыкать, но переход оказался довольно безболезненным. Хотя разница между ними хорошо показывает два разных подхода: IDE, где почти всё есть из коробки, и редактор, который сначала представляет собой скелет, а потом обрастает нужными плагинами.
Cursor — это ИИ-редактор на базе Visual Studio Code, поэтому первое время непривычно было работать с Git, а сильнее всего мешало отсутствие привычной панели для npm-скриптов. В WebStorm нужный функционал обычно уже есть — остаётся его настроить. В VS Code логика другая: доставляешь плагины и собираешь редактор под себя. Поставил всё необходимое, например Better Scripts для npm-скриптов, и проблема исчезла.
Особенно понравилось решать через Cursor задачи по системному администрированию. Если продукт один, обычно и самому понятно, куда смотреть. Но когда нужно интегрировать две-три системы, поиск решения легко занимает день и больше: документация, конфиги, права, особенности каждой системы. Cursor сам заходил на сервер, искал варианты решения и реализовывал их. В таких задачах экономия времени получается вполне ощутимая.
Но волшебная палочка быстро сломалась об Yandex SpeechSense. Там достаточно сложная система управления правами и доступами, и даже с MCP автоматически настроить необходимые права не получилось. Пришлось читать документацию и выполнять настройку вручную — по старинке. Хорошее напоминание, что ИИ особенно полезен, когда сам понимаешь внутренний процесс и можешь быстро заметить, что он пошёл куда-то совсем не туда.
А уехать он может далеко. Иногда смотрю на очередное решение и диву даюсь: технически всё выглядит убедительно, только к конкретной задаче имеет весьма отдалённое отношение. В таких случаях я просто останавливаю процесс и объясняю, почему этот вариант здесь неприменим. Cursor точно даст прирост в работе, но думать за инженера пока всё-таки не научился.
Параллельно разбирался с Keycloak (https://www.keycloak.org/) — бесплатной open-source системой управления доступом и идентификацией пользователей (IAM). У нас в компании много разных систем, и очень хочется, чтобы пользователь входил во все под одной учёткой. Это и есть единый вход — SSO. В Keycloak кроме SSO есть многофакторная авторизация, вход через социальные сети, защита от перебора паролей и интеграцией через Active Directory.
Основная проблема — Keycloak сам по себе достаточно сложный. Там уйма похожих терминов и сущностей, которые поначалу легко перепутать: пользователи, клиенты, роли, группы и всё остальное. Если приложение одно и авторизация простая, тащить ради него Keycloak, скорее всего, не стоит. А вот когда приложений много и требования к авторизации становятся замороченными, уже есть смысл задуматься о централизованном решении.
Я помню, как мы отделом писали собственную авторизацию: сначала на ролях, потом на атрибутах. Даже относительно простой вариант занял где-то два-три спринта. Поэтому управление доступом только со стороны выглядит задачей уровня «ну тут логин, пароль и несколько ролей». Чем глубже начинаешь разбираться, тем быстрее выясняется, что простая авторизация почему-то заканчивается отдельной системой.
В итоге за неделю получилось два похожих вывода. Cursor хорошо ускоряет работу, пока понимаешь, что именно он делает, а Keycloak хорошо решает авторизацию, когда действительно понимаешь, зачем тебе вся эта сложность. Инструменты становятся полезными не тогда, когда делают всё сами, а когда ты понимаешь, где их использовать и где вовремя остановиться.
Keycloak
Keycloak - the open source identity and access management solution. Add single-sign-on and authentication to applications and secure services with minimum effort.
👍4
Самые интересные задачи в IT обычно начинаются со слов «да тут всё просто». На этой неделе я дважды наступил на эти грабли: сначала с локальными LLM, потом с логированием скачиваний в NextCloud.
Решил проверить, насколько хорошо LLM работает локально. А вдруг наступит чебурнет? Железо у меня дома не самое выдающееся: RTX 3050 8 ГБ + i5-12600 + 48 ГБ RAM. Установил LM Studio и довольно быстро выяснил, что 8 ГБ видеопамяти для нейронок — это маловато. Поэтому выбрал две модели, которые туда влезают: qwen2.5-coder-7b-instruct для программирования и универсальную qwen3.5-9b.
Сама по себе LLM умеет немного: получила текст, вернула текст. Чтобы началась «магия», нужна обвязка — LLM harness, который позволяет модели работать с файлами, запускать команды и использовать другие инструменты. В качестве такой обвязки взял OpenCode https://opencode.ai/, подключил локальные модели и попросил написать простейшую программу — генератор паролей.
qwen2.5-coder долго думала и родила чудо-юдо в одном файле. Дизайн — без слёз не посмотришь, зато относительно работает. qwen3.5-9b тоже долго думала и выдала результат заметно красивее. Всё хорошо, только не работает. Для сравнения дал ту же задачу Cursor — он быстро сделал красивый и рабочий вариант.
Чуда не произошло. Если хочется качественно и быстро, придётся либо радикально обновлять железо, желательно парой мощных видеокарт, либо работать по подписке. Я пока за подписку: к хорошему быстро привыкаешь.
На работе тем временем появилась задача, которая звучала ещё проще: в NextCloud нужно увидеть, какой пользователь скачал какой файл. По собственному опыту знаю — самые сложные задачи начинаются именно с одной такой фразы.
Сначала попросил Cursor написать расширенный лог для Nginx. Он написал, только в лог начало попадать вообще всё. Результат мне сильно не понравился, поэтому пришлось самому вспоминать, как устроено логирование в Nginx. Посмотрел два видео:
"Логирование в Angie" https://www.youtube.com/watch?v=UDpeDHQmcic
"Директива location в Angie" https://www.youtube.com/watch?v=gZKc5Qe2NAY
После этого переформулировал задачу для Cursor: реализовать условное логирование в JSON только скачанных файлов по HTTPS и WebDAV, с размером больше нуля, отдельно сохранять пользователя, имя и путь к файлу, а результат писать в downloads.log. Уже лучше.
На следующий день выяснилось, что логи должны храниться централизованно в Elastic. Создал индекс, отправил туда данные и настроил Dashboard в Kibana. Казалось бы, задача решена. Но поиск по имени файла оказался самой незначительной проблемой.
Пользователи NextCloud у нас авторизуются через Active Directory под доменными учётками. Удобно для людей, не очень удобно для логов: вместо Иванов И.И. там лежит UUID вроде
Оказалось, в NextCloud есть таблица сопоставления UUID и пользователей. Раз в сутки я начал отправлять её в отдельный индекс Elastic, а затем пропускать логи через pipeline, который сопоставляет UUID с именем пользователя и записывает его в итоговое поле. После этого в Kibana добавил фильтры по пользователю и имени файла.
И наконец стало видно, кто, какие файлы и сколько раз скачивал — с графиками и диаграммами. Задача «просто настроить логирование» закончилась Nginx, NextCloud, Active Directory, Elastic, pipeline и Kibana.
Наверное, в этом и есть основная разница между демо и реальной инженерной работой. В демо всё решается одним промптом или одной настройкой. В реальности основная работа начинается сразу после слов «ну тут всё просто».
Решил проверить, насколько хорошо LLM работает локально. А вдруг наступит чебурнет? Железо у меня дома не самое выдающееся: RTX 3050 8 ГБ + i5-12600 + 48 ГБ RAM. Установил LM Studio и довольно быстро выяснил, что 8 ГБ видеопамяти для нейронок — это маловато. Поэтому выбрал две модели, которые туда влезают: qwen2.5-coder-7b-instruct для программирования и универсальную qwen3.5-9b.
Сама по себе LLM умеет немного: получила текст, вернула текст. Чтобы началась «магия», нужна обвязка — LLM harness, который позволяет модели работать с файлами, запускать команды и использовать другие инструменты. В качестве такой обвязки взял OpenCode https://opencode.ai/, подключил локальные модели и попросил написать простейшую программу — генератор паролей.
qwen2.5-coder долго думала и родила чудо-юдо в одном файле. Дизайн — без слёз не посмотришь, зато относительно работает. qwen3.5-9b тоже долго думала и выдала результат заметно красивее. Всё хорошо, только не работает. Для сравнения дал ту же задачу Cursor — он быстро сделал красивый и рабочий вариант.
Чуда не произошло. Если хочется качественно и быстро, придётся либо радикально обновлять железо, желательно парой мощных видеокарт, либо работать по подписке. Я пока за подписку: к хорошему быстро привыкаешь.
На работе тем временем появилась задача, которая звучала ещё проще: в NextCloud нужно увидеть, какой пользователь скачал какой файл. По собственному опыту знаю — самые сложные задачи начинаются именно с одной такой фразы.
Сначала попросил Cursor написать расширенный лог для Nginx. Он написал, только в лог начало попадать вообще всё. Результат мне сильно не понравился, поэтому пришлось самому вспоминать, как устроено логирование в Nginx. Посмотрел два видео:
"Логирование в Angie" https://www.youtube.com/watch?v=UDpeDHQmcic
"Директива location в Angie" https://www.youtube.com/watch?v=gZKc5Qe2NAY
После этого переформулировал задачу для Cursor: реализовать условное логирование в JSON только скачанных файлов по HTTPS и WebDAV, с размером больше нуля, отдельно сохранять пользователя, имя и путь к файлу, а результат писать в downloads.log. Уже лучше.
На следующий день выяснилось, что логи должны храниться централизованно в Elastic. Создал индекс, отправил туда данные и настроил Dashboard в Kibana. Казалось бы, задача решена. Но поиск по имени файла оказался самой незначительной проблемой.
Пользователи NextCloud у нас авторизуются через Active Directory под доменными учётками. Удобно для людей, не очень удобно для логов: вместо Иванов И.И. там лежит UUID вроде
0e9584bb-c1cd-4d44-ab94-a3e7a7b4c998. А в Dashboard хотелось видеть всё-таки людей, а не наборы символов.Оказалось, в NextCloud есть таблица сопоставления UUID и пользователей. Раз в сутки я начал отправлять её в отдельный индекс Elastic, а затем пропускать логи через pipeline, который сопоставляет UUID с именем пользователя и записывает его в итоговое поле. После этого в Kibana добавил фильтры по пользователю и имени файла.
И наконец стало видно, кто, какие файлы и сколько раз скачивал — с графиками и диаграммами. Задача «просто настроить логирование» закончилась Nginx, NextCloud, Active Directory, Elastic, pipeline и Kibana.
Наверное, в этом и есть основная разница между демо и реальной инженерной работой. В демо всё решается одним промптом или одной настройкой. В реальности основная работа начинается сразу после слов «ну тут всё просто».
OpenCode
OpenCode | The open source AI coding agent
OpenCode - The open source coding agent.
👍3