ar
Feedback
Сохранёнки программиста

Сохранёнки программиста

الذهاب إلى القناة على Telegram

Заметки и ссылки на будущее, чтобы изучить когда будет время. Разместить рекламу: @tproger_sales_bot Правила общения: https://tprg.ru/rules Другие каналы: @tproger_channels Другие наши проекты: https://tprg.ru/med

إظهار المزيد
6 608
المشتركون
-324 ساعات
-187 أيام
-3730 أيام
أرشيف المشاركات
p99 0 мс на автодополнение 240 миллионов доменов Автор поставил себе дерзкую цель: показывать подсказки раньше, чем пользователь успеет отпустить клавишу. Задержку он меряет от момента keyUp до готового результата и закладывает бюджет p99 в 121 мс на два нажатия с паузой между ними. Чтобы в него уложиться, выдача должна быть готова почти мгновенно. Архитектура делится на две части по распределению запросов: 🔘голова, миллион самых частых доменов из списка Tranco, лежит в памяти как символьный trie с заранее посчитанным топ-8 для каждого префикса; 🔘хвост, все 240 миллионов доменов из CZDS, лежит на SSD как memory-mapped блочный индекс с дельта-сжатием: 27 МБ оглавления в памяти и 2,5 ГБ на диске; 🔘большинство запросов к API отвечают за 2 мс, на нагрузке 1600 запросов в секунду p99 связки nginx и API держится около 15 мс; 🔘оставшаяся задержка упирается в сетевой путь через Cloudflare, поэтому для дальних регионов нужна геобалансировка. По дороге видно, как требование «мгновенно» раскладывается на конкретные структуры данных и бюджеты по миллисекундам. Сохранять тем, кто проектирует поиск и автодополнение под нагрузкой и любит, когда задержку считают по слоям. Полная статья: https://ruurtjan.com/articles/p99-0ms-autocomplete-for-240-million-domain-names @prog_stuff

Разработчик заменил 3 ГБ SQLite на десяток мегабайт FST и не потерял в скорости У финнов есть слово opiskelijassammekin, и если вы не носитель, разобрать его вручную — то ещё удовольствие. Проект Taskusanakirja как раз помогает: вводишь приставку, а словарь ищет финско-английские пары на лету. Раньше под это дело автор держал 3 ГБ SQLite и упирался в размер. В итоге он перешёл на FST (finite state transducer), статичную структуру данных для префиксного поиска. Бинарник сжался до десятка мегабайт, а отклик остался таким, что глаз не заметит. Цепляет не столько цифрой, сколько подходом: вместо универсальной базы используется узкая структура, которая делает ровно то, что нужно, и не жрёт лишнего. Хороший напоминание, что иногда оптимизация заключается не в ускорении запросов, а в отказе от лишнего инструмента.

Сжать баг до минимального примера автоматически: про недооценённые test-case reducers Когда баг воспроизводится на огромном входе — файле, программе, последовательности действий — стандартный совет «сделайте минимальный пример» звучит легко, а руками делается мучительно. Лори Тратт напоминает про инструменты, которые делают это сами: test-case reducers берут падающий вход и ужимают его, часто на 95-99%, до состояния, где удалить уже нечего. Ключевая идея — reducer ничего не знает про ваш язык и формат. Ему нужен только оракул: функция, которая отвечает «да, этот вход всё ещё интересен», то есть баг по-прежнему воспроизводится. Всё остальное — перебор и выбрасывание кусков. Что полезно знать: 🔘 reducer языконезависим: тот же инструмент сжимает и C-программу, и JSON, и лог действий, лишь бы был тест на «интересность»; 🔘 написать хороший тест на интересность сложнее, чем кажется: легко получить переусушку, когда вход схлопывается в другой баг, не тот, что вы ловите; 🔘 скорость этого теста решает всё: reducer вызывает его тысячи раз, поэтому его выгодно делать максимально дешёвым; 🔘 сжимать можно не только по длине входа, но и по другим метрикам — длине трейса, числу инструкций, частоте срабатывания ошибки; 🔘 есть приёмы и для недетерминированных багов, которые воспроизводятся через раз. Сохранять всем, кто хоть раз убил полдня на ручное вырезание строк из репродукции. Навык языконезависимый и не устаревает: дешёвый минимальный пример экономит часы на каждом нетривиальном баге. Полная статья: https://tratt.net/laurie/blog/2026/test_case_reducers_are_underappreciated_debugging_tools.html @prog_stuff

