3fd9b42bb0
Закрыты накопленные мелкие хвосты из ревью F/J/H/G: - Stage-нормализация: Stage-0/1/2 → Stage 0/1/2 по 6 докам (a/b/f/h/j/hardware); каноническая запись Stage 0/1/2 в glossary. - a-base §8: видео-пайплайн (DMABUF камер / VPU dashcam) внесён в OOM-порядок — задняя защищена (Stage 1), dashcam/surround throttleable. - a-base §12: dashcam-медиа (отдельный носитель) + контакты/журнал (G) в список factory-reset wipe. - b §12: grace-hold резолвнут ✅ — J запросчик (J §7), B владелец/арбитр (§4 шаг 2, §7). - dev-environment: моки fake-камера (J)/аудио (H)/BT-телефон (G) + plugin-host-харнесс; just-цели plugin-dev-run/sideload. - J §3/§11/§13 + hardware §4: сигнал реверса ✅ GPIO фонаря з.х. (выбранный дефолт); CAN-gear отложен (нет gear-сигнала в E). - glossary.md: наполнен (~55 терминов в 7 областях: машина/CAN, платформа/IPC, ассистент/аудио, питание/boot, хранилище/OTA, связь/телефон, безопасность). Tier-3 capability-catalog + roadmap не трогаются — зависят от доменов I+L. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
135 lines
13 KiB
Markdown
135 lines
13 KiB
Markdown
# Домен F — Plugin host & экосистема
|
||
|
||
> Рантайм и экосистема плагинов **поверх App-Host**: жизненный цикл (install/update/remove),
|
||
> валидация и подпись манифеста, дистрибуция, dev-tools. API/манифест — [plugin-sdk](../contracts/plugin-sdk.md);
|
||
> исполнение/sandbox — App-Host (ядро); **F — оркестрация и экосистема**.
|
||
|
||
Статус: **v2 (на ревью).** v2 — после adversarial-ревью (17 находок).
|
||
Связано с: [plugin-sdk.md](../contracts/plugin-sdk.md) (API) · [security-privacy.md](../contracts/security-privacy.md) (sandbox/подпись/id) · [ipc.md](../contracts/ipc.md) (`PluginManager`, `AppHost`) · [a-base-system.md](a-base-system.md) (§3 durable-write/storage, §8 память) · домен C (capability-review UX) · все домены (точки расширения)
|
||
|
||
---
|
||
|
||
## 1. Назначение и границы
|
||
|
||
- **F:** жизненный цикл плагинов + валидация манифеста + дистрибуция + dev-tools + enforcement версий + бюджет ресурсов.
|
||
- **App-Host (ядро, `ru.shturman.AppHost`)** физически запускает/супержит/песочит. **F оркестрирует, App-Host исполняет.**
|
||
- **plugin-sdk** = API/манифест; **security-privacy** = sandbox/capabilities/доверие. F их **использует, не дублирует**.
|
||
- **Границы:** не ядро; не обходит capability-модель; не трогает CAN/safety.
|
||
|
||
## 2. Жизненный цикл плагина
|
||
|
||
`discover → validate → install → activate → run → update → remove`. F оркестрирует; запуск/sandbox — App-Host.
|
||
**First-party** апы путь НЕ проходят (в подписанном base-образе, security-privacy §5).
|
||
|
||
- **Где живёт/исполняется:** пакет (manifest + бинарь + ассеты) — в `/data/apps/<id>/`. **Код — отдельное
|
||
exec-поддерево** (`/data/apps/<id>/bin`, монтируется exec в bubblewrap); данные (`storage`) — **noexec**.
|
||
Политика exec/mount на `/data` — совместно с a-base §3 (открытый вопрос §10).
|
||
- **Передача в App-Host (IPC):** после `validate`+`install` `PluginManager` зовёт **`AppHost.LoadApp(id)`**
|
||
(читает манифест, конфигурит bubblewrap + фильтр-прокси + `sender→манифест`), затем id доступен `StartApp`.
|
||
`RemovePlugin`/`UpdatePlugin` → **`AppHost.UnloadApp(id)`** (снести sandbox/прокси/identity-binding — иначе висит авторизация на шине).
|
||
- **Teardown (remove/update):** если работает → `StopApp` → await `AppStopped` (таймаут/force-kill) →
|
||
Perm-Broker отзывает гранты + подписки VehicleData падают по owner-exit → удалить `/data/apps/<id>`
|
||
(опц. экспорт). (`NameOwnerChanged` — сеть безопасности при крэше, не плановый путь; план зовёт `StopApp` явно.)
|
||
- **Атомарность install/update** (power-safe #5, контракт a-base §3): распаковка в staging `/data/apps/<id>.new/`
|
||
→ fsync → **атомарный `rename`** на живой каталог → fsync(parent); прежняя версия цела до успеха (откат);
|
||
health-check до commit (аналог RAUC mark-good); идемпотентное доедание `<id>.new` на next boot.
|
||
|
||
## 2a. Бюджет ресурсов плагина
|
||
|
||
App-Host из манифеста на activate ставит **cgroup-лимиты** (`MemoryMax`/`MemoryHigh`, `CPUQuota`, `pids.max`):
|
||
дефолтный потолок + опц. больший в манифесте (виден в ревью — как дисковая квота plugin-sdk §4.4).
|
||
В OOM-иерархии (a-base §8) сторонний плагин — **низкий приоритет** (ниже Stage 1-ядра и офлайн-LLM):
|
||
убивается раньше killer-фичи → `AppCrashed` → деградация (#4). CPU-троттлинг — чтобы busy-loop не съел UI (#11).
|
||
|
||
## 3. Валидация манифеста (целостность — только с подписью)
|
||
|
||
- **Schema-валидация** (plugin-sdk §2): поля; capabilities из таксономии; `len(tiles)≤ui_tiles`; `ui_screens`;
|
||
`vehicle_read` только из каталога data-model; i18n-строки (`ru` обязателен).
|
||
- **`shturman_api`:** неподдерживаемая → `Error.Unsupported` (plugin-sdk §7); **EOL установленного** (§3 ниже).
|
||
- **id-целостность** (security-privacy §5): отказ при коллизии с установленным/встроенным. **Манифестный id**:
|
||
`ru.shturman.*` (весь tree) **закрыт** для сторонних — их id = свой reverse-DNS (`dev.example.*`). *(Отдельно:
|
||
D-Bus OWN-экспорт плагина — платформа выдаёт префикс `ru.shturman.plugin.<id>.*`, это не манифестный id.)*
|
||
- **Sideload-гигиена (распаковка привилегированным до sandbox):** отбой path-traversal/symlink-escape;
|
||
лимит несжатого размера/числа записей (анти-zip-bomb); проверка места `/data`/квоты до распаковки (без частичной порчи).
|
||
- **Целостность во времени (без подписи неполна):** App-Host **ре-валидирует манифест на КАЖДОМ activate**
|
||
(capabilities из файла, не кэш с момента approve); **пин одобренного capability-набора** (хэш) — расширение
|
||
на диске после approve → форс ре-ревью, не молча. Полная целостность — только с подписью (store-фаза).
|
||
- **Аудит:** install/update/remove + grant/revoke — события **нормативного audit-log** (владелец A §9 /
|
||
security-privacy): id, версия, capability-набор, время (без payload). `PluginManager` эмитит их вместе с сигналами §7.
|
||
|
||
## 4. Дистрибуция
|
||
|
||
- **Sideload** (локальный пакет, на свой риск, без подписи) — v3.
|
||
- **Курируемый стор/реестр** с ревью + **обязательной подписью** — later. Пакет: каталог `manifest.yaml` + бинарь + ассеты + `locales/`.
|
||
|
||
## 5. Capability-review и управление (UX — домен C)
|
||
|
||
- Install-time: запрашиваемые capabilities + предупреждения о рисковом (`vehicle_read`+`network`; неподдерживаемые сигналы) — security-privacy §5/§7.
|
||
- Review/revoke грантов — UI домена C.
|
||
|
||
## 6. Dev-tools и тест-харнесс (#13)
|
||
|
||
- **v0 (без рантайма):** SDK-крейт `shturman-sdk`, **scaffolding** плагина, **валидатор манифеста**.
|
||
- **dev-run:** быстрый локальный запуск плагина в dev-VM (App-Host есть с v0); sandboxed install-flow — v3.
|
||
Нужен `justfile`-таргет в dev-environment.
|
||
- **Тест-харнесс plugin-host (#13):** библиотека **плохих манифестов** (коллизия id, неподдерж. `shturman_api`,
|
||
`tiles>ui_tiles`, capability вне таксономии, `vehicle_read` вне каталога, попытка `ru.shturman.*`) +
|
||
**тест-плагины** (crash-loop, mem-hog, quota-overflow, capability-escape, slow-shutdown, power-loss при update).
|
||
Завести в dev-environment (fault-injection) + интеграционный тир CI.
|
||
|
||
## 7. IPC
|
||
|
||
- **`ru.shturman.PluginManager`** (домен F, в реестре ipc §3): `InstallPlugin(pkg)`, `RemovePlugin(id)`,
|
||
`UpdatePlugin(id)`, `ListPlugins()`; сигналы `PluginInstalled/Removed/Updated` (+ эмит audit-записей).
|
||
- **Передача в App-Host:** `AppHost.LoadApp(id)` / `UnloadApp(id)` (ipc §3). Управление плагинами —
|
||
**привилегированная операция**, недоступна самим плагинам через прокси.
|
||
|
||
## 8. Функции
|
||
|
||
| функция | MVP/later | зависит от | фаза |
|
||
|---------|-----------|------------|------|
|
||
| SDK-крейт `shturman-sdk` | **MVP** | — | v0 |
|
||
| Dev-tools: scaffolding + валидатор манифеста | **MVP-dev** | — | v0 |
|
||
| Dev-run плагина в VM (через App-Host) | **MVP-dev** | App-Host, dev-environment | v0+ |
|
||
| Тест-харнесс plugin-host (#13) | **MVP-dev** | dev-environment | v0+ |
|
||
| Жизненный цикл (install/update/remove) + LoadApp/UnloadApp | later | App-Host, PluginManager, plugin-sdk | v3 |
|
||
| Атомарный install/update (staging+rename, a-base §3) | later | a-base §3 | v3 |
|
||
| Бюджет ресурсов (cgroup + OOM-приоритет) | later | a-base §8 | v3 |
|
||
| Schema/`shturman_api`/id-валидация + ре-валидация + capability-pin | later | plugin-sdk, security-privacy | v3 |
|
||
| Sideload (+ гигиена распаковки) | later | App-Host, PluginManager | v3 |
|
||
| Capability-review UX (с C) + аудит операций | later | C, security-privacy, A §9 | v3 |
|
||
| Подпись манифеста/бандла + keyring | later | security-privacy (схема §10); v4-trust-anchor (signed OTA) | v3+/v4 |
|
||
| Курируемый стор/реестр | later | — | later |
|
||
|
||
## 9. Зависимости
|
||
|
||
- **Вниз/вбок:** App-Host (запуск/sandbox/прокси/Load-Unload), plugin-sdk (API/манифест), security-privacy
|
||
(capabilities/доверие/подпись/namespace), a-base (§3 durable-write/exec-mount, §8 память/OOM, §9 audit-log),
|
||
data-model (валидация `vehicle_read`), C (review/revoke UI), dev-environment (dev-tools/харнесс).
|
||
- **Вверх:** механизм расширения third-party для всех доменов.
|
||
|
||
## 10. Открытые вопросы
|
||
|
||
- 🟡 **Exec/mount-политика `/data`** (exec-поддерево бинаря vs noexec) — совместно с a-base §3.
|
||
- 🟡 **Схема подписи** (формат, keyring издателей, ревокация, охват = манифест+бинарь) — со стором. → security-privacy + F.
|
||
- 🟡 **WASM-тир структурно несовместим с identity-моделью:** in-process WASM не имеет своего D-Bus-соединения/PID/cgroup
|
||
→ sender-identity-гейтинг (VehicleData/Settings/OWN) к нему неприменим без host-side брокера в рантайме. Не просто «паковка». → architecture §7 / security-privacy.
|
||
- ◻️ **`shturman_api` EOL/депрекация** установленных: warn→grace→block-launch (не тихий крэш), роль UpdatePlugin/ревью. (тайминг — ipc §2).
|
||
- ◻️ **Governance стора** (модерация, доверие издателей).
|
||
|
||
---
|
||
|
||
## Журнал решений (домен F)
|
||
|
||
| Решение | Выбор | Дата |
|
||
|---------|-------|------|
|
||
| Граница | F — оркестрация; App-Host исполняет (LoadApp/UnloadApp); plugin-sdk — API | 2026-06-16 |
|
||
| Где живёт | `/data/apps/<id>/`; код — exec-поддерево, данные — noexec; политика с a-base §3 | 2026-06-16 |
|
||
| Жизненный цикл | install/activate/teardown с явным StopApp+отзыв грантов; first-party вне пути | 2026-06-16 |
|
||
| Атомарность | staging + атомарный rename (a-base §3 durable-write); откат; идемпотентное доедание | 2026-06-16 |
|
||
| Ресурсы | cgroup-лимиты из манифеста; плагин — низкий OOM-приоритет (a-base §8) | 2026-06-16 |
|
||
| Валидация | ре-валидация на каждом activate + capability-pin; sideload-гигиена распаковки; аудит операций | 2026-06-16 |
|
||
| Namespace | манифестный id `ru.shturman.*` закрыт для сторонних; OWN-экспорт `ru.shturman.plugin.<id>.*` — выдаёт платформа | 2026-06-16 |
|
||
| Доверие | install-approve+sandbox (sideload на риск); подпись+keyring — со стором | 2026-06-16 |
|
||
| Фазы | SDK/dev-tools/харнесс — v0; плагин-экосистема — v3 | 2026-06-16 |
|