惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
T
The Blog of Author Tim Ferriss
U
Unit 42
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
Vercel News
Vercel News
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
D
DataBreaches.Net
The GitHub Blog
The GitHub Blog
大猫的无限游戏
大猫的无限游戏
C
Check Point Blog
Blog — PlanetScale
Blog — PlanetScale
I
InfoQ
Y
Y Combinator Blog
F
Full Disclosure
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
G
Google Developers Blog
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
博客园 - 叶小钗
S
SegmentFault 最新的问题
腾讯CDC
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
Recent Commits to openclaw:main
Recent Commits to openclaw:main
The Register - Security
The Register - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Azure Blog
Microsoft Azure Blog
云风的 BLOG
云风的 BLOG
Last Week in AI
Last Week in AI
F
Fortinet All Blogs
C
CXSECURITY Database RSS Feed - CXSecurity.com
Hugging Face - Blog
Hugging Face - Blog
T
Threatpost
GbyAI
GbyAI
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
L
LangChain Blog
T
Tenable Blog
C
Cisco Blogs
T
Threat Research - Cisco Blogs
Google Online Security Blog
Google Online Security Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Yggdrasil-ng: как я переписал Yggdrasil на Rust за 3.5 дня и неделю фиксил один баг
Revertis · 2026-04-25 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение9 мин

Охват и читатели0

Обзор

Это опять Revertron, в прошлой статье я разобрал, как устроена сеть Yggdrasil: криптоадресация, spanning tree, жадная маршрутизация, bloom-фильтры. Я обещал, что это первая статья цикла - и обещал рассказать новости. А новостей много: я переписал Yggdrasil с Go на Rust. Это и есть Yggdrasil-ng (next generation).

Сразу спойлер: рерайт у меня занял 3.5 дня. После этого я неделю чинил один баг. И на этом проекте я уже собрал Android-мессенджер. Обо всём по порядку.

Откуда вообще взялась эта идея

У меня есть свой проект - мессенджер Mimir для Android, основанный на Yggdrasil. До недавнего времени сетевая часть в нём работала через Go-библиотеку yggquic (Yggdrasil с QUIC внутри). Я туда регулярно вносил правки, но… делал это через веб-интерфейсы разных нейросетей - ChatGPT, Kimi и других. Кидаешь файл, просишь поменять, копируешь обратно. Каждое изменение - отдельный ритуал.

С каждым месяцем мне становилось всё сложнее: код Go-библиотеки рос, держать его в голове целиком я не мог, нейронкам приходилось давать всё больше контекста, а ошибок всё равно становилось больше. Проект развивался медленно, я выгорал.

Потом по работе я попробовал Claude Code - это CLI-инструмент от Anthropic, который интегрируется с IDE (у меня RustRover от JetBrains плюс Android Studio). Принципиальное отличие - Claude видит весь проект сам, читает файлы, запускает тесты, правит код прямо в репозитории. Не “скопируй мне функцию, я её перепишу”, а “вот задача, разберись и сделай”. Я вдохновился разработкой с LLM как таковой, причём на новом уровне - не для генерации отдельных функций, а для реальной работы над проектами.

А в русскоязычном сообществе Yggdrasil давно ходила шутка: “надо бы переписать Yggdrasil на Rust”. Несколько лет об этом смеялись. Браться за такой крупный проект без знания Go было страшно - Yggdrasil это не “hello world”, это сетевой стек с криптографией, async I/O, CRDT-маршрутизацией и особенно с каким-то кастомным актор-фреймворком.

И в один вечер опять зашёл разговор на эту тему, я прикинул то, насколько легче мне будет разрабатывать мессенджер, и психанул! Склонировал три репозитория - yggdrasil-go (сам демон), ironwood (библиотека маршрутизации) и phony (actor framework, на котором построен Go-код). Открыл Claude Code в этой папке. Запустил команду /init, и понеслось!

3,5 дня на рерайт

Это не опечатка. От git init Rust-проекта до работающего демона, который пингует Go-узлы по сети - три с половиной дня.

Конечно, “работающий” - это не “production-ready”. Тестов было мало, фич меньше, чем в Go-версии, кое-где вместо нормальной обработки ошибок стояло unwrap() (этот пассаж написала нейронка, на самом деле она такого не допускала ;) ). Но базовая сеть работала: Rust-узел подключался к публичным пирам, строил spanning tree, искал маршруты через bloom-фильтры, шифровал трафик и обменивался пакетами с Go-узлами.