Algorithm Visualizer — сайт, где 30+ алгоритмов разобраны пошаговой анимацией Открытый React-проект, который превращает сухие учебники по алгоритмам в живые картинки: на каждом шаге видно состояние структуры данных, активную строку кода и пояснение, что сейчас происходит. Проект живой, в июне завезли крупное обновление. Что внутри: 🔘поиск пути и обходы графов: BFS, DFS, Dijkstra, Bellman-Ford; 🔘остовные деревья Краскала и Прима, компоненты связности, потоки в сетях (Edmonds-Karp, Ford-Fulkerson); 🔘сортировки, бинарное дерево поиска, связные списки, дерево рекурсии; 🔘классика собеседований и олимпиад: N-Queens, выпуклая оболочка, машина Тьюринга. Июньское обновление добавило визуализатор связных списков, рабочее пространство для обходов графа, кратчайшие пути с остовными деревьями и переиспользуемый SVG-компонент дерева с BST. Работает прямо в браузере, ничего ставить не нужно. Сохранять студентам перед сессией, всем, кто готовится к алгоритмическим секциям собеседований, и менторам — объяснять джуну Дейкстру по анимации сильно проще, чем по псевдокоду. Полная ссылка: https://tamimehsan.github.io/AlgorithmVisualizer/ @prog_stuff

Как мы проскочили путь от первого iPhone и сложной разработки под мобильные устройства до эпохи ИИ? Что случилось и к чему это привело — в третьей части цикла об истории российского IT. Мобильный бум застал индустрию врасплох: было непонятно, как адаптировать сайты под маленькие экраны и что делать со слабой связью. Решением стали нативные приложения — их начали разрабатывать многие компании. Так мы пришли к эпохе супераппов, где собрано всё и сразу. Приложений, проектов и стартапов становилось больше — начался расцвет российского IT. Но разработчиков не хватало, и на сцену вышли курсы, школы и онлайн-уроки. Желающих войти в профессию оказалось огромное количество, и рынок быстро перегрелся. Теперь новичков заменяет ИИ, а найти работу — задача со звёздочкой. Сегодня гонка за лучшими программистами превратилась в гонку ИИ-инфраструктур. Так решения порождали новые проблемы, а российская IT-индустрия вышла на новый уровень сложности. Подробнее — в материале на Tproger.

CSS: какие части языка неустранимо плохие и как с ними жить Разбор от Алекса Кладова (matklad, автор rust-analyzer) — взгляд бэкендера, которому пришлось стилизовать свой блог. Он разложил CSS на части, которые работают предсказуемо, и части, которые подведут в самый неожиданный момент, и для каждой плохой нашёл обходной путь. Главные практические выводы: 🔘первая строка любого CSS-файла — * { box-sizing: border-box; }, иначе padding ломает размеры элементов; 🔘вместо обёрток и div-супа — семантические теги main, article, nav, details: с ними простой classless CSS работает сам; 🔘отступы между детьми удобно задавать через owl-селектор section > *+* { margin-top: 1rem; } — родитель контролирует расстояния, дети ни о чём не знают; 🔘явные media-запросы для простых страниц не нужны: flexbox и max-width на главной колонке дают отзывчивость бесплатно; 🔘браузерные дефолты — ловушка: проблема не в правиле, которое вы написали, а в правиле, на которое вы полагаетесь, не написав его; 🔘font-size задаёт размер виртуальной коробки вокруг глифа, а не сам глиф — выровнять два шрифта помогает font-size-adjust. Для блога автору хватило примерно 200 строк читаемого CSS без фреймворков. Сохранять тем, кто не фронтендер, но периодически вынужден верстать: страницу проекта, документацию, личный блог. Полная статья: https://matklad.github.io/2026/06/04/css-unavoidable-bad-parts.html @prog_stuff

