Перейти к содержимому
SheetForge

Веб-маркет плагинов

В веб-приложении есть магазин плагинов для установки плагинов SheetForge в браузер, плюс отдельный путь для сайдлоадинга непроверенного плагина по URL GitHub. Тот же магазин, пересобранный на UIToolkit, поставляется и внутри Unity.

Реестр — один статический файл, два читателя

Список магазина берётся из единого статического файла реестра (public/registry/plugins.json), который читают и веб-приложение, и окно магазина внутри Unity. Список один, поэтому обе поверхности всегда показывают один и тот же каталог.

SheetForge не хостит бинарники плагинов. Это делает собственный GitHub release каждого автора. Запись в реестре — это метаданные плюс зафиксированный хеш, а не копия плагина.

Фиксация по хешу — целостность прежде, чем ядро увидит хоть один байт

Каждая запись реестра несёт SHA-256, зафиксированный в момент одобрения плагина. При получении каждый полученный байт проверяется против этого хеша прежде, чем он вообще достигнет ядра. Расхождение хотя бы в один байт отклоняется.

Именно это делает безопасным то, что «бинарник живёт на чужом GitHub»: релиз можно скачать заново откуда угодно, но загружаются только в точности те байты, что были одобрены.

Установка в один клик через прокси сервера

Браузеры не могут напрямую получать файлы GitHub release — правила cross-origin (CORS) это блокируют. Поэтому получение проходит через прокси-маршрут сервера (api/market/artifact, подключённый через ArtifactProxy в lib/market/install.ts), который получает релиз на стороне сервера и передаёт его обратно потоком. Поэтому установка — это один клик.

Путь ручного скачивания и загрузки остаётся как вторичный запасной вариант на случай, когда прокси не может достучаться до релиза. Он проходит идентичную проверку хеша — загруженному вручную файлу доверяют не больше, чем полученному через прокси.

Шлюз совместимости — после целостности, до регистрации

Прохождение проверки хеша доказывает, что байты — одобренные. Это ничего не говорит о том, может ли этот хост прочитать формат этого плагина, — это второй и отдельный вопрос.

Ответ приходит из самой проверенной DLL: декларации на уровне сборки, называющей поколение формата плагина, для которого она собрана, и минимальную версию хоста, которую она принимает.

  • Листинг рекламирует, сборка решает. Запись реестра несёт те же два значения (pluginFormat, minHost), так что каталог может показать их до загрузки. Сам шлюз читает декларацию из байтов, только что прошедших проверку. Листинг может устареть; скомпилированная декларация — нет.
  • Один шлюз, три пути. Установка из маркета, сайдлоадинг и обычный локальный файл — все спрашивают один и тот же предикат, так что ни один маршрут не может тихо принять то, что отклоняет другой.
  • Всё или ничего на сборку. Отклонённая сборка не регистрирует ничего — никогда половину своих контрактов, — а отказ называет то, что заявила сборка, против того, что читает этот хост.
  • Отсутствие декларации — это нормально. Плагин, собранный до появления атрибута, читается как самое раннее поколение без требования к хосту, поэтому загружается точно так же, как и всегда.

Кеширование и выгрузка

Байты, прошедшие проверку хеша, кешируются в браузере (IndexedDB), так что плагин, включённый в списке, загружается автоматически при последующих визитах — вы включаете его один раз.

Отключение или удаление плагина вступает в силу немедленно: приложение просит ядро убрать эту сборку из композиции плагинов и пересобрать сеанс, поэтому её типы ячеек, перечисления, шаблоны, цветовые пресеты, действия студии и наложения холста исчезают без обновления страницы. (Сам .NET никогда не выгружает сборку — байты остаются в странице, но бездействуют; если снова включить тот же плагин, ядро повторно активирует резидентную сборку вместо того, чтобы загружать её второй раз.)

Сайдлоадинг непроверенного плагина по URL GitHub

Отдельно от курируемого реестра вы можете передать приложению произвольный URL GitHub, чтобы сайдлоадить непроверенный плагин (lib/market/sideload.ts, обслуживается api/market/github). Это для опробования плагина, которого нет в каталоге.

Поскольку эта ось принимает URL, введённый пользователем, а не проверенную запись реестра, это единственное место, где напрямую обеспечивается защита от SSRF:

  • URL должен разрешаться в хост семейства GitHubgithub.com, raw.githubusercontent.com, release-assets.githubusercontent.com и подобные, — сопоставляемые точно, в нижнем регистре.
  • Редиректы, которые утекали бы во внутреннюю сеть, блокируются на этой границе.

Сайдлоаженные артефакты кешируются под отдельной меткой владельца (sideload:). Так что непроверенный плагин, который случайно разделяет байты с записью реестра, держится отдельно от одобренного — сайдлоад никогда не маскируется под одобренный плагин.

GitHub как источник импорта

Оба пути пропускают байты плагина через один и тот же конвейер:

  • Установка из реестра забирает артефакт, размещённый в GitHub release автора, через прокси сервера, затем проверяет его против зафиксированного SHA-256.
  • Сайдлоадинг принимает сырой URL GitHub, ограниченный хостами семейства GitHub, затем проверяет байты тем же способом.

В обоих случаях ограничение CORS браузера на файлы GitHub release обрабатывается на стороне сервера, а целостность сохраняется проверкой хеша на клиенте до того, как ядро что-либо загрузит.

Магазин внутри Unity

Магазин плагинов Unity был пересобран на UIToolkit, чтобы выглядеть как веб-магазин, — сетка карточек рядом с панелью деталей, читающая тот же статический реестр, с тем же отклонением при несовпадении хеша и уведомлением об установке с полным доверием.

Вход и список плагинов, хранимый в браузере, вместе с пресетами остаются только веб; окно Unity — это каталог и поверхность установки.

Похожие страницы

  • SheetForge Web — браузерное приложение, в котором живёт магазин
  • Создание плагинов — создание плагина, на который указывает запись в маркете