Что важно понять: я сам не писал код. Я давал задания. Всё началось с анализа кода на Го. Я не помню точный промпт, но он был примерно из трёх предложений. Claude долго жевал гошные исходники и выдал некий обширный план того, как будет переписывать проект на Rust. Я очень внимательно читал план, чтобы нейронка не пошла по неверному пути прямо с самого начала, ибо дальше будет сложнее развернуться. Упирался в лимиты Claude Pro, приходилось делать перерывы на кофе, еду и даже какие-то дела по дому. Ложился спать в шесть утра. Да, наверное именно поэтому получилось 3,5 суток на перевод.

Получилось 7 фаз работы:

  • Фаза 1. Фундамент: типы, криптография, wire-протокол, конфиг.

  • Фаза 2. Маршрутизация: spanning tree, bloom-фильтры, pathfinder, роутер.

  • Фаза 3. Сеть: peers, ядро, публичный API.

  • Фаза 4. Шифрование: сессии, рэтчетинг ключей, подписи.

  • Фаза 5. Интеграционные тесты.

  • Фаза 6. Yggdrasil-демон поверх ironwood: TCP-транспорт, TUN, админ-сокет.

  • Фаза 7. Критические фичи: backpressure очередей, оптимизация keepalive. (Это подсказала нейронка, я уже точно не помню.)

Местами Claude Code справлялся блестяще. Например, он сам обнаружил, что в моей реализации bloom-фильтра нужен тот же алгоритм хеширования (FNV-128), что и в Go-библиотеке bits-and-blooms, иначе Rust-узел не сможет договориться с Go-узлом. Растовые крейты почему-то использовали другие реализации.

Местами было тяжелее. Особенно с конвертацией ключей Ed25519 → Curve25519: в Go-коде использовался кастомный bilinear map (u = (1+y)/(1-y) mod p), и стандартные Rust-крейты так не умеют (так подумал Клод). Пришлось реализовать big-integer арифметику вручную и проверять побайтово, что результат совпадает с Go. Но потом стало понятно, что реализация дичайше медленная! Пришлось хорошо поискать и найти стандартный curve25519-dalek, который это делает быстро.

Через 3,5 дня я подключился к публичной сети Yggdrasil с Rust-узла. Пинговал известные серверы, открывал сайты внутри сети - всё работало. Установил ноду на один из домашних серверов.

Неделя на один баг

А потом начался ад.

Симптом был издевательский: первый час всё работало нормально. Дальше - постепенная деградация. Сначала отваливались один-два узла, потом часть сети, потом маршруты начинало плющить совсем, и сеть шатало (извините). Перезапустишь - снова час всё в порядке, потом опять хрень. На маленьких тестовых сетях (3–5 узлов) баг не воспроизводился вообще: всё чисто. Только в реальной публичной сети с сотнями пиров (на моём публичном пире), и только когда пир проработает достаточно долго.

Я неделю ковырялся по этому поводу вместе с Claude. Перерывали Go-исходники, сравнивали логи, добавляли отладочные сообщения, гоняли захваты пакетов. Несколько раз казалось, что нашли - патч применили, узел подержали час, баг вернулся. Это было особенно обидно, потому что весь остальной код, переписанный с Go, работал правильно - handshake, шифрование, bloom-фильтры, pathfinder.

В итоге всё свелось к пяти строчкам в обработчике пира.

В Yggdrasil узлы периодически обмениваются “подписями” (SigReq/SigRes) - это часть протокола построения spanning tree. Заодно по разнице между отправкой запроса и получением ответа измеряется RTT (время до пира). Этот RTT потом используется при выборе родителя в дереве и вычислении наилучшего пути: при прочих равных предпочитается пир с меньшей задержкой.

Так вот, в моей реализации время отправки засекалось так:

async fn peer_reader(...) {
    let mut reader = BufReader::new(conn_read);
    let sig_req_send_time = Instant::now();  // ← один раз на весь reader
    loop {
        //...
        // на каждый входящий SigRes:
        let rtt = sig_req_send_time.elapsed();
        router.handle_response(peer_id, &peer_key, &res, rtt);
    }
}

Заметили? sig_req_send_time создавалась один раз, при старте обработчика пира. И дальше elapsed() от неё измерял не “время с момента отправки запроса”, а время с момента подключения к этому пиру.