Почему случайные UUID в роли первичного ключа убивают вставки в SQLite Разбор с бенчмарками и профилированием о том, как выбор типа первичного ключа меняет скорость записи в разы. Суть проблемы: первичный ключ задаёт физический порядок хранения строк в B-дереве. Случайный UUID4 означает вставки в случайные места дерева, а это бесконечные сплиты страниц и ребалансировки. Автор вставляет 10 миллионов строк пакетами по миллиону и сравнивает: 🔘обычный INTEGER-ключ: стабильные ~715 мс на миллион, эталон; 🔘UUID4 с WITHOUT ROWID: первый миллион 2649 мс, десятый уже 12586 мс — деградация нелинейная, чем больше таблица, тем хуже, итог до 18 раз медленнее эталона; 🔘UUID7 с WITHOUT ROWID: стабильные ~1250 мс на миллион без всякой деградации. Весь фокус в том, что UUID7 содержит таймстемп в старших битах, поэтому новые ключи монотонно растут и ложатся в конец дерева, как автоинкремент. UUID4 при этом остаётся медленнее целого числа примерно на 70%: ключ занимает 16 байт против 8, строк на страницу помещается меньше. Отдельный урок про WITHOUT ROWID: эта опция полезна, когда по первичному ключу часто ищут, но в паре со случайным UUID получается худшее из двух миров — данные лежат и в листьях, и в промежуточных узлах дерева, и ребалансировка дорожает максимально. Выводы переносятся на любую БД с кластерным индексом, от MySQL InnoDB до SQL Server. Сохранять всем, кто сейчас выбирает схему ключей для нового сервиса. Полная статья: https://andersmurphy.com/2026/06/05/the-perils-of-uuid-primary-keys-in-sqlite.html @prog_stuff

RCE, которую AMD не хотела чинить: история одного разбора Автор разозлился на всплывающее консольное окно на игровом ПК, отследил его до AMD AutoUpdate и в наказание декомпилировал программу. Внутри нашлась цепочка на удалённое выполнение кода: список обновлений приходит по HTTPS, но ссылки на сами исполняемые файлы в нём — обычный HTTP, а проверки подписи нет вообще. Атакующий в той же сети подменяет ответ, и апдейтер скачивает и сразу запускает любой бинарник. Как развивались события: 🔘27 января — уязвимость найдена, 6 февраля — отчёт в AMD; 🔘в тот же день AMD закрывает его со статусом «не будем чинить»: MITM-атаки вне скоупа их баг-баунти; 🔘на следующий день после публикации блог-поста компания передумала и попросила пост убрать; 🔘дальше четыре месяца продлений эмбарго: «затронуты ещё несколько инструментов», «клиенты просят время»; 🔘9 июня, через 124 дня, эмбарго снято и присвоен CVE. Детали финала достойны отдельного абзаца. Вместо криптографической подписи AMD добавила проверку CRC-32, которая от подмены не защищает. Выплата за находку — ноль долларов: формально вне скоупа. А эксплуатировать дыру всё это время было нельзя по смешной причине: апдейтер падал из-за другого, никем не замеченного бага с редиректом. Сохранять тем, кто пишет автообновления (HTTPS и подпись бинарников обязательны), и тем, кто хочет понимать, как на самом деле выглядит ответственное разглашение. Полная статья: https://mrbruh.com/amd2/ @prog_stuff

В большинстве компаний 1С и облачная инфраструктура живут в параллельных мирах: DevOps смотрит в Grafana, финдиректор — в 1С, а когда падает оплата, все смотрят друг на друга. На самом деле подружить 1С с современными инструментами мониторинга вполне реально всего за один спринт. В блоге Centicore рассказали, как это сделать. В статье разбирается, как вытащить метрики из 1С через OData без единой строчки кода, написать Prometheus Exporter на Python и собрать бизнес- и технические метрики на одном дашборде. А заодно — где интеграция обычно ломается и как это пережить.

Семь ошибок в архитектурных диаграммах, которые делают почти все Команда Ilograph собрала второй заход по антипаттернам системных диаграмм (в первой части было ещё семь, итого четырнадцать). Список из тех, где на каждом пункте узнаёшь свои схемы: 🔘подписи типом вместо имени: на диаграмме «Amazon S3» и «AWS Lambda», и непонятно, какой именно бакет и какая функция. Лечится суффиксом типа: Orders Table, Results Bucket; 🔘висящие ресурсы: компонент нарисован, но ни с чем не соединён, и его роль приходится угадывать; 🔘«мастер-диаграмма»: попытка уместить всю систему в одну схему, где смешаны runtime-зависимости, DNS, CDN и деплой. Решение — несколько диаграмм с разных точек зрения; 🔘синдром конвейера: поведение системы рисуют как поток слева направо, хотя реальные взаимодействия ходят туда-обратно. Для этого есть sequence-диаграммы; 🔘бессмысленные анимации: мелькающие стрелки дублируют то, что и так видно, и нужны только для маркетинга; 🔘fan trap: продюсеры и консьюмеры сходятся в одном брокере сообщений, и кто с кем реально общается — не видно. Лечится отрисовкой топиков внутри брокера; 🔘вера, что ИИ построит качественную диаграмму из исходников: на выходе размытые схемы с галлюцинациями и теми же ошибками из пунктов выше, потому что модель не умеет стратегически решать, что включить, а что выкинуть. Сохранять перед следующим дизайн-ревью: пройтись по списку и проверить свою схему по всем семи пунктам быстрее, чем потом объяснять её голосом. Полная статья: https://www.ilograph.com/blog/posts/more-common-diagram-mistakes/ @prog_stuff

