Files
shturman/docs/contracts/ipc.md
T
kk0t9 3d13bb5827 docs: tech-stack + контракты ipc/data-model (+ ревью-фиксы)
- tech-stack: Rust-first (один прод-рантайм; Python — dev-only), полный стек, крейты
- architecture: ассистент Python→Rust для консистентности; boot-порядок
  (Broker+App-Host до Shell); потолок частоты сигналов ~10–20 Гц
- contracts/ipc: реестр D-Bus (сервисы ядра/апов, соглашения, портал-брокеринг)
  + открытые вопросы из self-review
- contracts/data-model: VSS-aligned каталог сигналов, OBD-PID маппинг, DTC-модель;
  добавлен MIL-статус (PID 0x01) для killer-фичи, состояние машины, расход-estimate

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 20:01:36 +03:00

147 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Контракт: IPC (D-Bus)
> Backbone связей: реестр D-Bus-сервисов, их интерфейсов и соглашений.
> Формализует карту связей из [architecture.md](../architecture.md) §5 в конкретные
> контракты. К нему цепляются data-model, plugin-sdk и все домены.
Статус: **v1 (на ревью).**
Связано с: [architecture.md](../architecture.md) (§45) · [data-model.md](data-model.md) · [plugin-sdk.md](plugin-sdk.md) · [security-privacy.md](security-privacy.md)
Область: **control plane** (D-Bus). Аудио/видео/графика — НЕ здесь (PipeWire/Wayland, см. architecture §4).
---
## 1. Шина и топология
- **Одна системная шина устройства** (Штурман — single-purpose appliance, системная шина *и есть* его шина) со строгой D-Bus-политикой.
- Ядро-сервисы общаются на ней напрямую.
- **Песочные апы/плагины напрямую шину НЕ видят** — каждому выдаётся
**фильтрующий D-Bus-прокси** (паттерн `xdg-dbus-proxy`), настроенный App-Host'ом
из capabilities манифеста (см. §5). Это реализация портал-модели из решения №5.
> 🟡 *Мелкий выбор на подтверждение:* системная шина устройства (рекомендую,
> проще) vs выделенный экземпляр `dbus-daemon` только для Штурмана (чище изоляция
> от хост-сервисов, но лишний компонент). Прокси-фильтрация даёт изоляцию в обоих
> случаях.
## 2. Соглашения
| Аспект | Правило |
|--------|---------|
| Well-known имя | `ru.shturman.<Service>` (напр. `ru.shturman.VehicleData`) |
| Путь объекта | `/ru/shturman/<Service>` |
| Интерфейс | `ru.shturman.<Service>N``N` = мажорная версия (напр. `…VehicleData1`) |
| Версионирование | аддитивные изменения внутри версии; ломающие → новый интерфейс `…2` |
| Ошибки | `ru.shturman.Error.<Name>`: `PermissionDenied`, `NotAvailable`, `ReadOnly`, `InvalidArgument`, `Unsupported` |
| Действие | **метод** |
| Изменение состояния | **сигнал** |
| Текущее состояние | **property** (+ стандартный `PropertiesChanged`) |
| Асинхронность | всё async (zbus + tokio); долгие операции не блокируют |
| Стандартные интерфейсы | `org.freedesktop.DBus.{Properties,Introspectable,Peer}` |
> Полные сигнатуры (XML-интроспекция) фиксируются при реализации; здесь — реестр и ключевые члены.
---
## 3. Реестр сервисов — ядро (привилегированные)
### `ru.shturman.VehicleData` — данные машины (**READ-ONLY**)
- **Методы (только чтение):** `ListSignals() → [name]`, `GetSignal(name) → (value, unit, ts)`, `Subscribe(names, max_hz)`/`Unsubscribe(names)`, `GetDtcs() → [(code, status, desc)]`.
- **Сигналы:** `SignalChanged(name, value, ts)`**только подписчикам и только по подписанным** именам (не широковещательно «всё всем»), `DtcsChanged([...])`.
- **Политика частоты:** на шину сигналы идут **с потолком (~10–20 Гц)** — этого хватает для читаемых датчиков и держит control-plane лёгким. Сырой высокочастотный CAN остаётся внутри VehicleData. Цифровому приборному щитку, если нужна более плавная стрелка, — клиентская интерполяция или выделенный быстрый канал (не D-Bus); см. «Открытые вопросы».
- **Properties (горячие, текущее значение):** `Speed`, `Rpm`, `CoolantTemp`, `BatteryVoltage`, `Online`.
-**Методов записи нет** — ни `SetSignal`, ни actuator-команд, ни clear-DTC. Архитектурная гарантия read-only (принцип #2). Типы — [data-model.md](data-model.md).
### `ru.shturman.Power` — питание и жизненный цикл
- **Методы:** `GetPowerState() → state`, `RequestSleep()` (внутр.).
- **Сигналы:** `AccChanged(on)`, `ShutdownImminent(seconds)`, `Sleep()`, `Wake()`.
- **Properties:** `IgnitionState`, `Uptime`, `PowerSource`.
### `ru.shturman.Settings` — конфигурация и состояние
- **Методы:** `Get(key) → value`, `Set(key, value)`, `List(prefix) → [key]`, `Reset(key)`.
- **Сигналы:** `Changed(key, value)`.
- Namespace на каждый ап изолирован (брокер не даёт читать чужой).
### `ru.shturman.PermBroker` — выдача разрешений (привратник)
- **Методы:** `CheckCapability(app, cap) → bool`, `RequestRuntimeGrant(cap) → granted` (рантайм-промпт пользователю, напр. «ап X хочет сеть»).
- **Сигналы:** `GrantChanged(app, cap, granted)`.
- Основная фильтрация — на уровне прокси (§5); этот API для рантайм-согласий.
### `ru.shturman.AppHost` — запуск/супервизия апов и плагинов
- **Методы:** `ListApps() → [(id, status)]`, `StartApp(id)`, `StopApp(id)`, `GetStatus(id) → status`.
- **Сигналы:** `AppStarted(id)`, `AppStopped(id)`, `AppCrashed(id, reason)`.
- (Установка/дистрибуция плагинов — домен F, не здесь.)
### `ru.shturman.Connectivity` — сеть (обёртка NM/MM)
- **Методы:** `GetStatus() → status`, `ListNetworks() → [...]`, `Connect(id)`, `Disconnect()`.
- **Сигналы:** `ConnectivityChanged(online)`, `NetworkChanged(...)`.
- **Properties:** `Online`, `Type` (wifi/modem), `SignalStrength`.
---
## 4. Реестр сервисов — апы (на SDK)
### `ru.shturman.Assistant`
- **Методы:** `SendText(query) → reply`, `StartListening()`, `StopListening()`, `RegisterIntents(handler_path, [pattern])` (для плагинов с capability `assistant_intents`).
- **Сигналы:** `StateChanged(idle|listening|thinking|speaking)`, `TranscriptUpdated(text)`, `ReplyUpdated(text)`.
- Контекст машины подмешивается ассистентом из `VehicleData` (см. architecture §5).
### `ru.shturman.Shell` — UX-host (слот-модель, решение №6)
- **Методы:** `RegisterTile(decl)`, `RegisterScreen(decl | surface_handle)`, `RequestForeground(slot)`, `ShowOverlay(decl)`.
- **Сигналы:** `ForegroundChanged(app)`, `NavigatedTo(screen)`, `DistractionModeChanged(level)`.
- Декларативный вклад = данные (рендерит shell); богатый = Wayland-поверхность.
### `ru.shturman.Media` / `…Nav` / `…Phone`
- Свои интерфейсы (play/pause/route; navigateTo/cancel; dial/answer/hangup). **Детали — в спеках доменов** H/I/G; здесь — только факт регистрации на шине.
---
## 5. Брокеринг доступа песочных апов (портал-паттерн)
1. Манифест плагина декларирует capabilities (`vehicle_read:[speed]`, `network`, `assistant_intents`…).
2. App-Host поднимает плагин в bubblewrap и даёт ему **фильтрующий D-Bus-прокси**, сконфигурированный под эти capabilities.
3. Прокси пропускает только разрешённые сервисы/интерфейсы/методы/сигналы. Пример: `vehicle_read:[speed]` → виден `VehicleData.GetSignal("speed")` и `SignalChanged` по speed; **не виден** `Power`, чужие апы, любые write-методы.
4. Рантайм-согласия (сеть «сейчас») — через `PermBroker.RequestRuntimeGrant`.
Итог: плагин физически не может дотянуться до того, чего нет в манифесте. Детали модели — [security-privacy.md](security-privacy.md).
---
## 6. Точки расширения через IPC
- **Интенты ассистента:** плагин реализует `ru.shturman.IntentHandler1.HandleIntent(intent_id, slots) → result` и регистрируется через `Assistant.RegisterIntents`. Латентно-критичные интенты (громче, домой) ассистент обрабатывает локально без LLM.
- **Вклад в UI:** плагин зовёт `Shell.RegisterTile/RegisterScreen` (декларативно или поверхностью).
Полные контракты SDK (манифест, биндинги, точки расширения) — [plugin-sdk.md](plugin-sdk.md).
---
## Открытые вопросы (найдено на self-review → роутинг в нужные доки)
Не теряем; решается в указанных документах.
- **Гейтинг data-plane, не только D-Bus.** Портал-прокси (§5) фильтрует D-Bus, но
доступ к **PipeWire (аудио)** и **Wayland (графика)** тоже надо гейтить
capability'ями (через bubblewrap-сокеты). → [security-privacy.md](security-privacy.md) + [plugin-sdk.md](plugin-sdk.md).
- **Экспорт объектов из песочницы.** Чтобы Assistant/Shell звали `IntentHandler`/UI
плагина, прокси должен разрешать плагину **OWN/экспорт** своих объектов под
ограниченным префиксом. → [security-privacy.md](security-privacy.md).
- **Приватное хранилище апа.** Capability `storage` должна давать апу приватную
writable-директорию в `/data` (монтирует bubblewrap). → [security-privacy.md](security-privacy.md).
- **Коллизия интентов.** Два плагина регистрируют пересекающиеся фразы — нужна
политика разрешения (приоритет / namespace / выбор пользователя). → [plugin-sdk.md](plugin-sdk.md) + домен D.
- **Целостность манифеста.** Для сторонней дистрибуции — подпись/верификация
манифеста (защита от подмены capabilities). → домен F + [security-privacy.md](security-privacy.md).
- **Быстрый канал для приборки.** Если цифровой щиток требует плавнее, чем потолок
шины — спроектировать выделенный канал. → [architecture.md](../architecture.md) §4 + домен E.
---
## Журнал решений (ipc)
| Решение | Выбор | Дата |
|---------|-------|------|
| Топология шины | системная шина устройства + фильтрующий прокси на ап (🟡 на подтверждение) | 2026-06-16 |
| Изоляция доступа апов | портал-паттерн: per-app dbus-proxy из манифеста | 2026-06-16 |
| Соглашения имён/версий | `ru.shturman.*`, версия в имени интерфейса | 2026-06-16 |