Git

Публикация плагина Niti

Готовый виджет можно отдать другим людям через каталог расширений. Установка идёт через Forgejo-релизы на altlinux.space: пользователь добавляет ссылку на ваш репозиторий, Niti скачивает релиз, проверяет подписи и после согласия пользователя включает виджет на горячую, без перезапуска панели.

Важно. Каталог и подписи реализованы в клиенте Niti. Но в репозитории NitiVala нет команды загрузки, генератора index.json и описания серверного процесса публикации. Поэтому подготовьте манифест, архивы и подписи по формату ниже, а способ публикации на конкретный путь altlinux.space согласуйте с сопровождающими.

Что нужно приготовить#

В каждом релизе репозитория должны лежать четыре файла:

ФайлЧто это
plugin.jsonМанифест плагина
plugin.json.minisigПодпись манифеста
<имя>-<версия>-<платформа>.tar.gzАрхив плагина
<имя>-<версия>-<платформа>.tar.gz.minisigПодпись архива

Подписи делаются инструментом minisign (алгоритм Ed25519).

Манифест plugin.json#

{ "schema": 1, "id": "org.example.niti.weather", "name": "Погода", "version": "1.2.0", "type": "widget", "min_niti": "0.4.0", "panel_api": 1, "permissions": ["network"], "artifacts": [{ "platform": "x86_64-linux-gnu", "kind": "tar.gz", "path": "niti-weather-1.2.0-x86_64.tar.gz", "sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "size": 381240, "signature": "niti-weather-1.2.0-x86_64.tar.gz.minisig" }], "publisher": { "id": "org.example", "name": "Example", "key_id": "RW...ABC", "fingerprint": "SHA256:…", "public_key": "RW..." } }

Поля#

ПолеПравила
schemaЧисло 1
idСтрочная строка до 128 символов в обратной DNS-форме, начинается с буквы или цифры. Это идентификатор в панели и имя каталога
nameОтображаемое имя
versionSemVer major.minor.patch
typewidget, module или service. Сейчас загружаются только widget
min_nitiМинимальная версия Niti, SemVer
panel_apiВерсия API панели. Сейчас 1
permissionsСписок уникальных строк из files.read, files.write, network, dbus.session, dbus.system, exec. Пустой список значит, что прав не запрошено. Не больше 32
artifactsОт 1 до 32 записей: платформа, формат tar.gz, относительный путь файла, SHA-256 (64 символа), точный размер до 1 ГиБ, имя файла подписи
publisherИдентификатор и имя издателя, key ID, fingerprint и открытый ключ minisign

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

Fingerprint считается как SHA-256 от 42 байтов открытого ключа minisign (Ed, идентификатор ключа и сам ключ Ed25519). Значение в манифесте обязано совпасть.

Содержимое архива#

Архив содержит три файла:

  • <id>.plugin: описание для libpeas;
  • библиотеку libpeas с именем, указанным в Module;
  • <Module>.manifest с ключами Module=<Module> и SHA256=<хеш библиотеки>.

Имя модуля должно совпадать с id, чтобы включение через API было однозначным. При распаковке отклоняются абсолютные пути, .., симлинки, жёсткие ссылки, устройства, биты setuid, setgid и sticky, а также превышение лимитов размера и числа файлов.

Права плагина#

permissions это заявленные права. Niti показывает весь список пользователю и просит подтверждения. Но отдельного ограничения процесса по этим строкам сейчас нет: плагин остаётся кодом процесса панели и после согласия получает его возможности. Подпись удостоверяет издателя, но не изолирует код. Заявляйте честно только то, что нужно, и не просите лишнего.

Как плагин попадает к пользователю#

  1. Вы публикуете Forgejo-релиз со всеми четырьмя файлами. Черновики и prerelease не ставятся.
  2. Пользователь добавляет ссылку на репозиторий вида https://altlinux.space/<владелец>/<репозиторий> (только этот хост).
  3. Niti читает список релизов (/api/v1/repos/<владелец>/<репозиторий>/releases) и выбирает самую новую совместимую версию.
  4. Проверяются размер и SHA-256 архива, затем подпись minisign, затем доверие к издателю.
  5. При первом контакте с издателем Niti показывает имя, fingerprint, версию, источник и права. Доверие записывается только после явного подтверждения (модель TOFU). Смена fingerprint требует нового подтверждения.
  6. До подтверждения код не загружается.

Безопасность клиента#

  • Допускается только HTTPS на altlinux.space, без перенаправлений, имён пользователей в адресе, query и fragment.
  • Индекс не больше 1 МиБ, архив не больше 1 ГиБ.
  • Установка и обновление не означают согласия: активация идёт после подтверждения.
  • Сбой одного плагина переводит в состояние failed только его. После трёх падений подряд плагин отключается. Прежняя рабочая версия сохраняется для отката.

Управление: D-Bus#

Tuner управляет расширениями по D-Bus, не загружая чужой код в свой процесс. Шина org.altlinux.Niti.Extensions1, путь /org/altlinux/Niti/Extensions1, доступ только локальным процессам того же UID.

МетодЧто делает
ListInstalled()Установленные плагины
ListPlugins()Все доступные и установленные плагины в JSON
AddRepository(url)Добавить источник
Refresh()Обновить список релизов
Install(id)Скачать и проверить, дождаться согласия
GetPending(id)Сводка для окна подтверждения
ConfirmInstall(id, fingerprint)Подтвердить и включить
SetEnabled(id, enabled)Включить или отключить без перезапуска панели
Update(id)Подготовить новую версию
Rollback(id)Вернуться к последней рабочей версии
Remove(id)Отключить и удалить версии, данные пользователя остаются

Сигнал StateChanged(id, state, message) сообщает о смене состояния: available, pending-consent, installed, failed, enabled, disabled, rollback.

Что делать автору#

  1. Соберите виджет по руководству.
  2. Сгенерируйте ключ minisign и сохраните закрытый ключ в надёжном месте.
  3. Упакуйте виджет в архив, посчитайте SHA-256 и размер, подпишите архив и манифест.
  4. Создайте релиз и приложите четыре файла (работа с ALS).
  5. Напишите сопровождающим: чат ALT Atomic или issue в NitiVala. Они подскажут, как добавить ваш репозиторий в каталог.