Хватит использовать Conventional Commits — провокационное эссе с аргументами, которые сложно отмахнуть Автор бьёт по стандарту, который многие команды внедрили не задумываясь. Главный тезис: Conventional Commits фокусируют на неважном и обесценивают важное. Тип коммита (fix, feat, chore) стоит на первом месте и обязателен, а scope — область, которую трогает коммит — опционален и прячется в скобках. По мнению автора, всё должно быть наоборот. Аргументация по пунктам: 🔘всем читателям истории важнее «где», чем «что за тип»: контрибьютор ищет изменения в конкретной подсистеме, дебажащий ищет по компоненту, дежурный при инциденте смотрит на область, где всплеск ошибок; 🔘тип часто избыточен: в fix(compiler): prevent SVG elements from being stripped и без префикса видно, что это багфикс; 🔘обещания стандарта не выполняются: автогенерация changelog ломается на многокоммитных фичах и ревертах, автоопределение semver даёт ложные срабатывания, а триггерить CI по docs: в сообщении опасно — честнее смотреть на изменённые файлы; 🔘ИИ-ассистенты по привычке генерируют Conventional Commits, чем разносят антипаттерн дальше. Взамен предлагаются scoped commits: префикс с областью и описание. Это даже не новый стандарт — так десятилетиями живут Linux (i2c: virtio: mark device ready...), Git, Go (net/http/cookiejar: add godoc links), FreeBSD, Node.js и nixpkgs. Текст вышел 5 июня и уже собрал жаркие обсуждения. Сохранять тем, кто пишет гайдлайны для команды: даже если останетесь на Conventional Commits, аргументы стоит знать. Полная статья: https://sumnerevans.com/posts/software-engineering/stop-using-conventional-commits/ @prog_stuff

Софт рождается между коммитами — Zed представила DeltaDB, контроль версий для эпохи агентов Команда редактора Zed считает, что Git перестал отражать то, как теперь пишется код: половина работы происходит в диалогах с агентами, а коммит видит только итоговый снимок. DeltaDB записывает каждую операцию между коммитами как отдельную дельту со стабильным идентификатором и сохраняет рядом разговор, который это изменение породил. Что это даёт: 🔘с любой строки кода можно перейти к диалогу, в котором она появилась, и ко всем последующим обсуждениям; 🔘ссылки на код привязаны к дельтам, а не к номерам строк, поэтому не ломаются, когда код переезжает; 🔘рабочие деревья построены на CRDT: несколько людей и агентов правят одни файлы на разных машинах без конфликтов; 🔘коллега может подключиться к работе, поговорить с агентом и оставить пометки, не дожидаясь commit и push; 🔘агенты получают контекст: могут «спросить» предыдущих агентов, почему код написан именно так. Git при этом не выбрасывается — остаётся для CI и связи с внешним миром, просто перестаёт быть единственной точкой совместной работы. Бета обещана в ближайшие недели, открыт список ожидания. Сохранять тем, кто много работает с кодящими агентами и уже ловил себя на том, что контекст решений теряется между сессиями. Полная статья: https://zed.dev/blog/introducing-deltadb @prog_stuff