Что это означало на практике:

  • Только подключились - RTT 0 секунд, всё норм.

  • Через минуту - RTT каждого ответа от этого пира 60 секунд.

  • Через 10 минут - 600 секунд.

  • Через час - 3600 секунд.

Алгоритм Spanning tree смотрел на эти цифры и принимал решения: “у пира A задержка час, у пира B - два часа, выберу A”. Потом тот же узел через минуту: “у A - час и одна минута, у B - две и одна минута”. Дерево начинало плыть, координаты узлов разъезжались, и маршруты ломались - причём тем сильнее, чем дольше узел работал. На свежем подключении всё было ок, поэтому на коротких тестах баг не ловился.

Фикс - буквально хранить время отправки по каждому SigReq отдельно, в HashMap<PeerId, Instant> внутри роутера. Когда отправляем запрос - записываем время. Когда приходит ответ - берём оттуда. Дельта получается осмысленная.

Мораль простая. LLM сегодня может за несколько дней переписать сетевой стек средней сложности - это правда, я это видел своими глазами. Но это не значит, что человек больше не нужен. Большой проект Claude Code тащит на себе уверенно. А на тонком семантическом нюансе в пяти строках - где Instant::now() стоит не в той функции - может споткнуться так, что баг будет ловиться неделю. Особенно если он не воспроизводится на коротких прогонах, и обнаружить его можно только в живой сети.

И ещё одна вещь, важная для понимания. Это не баг “Claude написал плохо”. В Go-коде это решено правильно (там время отправки хранится в структуре пира). Но при переписывании логики на Rust LLM “оптимизировал”: подумал, что один раз засечь время хватит, ведь reader всё равно читает только этого пира.

Что нового в Yggdrasil-ng

Раз уж я переписывал, я не стал слепо копировать Go-версию. Несколько вещей в Rust-варианте сделаны иначе или добавлены с нуля.

Единый бинарник. В оригинале два исполняемых файла: yggdrasil (демон) и yggdrasilctl (управление). В Rust-версии это один бинарник. Запускаешь без аргументов - это демон. Запускаешь с yggdrasil getPeers - это команда управления. Удобнее ставить, удобнее писать скрипты.

Конфиг в формате TOML. Для проектов на Rust это идиоматичный формат, и я помню тысячи раз за эти семь лет как люди совершали простейшие ошибки в HJSON, который использует гошная версия.

Параметры запуска. Их я тоже переделал, сделал двойные минусы для длинных версий параметров и тому подобное.

Бан-лист по IP. Если с какого-то IP-адреса три раза подряд приходит битый handshake - этот IP временно банится. Защита от шумных или некорректно настроенных пиров, которые иначе забивают логи.

И главное - CKR.

CKR: VPN через Yggdrasil

CKR - Crypto-Key Routing. Идея простая: вы прокидываете обычные IPv4 или IPv6-подсети поверх mesh-сети Yggdrasil, маршрутизируя их по ключу через конкретный узел.

Зачем это нужно - несколько типичных сценариев:

  • Многоузловой VPN. Произвольное число узлов, можно создать свою IPv4-локалку внутри Yggdrasil, о которой знают только ваши узлы. Можно играть в старые сетевые игры, не поддерживающие IPv6, как Hamachi - помните такой?

  • Site-to-site. Соединить две локальные сети (например, домашнюю и офисную) - устройства в обеих сетях видят друг друга по обычным локальным IP, как будто они в одной подсети, а под капотом трафик идёт через Yggdrasil.

  • Exit-node. Один узел в сети раздаёт через себя “обычный” интернет - например, у вас сервер в неавторитарной стране, и весь ваш трафик идёт через Yggdrasil до сервера, а оттуда уже в интернет.

Технически это работает так: в конфиге клиента вы пишете соответствие “такая-то подсеть → такой-то ключ” (подсетью может быть 10.0.0.0/24 или даже 0.0.0.0/0). Когда на TUN-интерфейс приходит пакет с адресом из этой подсети, Yggdrasil не дропает его, а заворачивает в свой собственный зашифрованный туннель и отправляет узлу-владельцу подсети. Тот разворачивает и пускает в свою локальную сеть (или в интернет, если это exit-node).

Это полноценная альтернатива WireGuard или OpenVPN (никому не говорите!). И намного легче делать Multi-hop VPN (или Double VPN), когда вы входите в сеть через один IP, а в интрнет выходите через другой. Пакеты летят через всю сеть.

