Публикация плагина 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 | Отображаемое имя |
version | SemVer major.minor.patch |
type | widget, 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 показывает весь список пользователю и просит подтверждения. Но отдельного ограничения процесса по этим строкам сейчас нет: плагин остаётся кодом процесса панели и после согласия получает его возможности. Подпись удостоверяет издателя, но не изолирует код. Заявляйте честно только то, что нужно, и не просите лишнего.
Как плагин попадает к пользователю#
- Вы публикуете Forgejo-релиз со всеми четырьмя файлами. Черновики и prerelease не ставятся.
- Пользователь добавляет ссылку на репозиторий вида
https://altlinux.space/<владелец>/<репозиторий>(только этот хост). - Niti читает список релизов (
/api/v1/repos/<владелец>/<репозиторий>/releases) и выбирает самую новую совместимую версию. - Проверяются размер и SHA-256 архива, затем подпись
minisign, затем доверие к издателю. - При первом контакте с издателем Niti показывает имя, fingerprint, версию, источник и права. Доверие записывается только после явного подтверждения (модель TOFU). Смена fingerprint требует нового подтверждения.
- До подтверждения код не загружается.
Безопасность клиента#
- Допускается только 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.
Что делать автору#
- Соберите виджет по руководству.
- Сгенерируйте ключ minisign и сохраните закрытый ключ в надёжном месте.
- Упакуйте виджет в архив, посчитайте SHA-256 и размер, подпишите архив и манифест.
- Создайте релиз и приложите четыре файла (работа с ALS).
- Напишите сопровождающим: чат ALT Atomic или issue в NitiVala. Они подскажут, как добавить ваш репозиторий в каталог.