Сколько стоит прочитать одну страницу в 8 КБ из Postgres — трассировка по всем слоям кэшей Свежий разбор, который хочется выдать каждому, кто проектирует базы «на глазок». Автор словил в продакшене инцидент с IOPS, воспроизвёл ту же патологию на домашнем сервере и померил, во сколько обходится чтение одной и той же страницы на каждом уровне: shared buffers, page cache операционки, локальный NVMe и сетевой диск AWS EBS. Числа красивые своей наглядностью, каждый слой стоит примерно на порядок дороже предыдущего: 🔘страница в shared buffers — около 1,1 мкс; 🔘в page cache ОС — около 4 мкс; 🔘холодное чтение с локального NVMe — около 78 мкс; 🔘сетевой EBS в продакшене — около 497 мкс, в 124 раза дороже page cache. Самая поучительная деталь — про порядок чтения. Те же 500 холодных страниц в отсортированном порядке (bitmap heap scan) читаются за 2,8 мс, а в случайном (index scan) — за 39,5 мс. Разница в 14 раз на ровно тех же данных, всю работу делает readahead ядра. Сохранять бэкендерам и всем, кто хоть раз удивлялся, почему запрос на ноутбуке летает, а в облаке встаёт колом. Полная статья: https://frn.sh/8kb-read/ @prog_stuff

В блоге Альфа-Банка вышла статья о метриках в разработке. Команда перепробовала аж 7 штук и путём проб и ошибок собрала свой минимальный набор, который реально приносит пользу. Основой стала Cycle Time — она показывает, сколько времени задача провела внутри процесса разработки, от старта до релиза. Метрик часто опасаются: если внедрить их неправильно или использовать как дубинку, цифры начинают подгонять, а толку — ноль. Как этого избежать и подобрать правильный набор показателей под себя — читайте в статье: https://tproger.ru/articles/kak-my-sbezhali-iz-kpi-karaoke-naw-bazovyj-minimum-metrik-kot

Под капотом RollerCoaster Tycoon: оптимизация как искусство сказать «нет» RollerCoaster Tycoon (1999) до сих пор называют эталоном оптимизации. Крис Сойер написал игру почти целиком на ассемблере и заставил процессоры конца девяностых тащить парки с тысячами посетителей без единой просадки кадра — то, с чем многие современные градостроительные симуляторы справляются хуже на железе в сотни раз мощнее. Ларс Тофус в блоге Larst Of Us разобрал, как это устроено. Исходников игры нет, но есть почти эквивалент — OpenRCT2, побайтовая фанатская переразработка на годах реверс-инжиниринга. По ней и видно, насколько агрессивно вылизан каждый кусок. Первое, что бросается в глаза, это типы данных под деньги. Сойер не брал один универсальный тип на все случаи, а подбирал размер под максимально ожидаемое значение. Общая стоимость парка может быть огромной, поэтому под неё отведено 4 байта. А цена товара в ларьке заведомо маленькая, под неё хватает одного байта. На современных процессорах разницы уже нет, поэтому в OpenRCT2 всё свели к 8-байтовым переменным, но в оригинале экономили каждый байт. Второй приём — замена арифметики битовыми сдвигами. Вместо умножения на 4 в коде стоит сдвиг влево на две позиции, вместо деления на 8 — сдвиг вправо на три. Сдвиг намного дешевле для процессора. Интересна тут не сама техника, а то, как часто она применима: сдвигом можно умножать и делить только на степени двойки. То, что в коде это встречается постоянно, означает, что игровые формулы изначально проектировались под удобные числа. Представьте программиста, который просит геймдизайнера заменить 9,5 на 8, потому что так удобнее процессору. В обычной студии это невозможно. В RCT программист и дизайнер — один человек, и это открывает третий, самый глубокий слой оптимизаций. Дизайн ради производительности. Логичный путь для парк-симулятора такой: гость выбирает аттракцион по своим предпочтениям и идёт к нему. С точки зрения техники это худший сценарий — поиск пути дорогая операция, а гнать его для тысяч агентов разом тяжело даже сегодня. Поэтому гости в RCT ходят по парку фактически вслепую: идут по дорожке, на развилке выбирают направление почти случайно, с парой правил против тупиков, и натыкаются на интересное по дороге. Это видно в игре: гость жалуется на голод, но не ищет ближайший ларёк, а просто бредёт, пока случайно не пройдёт мимо еды. Честный поиск пути всё же есть — для механика, идущего к сломанному аттракциону, или для гостя к выходу. Но и там стоит предохранитель. 🔘 У поиска пути есть жёсткий лимит глубины обхода сети дорожек, и при его достижении поиск просто сдаётся и возвращает неудачу. 🔘 По умолчанию гостю можно пройти лишь до глубины в 5 развилок. Когда гость жалуется, что не может найти выход, это буквально работа алгоритма, который мог бы искать дальше, но не стал ради кадров. 🔘 Механик важнее обычного гостя, ему лимит подняли до 8 развилок. 🔘 Гость, купивший карту парка в киоске, получает лимит 7 вместо 5, и ему легче найти выход. Техническое ограничение превратили в игровую механику. Тем же принципом решена толкучка. Система столкновений и обхода для тысяч агентов убила бы фреймрейт, поэтому гости в RCT не сталкиваются и не избегают друг друга — на одной плитке дорожки их могут стоять хоть тысячи. Но они считают соседей: если рядом слишком людно, падает счастье и летит жалоба игроку. Для игрока результат тот же — приходится планировать дорожки, чтобы не было давки, — а расчёт на порядок дешевле. Вывод Тофуса: менять дизайн ради производительности кажется радикальным шагом, но при должном диалоге между кодом и геймдизайном это даёт выигрыш, которого не добьёшься никакой микрооптимизацией. Иногда лучшая оптимизация — это смелость сказать техническому вызову «нет». Сохранять тем, кто любит истории про low-level инженерию, ценит дизайн, продиктованный железом, и хочет показать коллегам, что значит «оптимизировано до предела». https://www.larstofus.com/the-gold-standard-of-optimization-a-look-under-the-hood-of-rollercoaster-tycoon @prog_stuff