CKR работает на Linux, Windows и macOS (и как клиент на Android). Маршруты в системе устанавливаются автоматически через кросс-платформенную библиотеку route_manager - никаких ручных ip route add.

Приложения на новом стеке

После того как Rust-демон стал стабильным, я вернулся к мессенджеру Mimir. Старая Go-библиотека yggquic (QUIC-стек внутри Yggdrasil) пошла на свалку. Вместо неё теперь - отдельный Rust-крейт ygg_stream, построенный поверх Yggdrasil-ng.

ygg_stream - это транспортный слой поверх Yggdrasil. Он реализует TCP/KEY: TCP-подобный протокол, в котором вместо IPv4/IPv6-адресов используются 32-байтные ed25519-ключи. Полная семантика TCP (3-way handshake, надёжная упорядоченная доставка, FIN/RST, congestion control по Reno, RTT по Jacobson/Karels), плюс UDP-подобные датаграммы - fire-and-forget, без рукопожатия. Адресацию обеспечивает сам Yggdrasil, шифрование - тоже его, поверх ничего лишнего не накручивается (а в случае с QUIC добавлялся ненужный оверхед с сертификатами и шифрованием).

Mimir получает из этого крейта обычные “соединения” и “датаграммы”, и вся прикладная логика мессенджера работает с ними так же, как раньше с QUIC-соединениями из Go. API получился практически идентичный старому: Node.connect(key, port), Conn.read/write, send_datagram.

В Android-проект ygg_stream экспортируется через UniFFI - инструмент Mozilla (используется даже в Firefox for Android), который из публичного API Rust-крейта генерирует биндинги под Kotlin/Swift/Python. Один раз пишешь Rust - получаешь готовые обёртки. Сборка идёт через cargo ndk - нативные .so-файлы плюс сгенерированные .kt-обёртки.

Mimir - это “лёгкий” сценарий: приложение использует только клиентскую часть стека, без TUN-интерфейса. Полный узел внутрь мобильного приложения с TUN-ом - это уже Yggdrasil-ng для Android. Это второе приложение, которое я сейчас разрабатываю - аналог официального Android-клиента Yggdrasil (я тоже его мейнтейнер, и у которого внутри Go-демон), только с Rust-сердцем. Здесь уже доступны все “взрослые” фичи: TUN-интерфейс, внутрисетевые DNS-серверы с блокировкой рекламы и аналитики, и главное - CKR. То есть с телефона можно поднять туннель к серверу и пустить через него весь трафик устройства, или объединить телефон с домашней сетью site-to-site.

В опенсорс это приложение я пока не выложил - думаю, как его правильно распространять. На сегодня оно живёт в виде бесплатных APK-сборок, которые я выкладываю в Telegram-чат сообщества.

И буквально сегодня я доделал ещё одну важную вещь, которая стоит отдельного упоминания. Раньше у меня TUN-интерфейс читался и писался с Kotlin-стороны: Android поднимает TUN, Kotlin-код в цикле читает из него пакеты, передаёт в Rust-библиотеку, получает обратно пакеты, отправляет в TUN. Каждый пакет совершал минимум четыре пересечения JNI-границы и проходил через Java-аллокаторы.

Сегодня я перенёс работу с TUN целиком внутрь Rust-крейта: FileDescriptor отдаётся в Rust один раз, дальше всё (чтение, шифрование, маршрутизация, расшифровка, запись) живёт на Rust-стороне без участия JVM. Результат - прирост скорости в 9–10 раз (пропускная способность через CKR-туннель), резко меньшее потребление памяти и почти полное снятие нагрузки с GC.

Что дальше

Это вторая статья цикла. В следующих хочу разобрать конкретные технические темы поглубже - на выбор:

  • Шифрование сессий - как именно работает сессионный handshake, рэтчетинг ключей, почему Ed25519 приходится конвертировать в Curve25519 и как это устроено.

  • Pathfinder изнутри - bloom-фильтры, path lookup, broken paths.

  • CKR на практике - отдельная статья с конкретными конфигами: как поднять exit-node, как сделать site-to-site, какие подводные камни.

  • Android-разработка с UniFFI - для тех, кто хочет встраивать Rust-код в мобильные приложения.

Что больше интересно - пишите в комментариях, расставлю приоритеты по запросам.

Спасибо, что дочитали. Yggdrasil-ng - открытый проект, исходники здесь, баг-репорты приветствуются, PR-ы не очень.