Почему запросы на staging укладываются в 12 мс, а в продакшене встают колом Обстоятельный разбор семи ошибок индексации, кото
Почему запросы на staging укладываются в 12 мс, а в продакшене встают колом Обстоятельный разбор семи ошибок индексации, которые убивают производительность SaaS на корню. Казалось бы, индексы, вроде, базовая тема, но главный подвох в другом: проблема не в их отсутствии, а в неправильных индексах. В материале: от параноидального создания индексов «на всякий случай» до игнорирования раздутия и мультитенантных схем. Каждый INSERT, UPDATE и DELETE обновляет все индексы таблицы, а индекс на колонке с низкой селективностью бесполезен без частичного (partial) условия. Внешние ключи в PostgreSQL не индексируются автоматически, а без EXPLAIN ANALYZE индексы создаются вслепую. Сохранить стоит разработчикам бэкенда и администраторам БД с production под нагрузкой. Остальным достаточно знать, что индексы — налог на запись, а не волшебная ускорялка. Читать разбор на Tproger

Один клик по ссылке — и у атакующего твой GitHub-токен на чтение и запись всех репозиториев, включая приватные Ammar Askar разобрал цепочку, которая складывается из вполне безобидных по отдельности фич. Началось всё с github.dev — это лёгкий VSCode прямо в браузере, который открывается, если в адресе репозитория поменять github.com на github.dev. Чтобы он мог коммитить и слать pull request от твоего имени, github.com по сети передаёт ему OAuth-токен. И вот ключевая деталь: токен не привязан к конкретному репозиторию. Он даёт доступ ко всему, к чему есть доступ у тебя. VSCode рендерит превью Markdown и Jupyter-ноутбуки внутри webview — это iframe с отдельным origin, отрезанный от основного окна. Идея правильная: даже если в ноутбуке выполнится произвольный JavaScript, до ядра редактора он не дотянется. Но есть нюанс удобства. Чтобы горячие клавиши работали, когда фокус внутри webview, VSCode вешает там слушатель keydown и пробрасывает нажатия в основное окно сообщением did-keydown. Основное окно принимает их за реальный ввод пользователя. А значит, скрипт из недоверенного webview может сам сгенерировать keydown и «нажать» клавиши за тебя. Дальше Askar обходит защиты одну за другой, и это самая поучительная часть: 🔘Палитру команд (Ctrl+Shift+P) открыть получается, но напечатать в неё текст нельзя: поле ввода слушает не keydown, а обычный HTML-input, до которого синтетические события не доходят 🔘Тогда в дело идут встроенные хоткеи VSCode, которые висят прямо на keydown. Через .vscode/extensions.json репозиторий рекомендует «своё» расширение, всплывает уведомление, а Ctrl+Shift+A («принять основное действие уведомления») жмёт кнопку установки 🔘Система доверия к издателю (с версии 1.97) показала бы диалог подтверждения, но кнопку в нём синтетическим Enter не нажать. Обход — local workspace extensions: расширение прямо в .vscode/extensions в доверенном workspace ставится без проверки издателя, а github.dev доверенный всегда 🔘Последний барьер, CSP, ломал прямую загрузку. Решение изящное: расширение через package.json регистрирует свой keybinding на runCommands, который вызывает workbench.extensions.installExtension с флагом skipPublisherTrust. Своё нажатие клавиши воспроизводится железно, так что устанавливается уже что угодно Итоговый payload прячется в Markdown-ячейке ноутбука как картинка с onerror, ждёт всплывающего уведомления, шлёт Ctrl+Shift+A, затем Ctrl+F1, и установленное расширение читает OAuth-токен и дёргает api.github.com за списком приватных репозиториев. CSRF-токенов у github.dev нет, поэтому редиректнуть жертву на атаку может любая ссылка. Отдельно ценен раздел про то, что VSCode сделал правильно: именно defense-in-depth спас от худшего сценария. На странице расширения скрипты в Markdown-превью отрублены через script-src 'none', иначе это была бы 1-click RCE на десктопе. Microsoft выкатил фикс на следующий день (3 июня): подтверждение при открытии ноутбуков в вебе и запрет пробрасывать keydown из webview ноутбука. Если защищаешься: очисти cookies и site data для github.dev. Тогда при заходе появится диалог, на котором можно уйти со страницы до запуска цепочки. Сохранять тем, кто пишет приложения с webview, разбирает модели изоляции iframe или просто любит, когда сложную атаку собирают из десятка «удобных» мелочей. https://blog.ammaraskar.com/github-token-stealing/ @prog_stuff

ИИ-агент для аналитики бесполезен, если он не понимает ваши данные Cloudflare написали production-разбор про Town Lake и Skipper. Снаружи это похоже на историю «мы дали модели доступ к SQL». Но главный смысл как раз в обратном: ИИ-агент для данных начинается не с промпта, а с платформы, которая объясняет ему схемы, владельцев, права, свежесть таблиц и смысл колонок. Контекст большой: больше миллиарда событий в секунду, 330+ городов, Postgres, ClickHouse, Kafka, BigQuery, R2 и внутренние пайплайны. Town Lake собирает это в единый SQL-интерфейс через Trino. DataHub хранит схемы и происхождение данных. Lifeguard управляет доступами. Skimmer ищет персональные данные. А Skipper уже поверх этого превращает вопросы на естественном языке в проверяемые SQL-запросы. Главный вывод: если дать модели просто список таблиц, она будет уверенно придумывать связи и считать не то. Проверять в таких проектах надо не только модель, но и слой метаданных, доступы, подготовленные модели данных и то, откуда агент берёт контекст.

Где держать Telegram-бота или API, чтобы они не падали под нагрузкой и не съедали бюджет? Tproger собрал подборку из шести VPS-провайдеров под этот сценарий: от тарифов за пару сотен рублей в месяц до конфигураций с DDR5 и портом 10 Гбит/с. У каждого свой акцент — где-то посуточная оплата и запуск за минуту, где-то API для CI/CD, бэкапы и приватные сети, где-то зарубежные локации. Внутри по каждому провайдеру: реальные конфигурации, цены, на какой нагрузке тестировали и под какой сценарий брать. https://tproger.ru/articles/gde-razvernut-bota-ili-api---podborka-vps--kotorye-ne-tormozyat @prog_stuff

Почему передача репозитория не равна передаче проекта Programming as Theory Building — классический текст Питера Наура о том, что программирование не сводится к коду, документации и диаграммам. Всё это важные артефакты, но они не содержат всю «теорию» системы. Главное в тексте — очень точное объяснение боли legacy: проект можно формально передать полностью, но новая команда всё равно не получит систему. Репозиторий есть, README есть, схемы есть, backlog есть, а уверенности в изменениях нет. Теория у Наура — это понимание, которое держат в голове разработчики: почему решения приняты именно так, какие варианты уже пробовали, какие ограничения нельзя трогать и какие изменения выглядят локально разумно, но ломают общий смысл конструкции. Отсюда хорошо считываются последствия для сопровождения. Документация помогает, но не заменяет участие в разработке. Code review проверяет не только строки, но и то, совпадает ли изменение с теорией системы. Онбординг — это не экскурсия по файлам, а постепенная передача причин, ограничений и инженерной памяти. Сохранять тем, кто занимается legacy, онбордингом, ревью, архитектурой или передачей проектов между командами. Текст старый, но после него иначе смотришь на фразу «мы всё задокументировали». https://pages.cs.wisc.edu/~remzi/Naur.pdf

Сохранёнки программиста - إحصائيات وتحليلات قناة تيليجرام @prog_stuff